[OpenCV] 특징점 검출과 매칭

2025. 4. 4. 16:26·OpenCV

코너

코너의 특징

  • 평탄한 영역 & Edge 영역은 고유한 위치를 찾기 어려움
  • 따라서 변별력이 높고 영상의 이동, 회전 변환에 강인한 코너를 검출함

다양한 코너 검출 방법

해리스 코너 응답 함수 계산

cv2.cornerHarris(src, blockSize, ksize, k, dst=None, borderType=None) -> dst
  • src : 입력 단일 채널 8비트 또는 실수형 영상
  • blockSize : 코너 응답 함수 계산에서 고려할 이웃 픽셀 크기. 보통 2~5 [3 정도면 무난하게 사용 가능]
  • ksize : [미분을 위한] 소벨 연산자를 위한 커널 크기. 보통 3
  • k : 해리스 코너 검출 상수 [보통 0.04~0.06]
  • dst : 해리스 코너 응답 계수. src와 같은 크기의 행렬
  • borderType : 가장자리 픽셀 확장 방식. 기본값은 cv2.BORDER_DEFAULT

추적하기 좋은 특징 코너 검출

: goodFeaturesToTrack 함수의 경우 parameter가 9개나 된다. 이걸 외우기엔 정말 빡셀 것 같지만, 그 중 5개가 default 값이기 때문에 사실상 4개의 parameter만 정해주면 된다.

cv2.goodFeaturesToTrack(image, maxCorners, qualityLevel, minDistance, corners=None, mask=None, 
						blockSize=None, useHarrisDetector=None, k=None)-> corners
  • image : 8비트 또는 32비트 실수, 단일 채널 영상
  • maxCorners : 최대 코너 개수. maxCorners ≤ 0이면 무제한
  • qualityLevel : 코너점 결정을 위한 값. 보통 0.01 ~ 0.1
  • minDistance : 코너점 사이의 최소 거리
  • corners : 검출된 코너점 좌표 → 출력하려면 int type으로 전환한 뒤 출력해야 함 [기본형이 float32이기 때문]
  • mask : 마스크 영상
  • blockSize : 코너 검출을 위한 블록 크기. 기본값은 3
  • useHarrisDetector : 해리스 코너 방법 사용 여부. 기본값은 False
  • k : 해리스 코너 검출 시 사용할 k 값

FAST 코너 검출

cv2.FastFeatureDetector_create(, threshold=None, nonmaxSuppression=None, type=None) -> retval           
cv2.FastFeatureDetector.detect(image) -> keypoints
  • threshold : 중심 픽셀 값과 주변 픽셀 값과의 차이 임계값. 기본 값은 10
    [ex 16개 중 10개 이상의 픽셀이 기준점 P보다 밝으면 이 점 P를 Corner로 판단] … 30~60이 가장 이상적
  • nonmaxSuppression : 비최대 억제 수행 여부. 기본 값은 True
  • type : 코너 검출 방법. 기본값은 cv2.FAST_FEATURE_DETECTOR_TYPE_9_16
    → type은 변경하지 않는게 좋음
  • retval : FastFeatureDetector 객체
  • image : [입력] 그레이스케일 영상
  • keypoints : [출력] 검출된 코너점 정보. cv2.KeyPoint 객체를 담은 리스트. cv2.KeyPoint의 pt 멤버를 이용하여 코너 좌표를 추출. pt[0]은 x좌표, pt[1]은 y좌표

예시 코드

GTFF와 FAST 코너 검출 예제

import sys
import numpy as np
import cv2


src = cv2.imread('building.jpg', cv2.IMREAD_GRAYSCALE)

if src is None:
    print('Image load failed!')
    sys.exit()

tm = cv2.TickMeter()

# GFTT
tm.start()

corners = cv2.goodFeaturesToTrack(src, 400, 0.01, 10)

tm.stop()
print('GFTT: {}ms.'.format(tm.getTimeMilli()))

dst1 = cv2.cvtColor(src, cv2.COLOR_GRAY2BGR)

