OpenCV-Python 은 두 장의 그림 을 자동 으로 전경 그림 으로 연결 합 니 다.

배경 설명
사진 의 전경 연결 은 이제 더 이상 신기 하지 않다.현재 의 스마트 카메라 와 휴대 전화 카 메 라 는 기본적으로 사진 자동 전경 연결 기능 을 가지 고 있 지만 일반적으로 촬영 자 에 게 설비 의 안정 과 단 방향의 이동 촬영 을 유지 하여 비교적 좋 은 연결 결 과 를 실현 하도록 요구한다.이 는 맞 춤 형 그림 사이 에 맞 춤 형 결과 의 정확성 과 완전 성 을 확보 하기 위해 비슷 한 구역 이 있어 야 하기 때문이다.본 고 는 주로 Python 과 OpenCV 라 이브 러 리 로 두 장의 그림 의 자동 조합 을 어떻게 실현 하 는 지 간단하게 설명 하고 먼저 두 장의 그림 조합 원 리 를 간단하게 소개 한다.
기본 원리
두 장의 그림 의 간단 한 조합 을 실현 하려 면 두 장의 그림 에서 비슷 한 점(적어도 네 개,homography 매트릭스 의 계산 은 최소 네 개의 점 이 필요 하기 때 문)을 찾 아야 한다.한 장의 그림 을 계산 하면 다른 그림 의 변환 행렬(homography 단일 응력 행렬)로 바 꿀 수 있다.이 행렬 로 그 그림 을 바 꾼 후 다른 그림 에 해당 하 는 위치 에 놓 습 니 다.이렇게 하면 간단 한 전경 조합 을 실현 할 수 있다.물론 맞 추 면 그림 이 겹 치기 때문에 그림 중첩 부분의 픽 셀 값 을 다시 계산 해 야 한다.그렇지 않 으 면 결과 가 보기 흉 할 것 이다.그래서 정리 해 보면 두 가지 절차 가 있 습 니 다.
1.두 장의 그림 에서 비슷 한 점 을 찾 아 행렬 을 계산한다.
2.한 장의 그림 을 다른 그림 의 적당 한 위치 로 바 꾸 고 중첩 구역 의 새로운 픽 셀 값 을 계산 합 니 다.(여기 가 바로 그림 융합 에 필요 한 전략 입 니 다)
구체 적 실현
유사 점 을 찾다
물론 비슷 한 점 을 수 동 으로 찾 을 수 있 지만 귀 찮 습 니 다.유사 점 이 많 거나 유사 점 에 대응 하 는 위치 가 정확 할 수록 얻 는 결과 가 좋 지만 사람의 육안 으로 찾 는 위 치 는 항상 오차 가 있 고 많은 점 을 찾 는 것 도 쉬 운 일이 아니다.그래서 똑똑 한 사람 이 유사 점 을 자동 으로 찾 는 알고리즘 을 설계 했다.여기 서 우 리 는 SIFT 알고리즘 을 사 용 했 고 OpenCV 도 우리 에 게 SIFT 알고리즘 의 인 터 페 이 스 를 제공 하기 때문에 우 리 는 스스로 힘 들 게 실현 할 필요 가 없다.다음은 두 장의 테스트 그림 의 원 도와 유사 점 을 찾 은 그림 이다.


그 중에서 빨간색 점 은 SIFT 알고리즘 이 찾 아 낸 유사 점 이 고 녹색 선 은 모든 비슷 한 점 에서 찾 아 낸 신뢰 도가 높 은 유사 점 을 나타 낸다.알고리즘 이 찾 아 낸 유사 점 이 꼭 100%정확 한 것 은 아니 기 때문이다.그 다음 에 이런 선별 한 유사 점 에 따라 행렬 을 바 꿀 수 있다.물론 OpenCV 도 해당 하 는 인 터 페 이 스 를 제공 하여 우리 의 계산 을 편리 하 게 하고 구체 적 인 코드 실현 도 OpenCV 의 Python tutorial 에서 찾 을 수 있다[1]
사진 조합
변환 행렬 을 계산 한 다음 두 번 째 단 계 는 계 산 된 변환 행렬 로 그 중의 한 장의 그림 을 변환 한 다음 에 변 경 된 그림 을 다른 그림 과 겹 쳐 중첩 구역 의 새로운 픽 셀 값 을 다시 계산한다.중첩 구역 의 픽 셀 값 을 계산 하 는 데 있어 서 사실 여러 가지 방법 으로 좋 은 융합 효 과 를 실현 할 수 있 습 니 다.여 기 는 가장 간단 하고 거 칠 지만 효과 도 좋 은 방식 을 사용 합 니 다.솔직히 말 하면 한 이미지 의 선형 그 라 데 이 션 을 실현 하 는 것 이다.겹 치 는 구역 에 대해 왼쪽 부분 에 가 깝 고 왼쪽 이미지 내용 을 많이 표시 하 며 오른쪽 부분 에 가 까 워 서 오른쪽 이미지 의 내용 을 많이 표시 하 는 것 이다.공식 적 으로 알파 가 픽 셀 점 가로 좌표 에서 좌우 중첩 구역 경계 가로 좌표 의 거 리 를 나타 낸다 고 가정 하면 새로운 픽 셀 값 은 new pixel=왼쪽 픽 셀 값 이다.× (1-알파)+오른쪽 픽 셀 값× alpha 。이렇게 하면 간단 한 융합 효 과 를 실현 할 수 있다.더 복잡 하거나 더 좋 은 효 과 를 실현 하려 면 multi-band 융합 을 검색 하고 시도 해 볼 수 있다.여 기 는 군더더기 에 불과 하 다.마지막 으로 실 현 된 결과 와 코드 를 동봉 하 니 참고 하 시기 바 랍 니 다.