# 코너 부분을 빨간색 원으로 표시
if corners is not None:
    for i in range(corners.shape[0]):
        pt = (int(corners[i, 0, 0]), int(corners[i, 0, 1]))
        cv2.circle(dst1, pt, 5, (0, 0, 255), 2)

# FAST
tm.reset() # reset을 하지 않으면 위에서 측정한 시간이 추가됨
tm.start()

fast = cv2.FastFeatureDetector_create(60)
keypoints = fast.detect(src)

tm.stop()
print('FAST: {}ms.'.format(tm.getTimeMilli()))

dst2 = cv2.cvtColor(src, cv2.COLOR_GRAY2BGR)

for kp in keypoints:
    pt = (int(kp.pt[0]), int(kp.pt[1])) # pt[0], pt[1]은 각각 x좌표, y좌표
    cv2.circle(dst2, pt, 5, (0, 0, 255), 2)

cv2.imshow('src', src)
cv2.imshow('dst1', dst1)
cv2.imshow('dst2', dst2)
cv2.waitKey()

cv2.destroyAllWindows()

>>>
GFTT: 21.5232ms.
FAST: 0.5976ms

코너 검출 방법 성능 비교

특징점 검출

Harris, GFTT, FAST 코너의 문제점

  • 이동, 회전 변환에 강인
  • 크기 변환에 취약

→ 다양한 크기 관점에서 특징을 검출할 필요가 있다.

  • 특징점 [Feature Point] ~ 키포인트 ~ 관심점
  • 기술자 [Descriptor] ~ feature vector

크기 불변 특징점 검출 방법

  • SIFT, KAZE, AKAZE, ORB 등 다양한 특징점 검출 방법에서 스케일 스페이스, 이미지 피라미드를 구성하여 크기 불변 특징점을 검출

  • OpenCV 특징점 검출 클래스 : Feature2D 클래스와 파생 클래스

특징점 검출 알고리즘 객체 생성

cv2.SIFT_create(,...) -> retval
cv2.KAZE_create(,...) -> retval
cv2.AKAZE_create(,...) -> retval
cv2.ORB_create(,...) -> retval
  • retval : 각 특징점 검출 알고리즘 객체
  • 참고사항
    - 각각의 알고리즘은 고유한 파라미터를 인자로 받을 수 있음
    - 대부분의 인자는 기본값을 가지고 있으므로 함수 인자 없이 호출 가능

특징점 검출 함수

cv2.Feature2D.detect(image, mask=None) -> keypoints
  • image : 입력 영상
  • mask : 마스크 영상
  • keypoints : 검출된 특징점 정보. cv2.KeyPoints 객체의 리스트
    → pt [x좌표, y좌표 float type], size, angle 정보 포함

검출된 특징점 그리기 함수

cv2.drawKeypoints(image, keypoints, outImage, color=None, flags=None) -> outImage
  • image : 입력 영상
  • keypoints : 검출된 특징점 정보. cv2.KeyPoint 객체의 리스트
  • outImage : 출력 영상
  • color : 특징점 표현 색상. 기본값은 [-1,-1,-1,-1]이며 이 경우 임의의 색상으로 표현
  • flags : 특징점 표현 방법

예시 코드

# keypoints.py

import sys
import numpy as np
import cv2


# 영상 불러오기
src1 = cv2.imread('graf1.png', cv2.IMREAD_GRAYSCALE)
src2 = cv2.imread('graf3.png', cv2.IMREAD_GRAYSCALE)

if src1 is None or src2 is None:
    print('Image load failed!')
    sys.exit()

# 특징점 알고리즘 객체 생성 (KAZE, AKAZE, ORB 등)
feature = cv2.KAZE_create()
# feature = cv2.AKAZE_create()
# feature = cv2.ORB_create()

# 특징점 검출
kp1 = feature.detect(src1)
kp2 = feature.detect(src2)

print('# of kp1:', len(kp1))
print('# of kp2:', len(kp2))