Python 코드 는 다음 과 같 습 니 다:

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt

if __name__ == '__main__':
    top, bot, left, right = 100, 100, 0, 500
    img1 = cv.imread('test1.jpg')
    img2 = cv.imread('test2.jpg')
    srcImg = cv.copyMakeBorder(img1, top, bot, left, right, cv.BORDER_CONSTANT, value=(0, 0, 0))
    testImg = cv.copyMakeBorder(img2, top, bot, left, right, cv.BORDER_CONSTANT, value=(0, 0, 0))
    img1gray = cv.cvtColor(srcImg, cv.COLOR_BGR2GRAY)
    img2gray = cv.cvtColor(testImg, cv.COLOR_BGR2GRAY)
    sift = cv.xfeatures2d_SIFT().create()
    # find the keypoints and descriptors with SIFT
    kp1, des1 = sift.detectAndCompute(img1gray, None)
    kp2, des2 = sift.detectAndCompute(img2gray, None)
    # FLANN parameters
    FLANN_INDEX_KDTREE = 1
    index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
    search_params = dict(checks=50)
    flann = cv.FlannBasedMatcher(index_params, search_params)
    matches = flann.knnMatch(des1, des2, k=2)

    # Need to draw only good matches, so create a mask
    matchesMask = [[0, 0] for i in range(len(matches))]

    good = []
    pts1 = []
    pts2 = []
    # ratio test as per Lowe's paper
    for i, (m, n) in enumerate(matches):
        if m.distance < 0.7*n.distance:
            good.append(m)
            pts2.append(kp2[m.trainIdx].pt)
            pts1.append(kp1[m.queryIdx].pt)
            matchesMask[i] = [1, 0]

    draw_params = dict(matchColor=(0, 255, 0),
                       singlePointColor=(255, 0, 0),
                       matchesMask=matchesMask,
                       flags=0)
    img3 = cv.drawMatchesKnn(img1gray, kp1, img2gray, kp2, matches, None, **draw_params)
    plt.imshow(img3, ), plt.show()

    rows, cols = srcImg.shape[:2]
    MIN_MATCH_COUNT = 10
    if len(good) > MIN_MATCH_COUNT:
        src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
        dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
        M, mask = cv.findHomography(src_pts, dst_pts, cv.RANSAC, 5.0)
        warpImg = cv.warpPerspective(testImg, np.array(M), (testImg.shape[1], testImg.shape[0]), flags=cv.WARP_INVERSE_MAP)

        for col in range(0, cols):
            if srcImg[:, col].any() and warpImg[:, col].any():
                left = col
                break
        for col in range(cols-1, 0, -1):
            if srcImg[:, col].any() and warpImg[:, col].any():
                right = col
                break

        res = np.zeros([rows, cols, 3], np.uint8)
        for row in range(0, rows):
            for col in range(0, cols):
                if not srcImg[row, col].any():
                    res[row, col] = warpImg[row, col]
                elif not warpImg[row, col].any():
                    res[row, col] = srcImg[row, col]
                else:
                    srcImgLen = float(abs(col - left))
                    testImgLen = float(abs(col - right))
                    alpha = srcImgLen / (srcImgLen + testImgLen)
                    res[row, col] = np.clip(srcImg[row, col] * (1-alpha) + warpImg[row, col] * alpha, 0, 255)

        # opencv is bgr, matplotlib is rgb
        res = cv.cvtColor(res, cv.COLOR_BGR2RGB)
        # show the result
        plt.figure()
        plt.imshow(res)
        plt.show()
    else:
        print("Not enough matches are found - {}/{}".format(len(good), MIN_MATCH_COUNT))
        matchesMask = None
Reference
[1] OpenCV tutorial: https://docs.opencv.org/3.4.1/d1/de0/tutorial_py_feature_homography.html
OpenCV-Python 이 두 장의 그림 을 자동 으로 전경 그림 으로 연결 하 는 것 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 OpenCV 그림 이 자동 으로 전경 그림 으로 연결 되 는 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 부 탁 드 리 겠 습 니 다!

좋은 웹페이지 즐겨찾기