# 검출된 특징점 출력 영상 생성
dst1 = cv2.drawKeypoints(src1, kp1, None,
                         flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
dst2 = cv2.drawKeypoints(src2, kp2, None,
                         flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

cv2.imshow('dst1', dst1)
cv2.imshow('dst2', dst2)
cv2.waitKey()
cv2.destroyAllWindows()

>>>
# of kp1: 3159
# of kp2: 3625

특징점 기술

기술자 [Descriptor, feature vector]

: 특징점 근방의 부분 영상을 표현하는 실수 또는 이진 벡터

  • OpenCV에서는 2차원 행렬로 표현

실수 기술자

  • 주로 특징점 부근 부분 영상의 방향 히스토그램을 사용

  • 보통 numpy.float32 자료형을 사용하여 실수 정보를 저장하는 방식
  • 실수 기술자를 사용하는 알고리즘 : SIFT, SURF, KAZE 등
  • 실수 기술자는 보통 L2-Norm을 사용하여 유사도 판단

이진 기술자

  • 이진 테스트를 이용하여 부분 영상의 특징을 기술

ex) 1과 2 비교 : 1이 더 밝기 때문에 1
      2와 3 비교 : 2가 더 어둡기 때문에 0
      1과 3 비교 : 1이 더 밝기 때문에 1
      → 따라서, 1,2,3이 겹치는 point P의 이진 정보는 101

  • 보통 numpy.uint8 자료형을 사용하여 비트 단위로 영상 특징 정보를 저장하는 방식
  • 이진 기술자를 사용하는 알고리즘 : AKAZE, ORB, BRIEF
  • 이진 기술자는 해밍 거리를 사용하여 유사도를 판단
    e.g.) d1=1011101, d2=1001001인 경우 해밍 거리는 2

함수

특징점 기술자 계산 함수

cv2.Feature2D.compute(image, keypoints, descriptors=None) ->keypoints, descriptors
  • image : 입력 영상
  • mask : 마스크 영상
  • keypoints : 검출된 특징점 정보. cv2.KeyPoint 객체의 리스트
  • descriptors : 특징점 기술자 행렬

특징점 검출 및 기술자 계산 함수

cv2.Feature2D.detectAndCompute(image, mask=None, descriptors=None) -> keyPoints, descriptors
  • image : 입력 영상
  • mask : 마스크 영상
  • keypoints : 검출된 특징점 정보. cv2.KeyPoint 객체의 리스트
  • descriptors : 특징점 기술자 행렬

예시 코드

import sys
import numpy as np
import cv2


# 영상 불러오기
src1 = cv2.imread('graf1.png', cv2.IMREAD_GRAYSCALE)
src2 = cv2.imread('graf3.png', cv2.IMREAD_GRAYSCALE)

if src1 is None or src2 is None:
    print('Image load failed!')
    sys.exit()

# 특징점 알고리즘 객체 생성 (KAZE, AKAZE, ORB 등)
# feature = cv2.SIFT_create()
feature = cv2.KAZE_create()
# feature = cv2.AKAZE_create()
# feature = cv2.ORB_create()

# 특징점 검출 및 기술자 계산
kp1 = feature.detect(src1)
_, desc1 = feature.compute(src1, kp1)

kp2, desc2 = feature.detectAndCompute(src2, None) # 위의 두 줄을 한꺼번에 연산

print('desc1.shape:', desc1.shape)
print('desc1.dtype:', desc1.dtype)
print('desc2.shape:', desc2.shape)
print('desc2.dtype:', desc2.dtype)

# 검출된 특징점 출력 영상 생성
dst1 = cv2.drawKeypoints(src1, kp1, None,
                         flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
dst2 = cv2.drawKeypoints(src2, kp2, None,
                         flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

cv2.imshow('dst1', dst1)
cv2.imshow('dst2', dst2)
cv2.waitKey()
cv2.destroyAllWindows()

>>>
[KAZE]
desc1.shape: (3159, 64)
desc1.dtype: float32
desc2.shape: (3625, 64)
desc2.dtype: float32

[AKAZE]
desc1.shape: (2418, 61)
desc1.dtype: uint8
desc2.shape: (2884, 61)
desc2.dtype: uint8
# AKAZE의 column은 무조건 61개

[ORB]
desc1.shape: (500, 32)
desc1.dtype: uint8
desc2.shape: (500, 32)
desc2.dtype: uint8

오른쪽 2개의 푸른색 막대 그래프를 보면, 왼쪽은 정확도에 관한 그래프이고, 오른쪽은 시간에 대한 그래프이다. 분석을 해보면 SIFT와 AKAZE의 정확도가 높고, 시간도 적게 걸린다는 것을 알 수 있다. 그에 반해 KAZE는 정확도는 높은 편이지만 시간이 오래걸리고, ORB는 시간은 거의 소모되지 않지만 정확도가 낮기 때문에 ORB, KAZE 보다는 SIFT나 AKAZE 알고리즘을 AKAZE보다는 SIFT 알고리즘을 사용하는 것이 조금 더 효율적인 성능을 보일 것으로 예상된다.

특징점 매칭

: 두 영상에서 추출한 특징점 기술자를 비교하여 서로 유사한 기술자 [descriptor]를 찾는 작업

특징 벡터 유사도 측정 방법

  • 이진 특징 벡터 : 해밍 거리 사용
  • 실수 특징 벡터 : L2-Norm 사용

OpenCV 특징점 매칭 클래스

  • BF : Brute-Force [전수 조사]
  • Flann : Fast Library for Approximate Nearest Neighbor [K-D Tree 사용]
    → 근사화를 하였기 때문에 완전 정확한 값은 아니지만, 연산 속도가 빠르다.

특징점 매칭 알고리즘 객체 생성

cv2.BFMatcher_create(, normType=None, crossCheck=None) -> retval
  • normType : 특징점 기술자 거리 계산 방식 지정. 기본값은 cv2.NORM_L2

  • crossCheck : 이 값이 True이면 양방향 매칭 결과가 같은 경우만 반환. 기본값은 False

특징점 검출 알고리즘 객체 생성

cv2.DescriptorMatcher.match(queryDescriptors, trainDescriptors, mask=None) -> matches
  • queryDescriptors : [기준 영상 특징점] 질의 기술자 행렬
  • trainDescriptors : [대칭 영상 특징점] 학습 기술자 행렬
  • mask : 매칭 진행 여부를 지정하는 행렬 마스크
  • matches : 매칭 결과. cv2.DMatch 객체의 리스트
cv2.DescriptorMatcher.match(queryDescriptors, trainDescriptors, k, mask=None, compactResult=None)
-> matches
  • queryDescriptors : [기준 영상 특징점] 질의 기술자 행렬
  • trainDescriptors : [대칭 영상 특징점] 학습 기술자 행렬
  • k : 질의 기술자에 대해 검출할 매칭 개수
  • mask : 매칭 진행 여부를 지정하는 행렬 마스크
  • compactResult : mask가 None이 아닐 때 사용되는 파라미터. 기본값은 False이며, 이 경우 결과 matches는 기준 영상 특징점과 같은 크기를 가짐
  • matches : 매칭 결과. cv2.DMatch 객체의 리스트

특징점 매칭 결과 영상 생성

cv2.drawMatches(img1, keypoints1, img2, keypoints2, matches1to2, outImg, matchColor=None, singlePointColor=None, 
				matchesMask=None, flags=None) -> outImg
  • img1, keypoints1 : 기준 영상과 기준 영상에서 추출한 특징점 정보
  • img2, keypoints2 : 대상 영상과 대상 영상에서 추출한 특징점 정보
  • matches1to2 : 매칭 정보. cv2.DMatch의 리스트
  • outImg : 출력 영상 → None 지정
  • matchColor : 매칭된 특징점과 직선 색상 → None 지정하면 Random 색상으로 출력
  • singlePointColor : 매칭되지 않은 특징점 색상
  • matchesMask : 매칭 정보를 선택하여 그릴 때 사용할 마스크
  • flags : 매칭 정보 그리기 방법. 기본값은 cv2.DRAW_MATCHES_FLAGS_DEFAULT

예시 코드

# matching.py

import sys
import numpy as np
import cv2


# 영상 불러오기
src1 = cv2.imread('graf1.png', cv2.IMREAD_GRAYSCALE)
src2 = cv2.imread('graf3.png', cv2.IMREAD_GRAYSCALE)

if src1 is None or src2 is None:
    print('Image load failed!')
    sys.exit()

# 특징점 알고리즘 객체 생성 (KAZE, AKAZE, ORB 등)
feature = cv2.KAZE_create()
# feature = cv2.AKAZE_create()
# feature = cv2.ORB_create()

# 특징점 검출 및 기술자 계산
kp1, desc1 = feature.detectAndCompute(src1, None)
kp2, desc2 = feature.detectAndCompute(src2, None)

# 특징점 매칭
matcher = cv2.BFMatcher_create()
#matcher = cv2.BFMatcher_create(cv2.NORM_HAMMING)
matches = matcher.match(desc1, desc2)

print('# of kp1:', len(kp1))
print('# of kp2:', len(kp2))
print('# of matches:', len(matches))

# 특징점 매칭 결과 영상 생성
dst = cv2.drawMatches(src1, kp1, src2, kp2, matches, None)

cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()

>>>
# of kp1: 3159
# of kp2: 3625
# of matches: 3159

좋은 매칭 선별

좋은 매칭 선별 방법 #1

: 위에서 특징점 매칭 결과를 보면 알겠지만, 모든 점들을 이었기 때문에 원본 영상이 안보일 뿐더러 어떤점이 매칭이 되었는지 확인하기가 매우 힘들다. 따라서 좋은 매칭 선별 방법을 사용해서 매칭들 중 일부만 매칭해서 특징점을 선별한다.

  • 가장 좋은 매칭 결과에서 distance 값이 작은 것 N개를 사용
  • cv2.DMatch.distance 값을 기준으로 정렬 후 상위 N개 선택
import sys
import numpy as np
import cv2


# 영상 불러오기
src1 = cv2.imread('graf1.png', cv2.IMREAD_GRAYSCALE)
src2 = cv2.imread('graf3.png', cv2.IMREAD_GRAYSCALE)

if src1 is None or src2 is None:
    print('Image load failed!')
    sys.exit()

# 특징점 알고리즘 객체 생성 (KAZE, AKAZE, ORB 등)
feature = cv2.KAZE_create()
# feature = cv2.AKAZE_create()
# feature = cv2.ORB_create()

# 특징점 검출 및 기술자 계산
kp1, desc1 = feature.detectAndCompute(src1, None)
kp2, desc2 = feature.detectAndCompute(src2, None)

# 특징점 매칭
matcher = cv2.BFMatcher_create()
#matcher = cv2.BFMatcher_create(cv2.NORM_HAMMING)
matches = matcher.match(desc1, desc2)

# 좋은 매칭 결과 선별
matches = sorted(matches, key=lambda x: x.distance)
good_matches = matches[:80]

print('# of kp1:', len(kp1))
print('# of kp2:', len(kp2))
print('# of matches:', len(matches))
print('# of good_matches:', len(good_matches))

# 특징점 매칭 결과 영상 생성
dst = cv2.drawMatches(src1, kp1, src2, kp2, good_matches, None)

cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()

>>>
# of kp1: 3159
# of kp2: 3625
# of matches: 3159
# of good_matches: 80

좋은 매칭 선별 방법 #2

  • 가장 좋은 매칭 결과의 distance 값과 두 번째로 좋은 매칭 결과의 distance 값의 비율을 계산
  • 이 비율이 임계값보다 작으면 선택

import sys
import numpy as np
import cv2


# 영상 불러오기
src1 = cv2.imread('graf1.png', cv2.IMREAD_GRAYSCALE)
src2 = cv2.imread('graf3.png', cv2.IMREAD_GRAYSCALE)

if src1 is None or src2 is None:
    print('Image load failed!')
    sys.exit()

# 특징점 알고리즘 객체 생성 (KAZE, AKAZE, ORB 등)
feature = cv2.KAZE_create()
#feature = cv2.AKAZE_create()
#feature = cv2.ORB_create()

# 특징점 검출 및 기술자 계산
kp1, desc1 = feature.detectAndCompute(src1, None)
kp2, desc2 = feature.detectAndCompute(src2, None)

# 특징점 매칭
matcher = cv2.BFMatcher_create()
#matcher = cv2.BFMatcher_create(cv2.NORM_HAMMING)
matches = matcher.knnMatch(desc1, desc2, 2)

# 좋은 매칭 결과 선별
good_matches = []
for m in matches:
    if m[0].distance / m[1].distance < 0.7:
        good_matches.append(m[0])

print('# of kp1:', len(kp1))
print('# of kp2:', len(kp2))
print('# of matches:', len(matches))
print('# of good_matches:', len(good_matches))

# 특징점 매칭 결과 영상 생성
dst = cv2.drawMatches(src1, kp1, src2, kp2, good_matches, None)

cv2.namedWindow('dst', cv2.WINDOW_NORMAL)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()

호모그래피와 영상 매칭

: 두 평면 사이의 투시 변환 [Perspective transform]

  • 8DOF ... 최소 4개의 대응점 좌표가 필요하다

호모그래피 계산 함수

cv2.findHomography(srcPoints, dstPoints, method=None, ransacReprojThreshold=None, mask=None, maxIters=None,
				confidence=NOne) -> retval, mask
  • srcPoints : 입력 점 좌표
  • dstPoints : 결과 점 좌표
  • method : 호모그래피 행렬 계산 방법. 0, LMEDS, RANSAC, RHO 중 선택. 기본값은 0이며, 이상치가 있을 경우 RANSAC, RHO 방법 권장 [cv2.RANSAC]
  • ransacReprojThreshold : RANSAC 재투영 에러 허용치. 기본값은 3

RANSAC : RANdom SAmple Consensus
= 이상치 [Outlier]가 많은 원본 데이터로부터 모델 파라미터를 예측하는 방법

  • maxIters : RANSAC 최대 반복 횟수. 기본값은 2000
  • retval : 호모그래피 행렬
  • mask : 출력 마스크 행렬. RANSAC, RHO 방법 사용시 Inlier로 사용된 점들을 1로 표시한 행렬

예시 코드

# homography.py

import sys
import numpy as np
import cv2

# Load two images to be used for homography
src1 = cv2.imread('box.png', cv2.IMREAD_GRAYSCALE)
src2 = cv2.imread('box_in_scene.png', cv2.IMREAD_GRAYSCALE)

# Check if images are loaded successfully
if src1 is None or src2 is None:
    print('Image load failed!')
    sys.exit()

# Create a feature point algorithm object (KAZE, AKAZE, ORB, etc.)
feature = cv2.KAZE_create()
# Alternatively, you can use AKAZE or ORB instead of KAZE
# feature = cv2.AKAZE_create()
# feature = cv2.ORB_create()

# Detect feature points and calculate descriptors for each image
kp1, desc1 = feature.detectAndCompute(src1, None)
kp2, desc2 = feature.detectAndCompute(src2, None)

# Use a feature point matcher (Brute-Force Matcher) to find matches between descriptors
matcher = cv2.BFMatcher_create()
matches = matcher.match(desc1, desc2)

# Sort matches based on their distances and select the top 80 matches
matches = sorted(matches, key=lambda x: x.distance)
good_matches = matches[:80]

# Print information about the number of feature points and matches
print('# of kp1:', len(kp1))
print('# of kp2:', len(kp2))
print('# of matches:', len(matches))
print('# of good_matches:', len(good_matches))

# Extract coordinates of feature points from the good matches
pts1 = np.array([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2).astype(np.float32)
pts2 = np.array([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2).astype(np.float32)

# Calculate homography matrix using RANSAC
H, _ = cv2.findHomography(pts1, pts2, cv2.RANSAC)

# Display matching results and draw the reference image area using homography
dst = cv2.drawMatches(src1, kp1, src2, kp2, good_matches, None,
                      flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)

# Get the dimensions of the reference image
(h, w) = src1.shape[:2]

# Define the four corners of the reference image
corners1 = np.array([[0, 0], [0, h-1], [w-1, h-1], [w-1, 0]]).reshape(-1, 1, 2).astype(np.float32)

# Transform the corners using the calculated homography matrix
corners2 = cv2.perspectiveTransform(corners1, H)
# Shift the transformed corners to match the second image
corners2 = corners2 + np.float32([w, 0])

# Draw the polygon representing the reference image area in the second image
cv2.polylines(dst, [np.int32(corners2)], True, (0, 255, 0), 2, cv2.LINE_AA)

# Display the result
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()

이미지 스티칭

: 동일 장면의 사진을 자연스럽게 붙여서 한 장의 사진으로 만드는 기술

이미지 스티칭 객체 생성

cv2.Stitcher_create(, mode=None) -> retval
  • mode : 스티칭 모드. cv2.PANORAMA 또는 cv2.SCANS 중 하나 선택. 기본값은 cv2.PANORAMA
  • retval : cv2.Stitcher 클래스 객체

이미지 스티칭 함수

cv2.Stitcher.stitch(images, pano=None) -? retval, pano
  • images : 입력 영상 리스트
  • retval : 성공하면 cv2.Stitcher_OK
  • pano : 파노라마 영상

예시 코드

# stitching.py

import sys
import numpy as np
import cv2


img_names = ['img1.jpg', 'img2.jpg', 'img3.jpg']

imgs = []
for name in img_names:
    img = cv2.imread(name)

    if img is None:
        print('Image load failed!')
        sys.exit()

    imgs.append(img)

stitcher = cv2.Stitcher_create()
status, dst = stitcher.stitch(imgs)

if status != cv2.Stitcher_OK:
    print('Stitch failed!')
    sys.exit()

cv2.imwrite('output.jpg', dst)

cv2.namedWindow('dst', cv2.WINDOW_NORMAL) # 창 크기 조절
for i in range(3):
    cv2.imshow('img{}'.format(i+1),imgs[i])
    
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()

OpenCV 끝!!

 

'OpenCV' 카테고리의 다른 글

[OpenCV] 영상 분할과 객체 검출  (0) 2025.04.04
[OpenCV] 이진 영상 처리  (0) 2025.04.04
[OpenCV] 영상의 특징 추출  (0) 2025.04.04
[OpenCV] 기하학적 변환  (0) 2025.04.04
[OpenCV] 필터링  (1) 2025.04.04
'OpenCV' 카테고리의 다른 글
  • [OpenCV] 영상 분할과 객체 검출
  • [OpenCV] 이진 영상 처리
  • [OpenCV] 영상의 특징 추출
  • [OpenCV] 기하학적 변환
HJo0on
HJo0on
Hyunjoon
  • HJo0on
    Visionery
    HJo0on
  • 전체
    오늘
    어제
    • 분류 전체보기 (57)
      • Baekjoon (17)
      • OpenCV (9)
      • Paper Review (20)
        • Baseline (4)
        • 3D Human Reconstruction (7)
        • 3D Gaussian Splatting (1)
        • Neural Radiance Field (1)
        • Music-to-Dance (6)
        • Video Generation (1)
      • Pose Estimation (3)
      • Object Detection (2)
      • Segmentation (3)
      • ETC (1)
      • Reinforcement Learning (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • Velog
    • Github
  • 공지사항

  • 인기 글

  • 태그

    object detection
    computer vision
    BFS
    Human pose estimation
    C++
    pose estimation
    티스토리챌린지
    pifu
    sam
    DP
    6DOF
    mesh
    graph
    math
    3dgs
    3d human reconstruction
    Diffusion
    opencv
    grounding dino
    BAEKJOON
    Dino
    3d vision
    Deep learning
    segmentation
    novel-view synthesis
    Python
    music-to-dance
    PAPER
    reinforcement learning
    오블완
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
HJo0on
[OpenCV] 특징점 검출과 매칭
상단으로

티스토리툴바