๐Ÿ˜Ž ๊ณต๋ถ€ํ•˜๋Š” ์ง•์ง•์•ŒํŒŒ์นด๋Š” ์ฒ˜์Œ์ด์ง€?

[v0.29]์˜์ƒ์ฒ˜๋ฆฌ_ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฒ€์ถœ๊ธฐ ๋ณธ๋ฌธ

๐Ÿ‘ฉ‍๐Ÿ’ป IoT (Embedded)/Image Processing

[v0.29]์˜์ƒ์ฒ˜๋ฆฌ_ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฒ€์ถœ๊ธฐ

์ง•์ง•์•ŒํŒŒ์นด 2022. 1. 15. 23:59
728x90
๋ฐ˜์‘ํ˜•

220115 ์ž‘์„ฑ

<๋ณธ ๋ธ”๋กœ๊ทธ๋Š” ๊ท€ํ‰์ด ์„œ์žฌ๋‹˜์˜ ๋ธ”๋กœ๊ทธ๋ฅผ ์ฐธ๊ณ ํ•ด์„œ ๊ณต๋ถ€ํ•˜๋ฉฐ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค>

https://bkshin.tistory.com/entry/OpenCV-27-%ED%8A%B9%EC%A7%95-%EB%94%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%84%B0-%EA%B2%80%EC%B6%9C%EA%B8%B0-SIFT-SURF-ORB?category=1148027 

 

OpenCV - 27. ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฒ€์ถœ๊ธฐ (SIFT, SURF, ORB)

์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฒ€์ถœ๊ธฐ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ ํฌ์ŠคํŒ… ์—ญ์‹œ 'ํŒŒ์ด์ฌ์œผ๋กœ ๋งŒ๋“œ๋Š” OpenCV ํ”„๋กœ์ ํŠธ(์ด์„ธ์šฐ ์ €)'๋ฅผ ์ •๋ฆฌํ•œ ๊ฒƒ์ž„์„ ๋ฐํž™๋‹ˆ๋‹ค. ์ฝ”๋“œ: github.com/BaekKyunShin/OpenCV_

bkshin.tistory.com

 

 

 

ํŠน์ง•์ ์ด๋ž€ ๋ง ๊ทธ๋Œ€๋กœ ์ด๋ฏธ์ง€์—์„œ ํŠน์ง•์ด ๋˜๋Š” ๋ถ€๋ถ„ == ํ‚คํฌ์ธํŠธ (keypoints)

 

1. ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ

: ์ด ํŠน์ง•์ ์€ ๊ฐ์ฒด์˜ ์ขŒํ‘œ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๊ทธ ์ฃผ๋ณ€ ํ”ฝ์…€๊ณผ์˜ ๊ด€๊ณ„์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ฐ€์ง„๋‹ค

: ๊ฐ€์žฅ ๋Œ€ํ‘œ์ ์ธ ๊ฒƒ์ด size์™€ angle ์†์„ฑ์ด๋ฉฐ, ์ฝ”๋„ˆ(corner)์ ์ธ ๊ฒฝ์šฐ ์ฝ”๋„ˆ์˜ ๊ฒฝ์‚ฌ๋„์™€ ๋ฐฉํ–ฅ๋„ ์†์„ฑ์œผ๋กœ ๊ฐ€์ง

: ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ(feature descriptor)๋ž€

ํŠน์ง•์  ์ฃผ๋ณ€ ํ”ฝ์…€์„ ์ผ์ •ํ•œ ํฌ๊ธฐ์˜ ๋ธ”๋ก์œผ๋กœ ๋‚˜๋ˆ„์–ด ๊ฐ ๋ธ”๋ก์— ์†ํ•œ ํ”ฝ์…€์˜ ๊ทธ๋ ˆ๋””์–ธํŠธ ํžˆ์Šคํ† ๊ทธ๋žจ์„ ๊ณ„์‚ฐํ•œ ๊ฒƒ

์ฃผ๋กœ ํŠน์ง•์  ์ฃผ๋ณ€์˜ ๋ฐ๊ธฐ, ์ƒ‰์ƒ, ๋ฐฉํ–ฅ, ํฌ๊ธฐ ๋“ฑ์˜ ์ •๋ณด๊ฐ€ ํฌํ•จ

: ์ถ”์ถœํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ๋”ฐ๋ผ ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ๊ฐ€ ์ผ๋ถ€ ๋‹ฌ๋ผ์งˆ ์ˆ˜๋Š” ์žˆ์Œ

: ์ผ๋ฐ˜์ ์œผ๋กœ ํŠน์ง•์  ์ฃผ๋ณ€์˜ ๋ธ”๋ก ํฌ๊ธฐ์— 8๋ฐฉํ–ฅ(์ƒ, ํ•˜, ์ขŒ, ์šฐ ๋ฐ ๋„ค ๋ฐฉํ–ฅ์˜ ๋Œ€๊ฐ์„ ) ๊ฒฝ์‚ฌ๋„๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Œ

: 4 x 4 ํฌ๊ธฐ์˜ ๋ธ”๋ก์ธ ๊ฒฝ์šฐ ํ•œ ๊ฐœ์˜ ํŠน์ง•์ ๋‹น 4 x 4 x 8 = 128๊ฐœ์˜ ๊ฐ’์„ ๊ฐ€์ง

 

keypoints, descriptors = detector.compute(image, keypoins, descriptors)

: ํŠน์ง•์ ์„ ์ „๋‹ฌํ•˜๋ฉด ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ๊ณ„์‚ฐํ•ด์„œ ๋ฐ˜ํ™˜

 

keypoints, descriptors = detector.detectAndCompute(image, mask, decriptors, useProvidedKeypoints)

: ํŠน์ง•์  ๊ฒ€์ถœ๊ณผ ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ณ„์‚ฐ์„ ํ•œ ๋ฒˆ์— ์ˆ˜ํ–‰

 

- image : ์ž…๋ ฅ ์ด๋ฏธ์ง€
- keypoints : ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ณ„์‚ฐ์„ ์œ„ํ•ด ์‚ฌ์šฉํ•  ํŠน์ง•์ 
- descriptors(optional) : ๊ณ„์‚ฐ๋œ ๋””์Šคํฌ๋ฆฝํ„ฐ
- mask(optional) : ํŠน์ง•์  ๊ฒ€์ถœ์— ์‚ฌ์šฉํ•  ๋งˆ์Šคํฌ
- useProvidedKeypoints(optional) : True์ธ ๊ฒฝ์šฐ ํŠน์ง•์  ๊ฒ€์ถœ์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์Œ

 

detector.compute() ํ•จ์ˆ˜

: ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ๊ตฌํ•จ

: keypoints ํŒŒ๋ผ๋ฏธํ„ฐ์— ํŠน์ง•์ ์„ ์ „๋‹ฌ

: ํŠน์ง•์  ๊ฒ€์ถœ๊ธฐ๋กœ ํŠน์ง•์ ์„ ํ•œ๋ฒˆ ๊ฒ€์ถœํ•˜๊ณ , ๊ทธ๋‹ค์Œ detector.compute() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉ

 

detector.detectAndCompute() ํ•จ์ˆ˜

: ํŠน์ง•์ ๊ณผ ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ๋™์‹œ์— ๊ณ„์‚ฐ

: ์ฒ˜์Œ๋ถ€ํ„ฐ detector.detectAndCompute() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ๋” ํŽธ๋ฆฌ

 

 

 

 

2. SIFT, SURF, ORB๋Š” ๋ชจ๋‘ ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ๊ตฌํ•ด์ฃผ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜

1) SIFT (Scale-Invariant Feature Transform)

: ๊ธฐ์กด์˜ ํ•ด๋ฆฌ์Šค ์ฝ”๋„ˆ ๊ฒ€์ถœ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ํฌ๊ธฐ ๋ณ€ํ™”์— ๋ฏผ๊ฐํ•œ ๋ฌธ์ œ๋ฅผ ๊ฐ€์ง

: SIFT๋Š” ์ด๋ฏธ์ง€ ํ”ผ๋ผ๋ฏธ๋“œ๋ฅผ ์ด์šฉํ•ด์„œ ํฌ๊ธฐ ๋ณ€ํ™”์— ๋”ฐ๋ฅธ ํŠน์ง•์  ๊ฒ€์ถœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐ

 

detector = cv2.xfeatures2d.SIFT_create(nfeatures, nOctaveLayers, contrastThreshold, edgeThreshold, sigma)
- nfeatures : ๊ฒ€์ถœ ์ตœ๋Œ€ ํŠน์ง• ์ˆ˜
- nOctaveLayers : ์ด๋ฏธ์ง€ ํ”ผ๋ผ๋ฏธ๋“œ์— ์‚ฌ์šฉํ•  ๊ณ„์ธต ์ˆ˜
- contrastThreshold : ํ•„ํ„ฐ๋งํ•  ๋นˆ์•ฝํ•œ ํŠน์ง• ๋ฌธํ„ฑ ๊ฐ’
- edgeThreshold : ํ•„ํ„ฐ๋งํ•  ์—ฃ์ง€ ๋ฌธํ„ฑ ๊ฐ’
- sigma : ์ด๋ฏธ์ง€ ํ”ผ๋ผ๋ฏธ๋“œ 0 ๊ณ„์ธต์—์„œ ์‚ฌ์šฉํ•  ๊ฐ€์šฐ์‹œ์•ˆ ํ•„ํ„ฐ์˜ ์‹œ๊ทธ๋งˆ ๊ฐ’

# SIFT๋กœ ํŠน์ง•์  ๋ฐ ๋””์Šคํฌ๋ฆฝํ„ฐ ์ถ”์ถœ
import cv2
import numpy as np

img = cv2.imread('img/house.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# SIFT ์ถ”์ถœ๊ธฐ ์ƒ์„ฑ
sift = cv2.xfeatures2d.SIFT_create()
# ํ‚ค ํฌ์ธํŠธ ๊ฒ€์ถœ๊ณผ ์„œ์ˆ ์ž ๊ณ„์‚ฐ
keypoints, descriptor = sift.detectAndCompute(gray, None)
print('keypoint:',len(keypoints), 'descriptor:', descriptor.shape)
print(descriptor)

# ํ‚ค ํฌ์ธํŠธ ๊ทธ๋ฆฌ๊ธฐ
img_draw = cv2.drawKeypoints(img, keypoints, None, \
                flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
# ๊ฒฐ๊ณผ ์ถœ๋ ฅ
cv2.imshow('SIFT', img_draw)
cv2.waitKey()
cv2.destroyAllWindows()

ํฌ๊ณ  ์ž‘์€ ์•„๋ฆ„๋‹ค์šด ํŠน์ง•์ 
ํŠน์ง•์  : 413๊ฐœ, ํŠน์ง•์  1๊ฐœ ๋‹น 128๊ฐœ์˜ ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฐ’ ์‚ฌ์šฉ

 

 

 

2) SURF (Speeded Up Robust Features)

: SIFT๋Š” ํฌ๊ธฐ ๋ณ€ํ™”์— ๋”ฐ๋ฅธ ํŠน์ง• ๊ฒ€์ถœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์ด๋ฏธ์ง€ ํ”ผ๋ผ๋ฏธ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์†๋„๊ฐ€ ๋Š๋ฆฌ๋‹ค

: SURF๋Š” ์ด๋ฏธ์ง€ ํ”ผ๋ผ๋ฏธ๋“œ ๋Œ€์‹  ํ•„ํ„ฐ์˜ ํฌ๊ธฐ๋ฅผ ๋ณ€ํ™”์‹œํ‚ค๋Š” ๋ฐฉ์‹์œผ๋กœ ์„ฑ๋Šฅ์„ ๊ฐœ์„ 

 

detector = cv2.xfeatures2d.SURF_create(hessianThreshold, nOctaves, nOctaveLayers, extended, upright)
- hessianThreshold(optional) : ํŠน์ง• ์ถ”์ถœ ๊ฒฝ๊ณ„ ๊ฐ’ (default=100)
- nOctaves(optional) : ์ด๋ฏธ์ง€ ํ”ผ๋ผ๋ฏธ๋“œ ๊ณ„์ธต ์ˆ˜ (default=3)
- extended(optional) : ๋””์Šคํฌ๋ฆฝํ„ฐ ์ƒ์„ฑ ํ”Œ๋ž˜๊ทธ (default=False), True: 128๊ฐœ, False: 64๊ฐœ
- upright(optional) : ๋ฐฉํ–ฅ ๊ณ„์‚ฐ ํ”Œ๋ž˜๊ทธ (default=False), True: ๋ฐฉํ–ฅ ๋ฌด์‹œ, False: ๋ฐฉํ–ฅ ์ ์šฉ

# SURF๋กœ ํŠน์ง•์  ๋ฐ ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ ์ถ”์ถœ
import cv2
import numpy as np

img = cv2.imread('img/house.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# SURF ์ถ”์ถœ๊ธฐ ์ƒ์„ฑ ( ๊ฒฝ๊ณ„:1000, ํ”ผ๋ผ๋ฏธ๋“œ:3, ์„œ์ˆ ์žํ™•์žฅ:True, ๋ฐฉํ–ฅ์ ์šฉ:True)
surf = cv2.xfeatures2d.SURF_create(1000, 3, True, True)

# ํ‚ค ํฌ์ธํŠธ ๊ฒ€์ถœ ๋ฐ ์„œ์ˆ ์ž ๊ณ„์‚ฐ
keypoints, desc = surf.detectAndCompute(gray, None)
print(desc.shape, desc)
# ํ‚คํฌ์ธํŠธ ์ด๋ฏธ์ง€์— ๊ทธ๋ฆฌ๊ธฐ
img_draw = cv2.drawKeypoints(img, keypoints, None, \
                flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

cv2.imshow('SURF', img_draw)
cv2.waitKey()
cv2.destroyAllWindows()

https://bkshin.tistory.com/entry/OpenCV-27-%ED%8A%B9%EC%A7%95-%EB%94%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%84%B0-%EA%B2%80%EC%B6%9C%EA%B8%B0-SIFT-SURF-ORB?category=1148027
https://bkshin.tistory.com/entry/OpenCV-27-%ED%8A%B9%EC%A7%95-%EB%94%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%84%B0-%EA%B2%80%EC%B6%9C%EA%B8%B0-SIFT-SURF-ORB?category=1148027

- opencv ๋ฒ„์ „์ด ์•ˆ๋งž์•„์„œ ์—๋Ÿฌ๊ฐ€ ๋‚œ๋‹ค

- ํŠน์ง•์  : 104๊ฐœ, ๊ฐ ํŠน์ง•์ ๋งˆ๋‹ค 128๊ฐœ์˜ ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฐ’ ์‚ฌ์šฉ

 

 

 

 

3) ORB (Oriented and Rotated BRIEF)

: ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฒ€์ถœ๊ธฐ ์ค‘ BRIEF(Binary Robust Independent Elementary Features)๋ผ๋Š” ๊ฒƒ์ด ์žˆ์Œ

: BRIEF๋Š” ํŠน์ง•์  ๊ฒ€์ถœ์€ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๋””์Šคํฌ๋ฆฝํ„ฐ ์ถ”์ถœ๊ธฐ

: BRIEF์— ๋ฐฉํ–ฅ๊ณผ ํšŒ์ „์„ ๊ณ ๋ คํ•˜๋„๋ก ๊ฐœ์„ ํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ๋ฐ”๋กœ ORB

: ํŠน์ง•์  ๊ฒ€์ถœ ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ FAST๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ํšŒ์ „๊ณผ ๋ฐฉํ–ฅ์„ ๊ณ ๋ คํ•˜๋„๋ก ๊ฐœ์„ ํ–ˆ์œผ๋ฉฐ ์†๋„๋„ ๋นจ๋ผ SIFT์™€ SURF์˜ ์ข‹์€ ๋Œ€์•ˆ์œผ๋กœ ์‚ฌ์šฉ

 

detector = cv2.ORB_create(nfeatures, scaleFactor, nlevels, edgeThreshold, firstLevel, WTA_K, scoreType, patchSize, fastThreshold)
- nfeatures(optional) : ๊ฒ€์ถœํ•  ์ตœ๋Œ€ ํŠน์ง• ์ˆ˜ (default=500)
- scaleFactor(optional) : ์ด๋ฏธ์ง€ ํ”ผ๋ผ๋ฏธ๋“œ ๋น„์œจ (default=1.2)
- nlevels(optional) : ์ด๋ฏธ์ง€ ํ”ผ๋ผ๋ฏธ๋“œ ๊ณ„์ธต ์ˆ˜ (default=8)
- edgeThreshold(optional) : ๊ฒ€์ƒ‰์—์„œ ์ œ์™ธํ•  ํ…Œ๋‘๋ฆฌ ํฌ๊ธฐ, patchSize์™€ ๋งž์ถœ ๊ฒƒ (default=31)
- firstLevel(optional) : ์ตœ์ดˆ ์ด๋ฏธ์ง€ ํ”ผ๋ผ๋ฏธ๋“œ ๊ณ„์ธต ๋‹จ๊ณ„ (default=0)
- WTA_K(optional) : ์ž„์˜ ์ขŒํ‘œ ์ƒ์„ฑ ์ˆ˜ (default=2)
- scoreType(optional) : ํŠน์ง•์  ๊ฒ€์ถœ์— ์‚ฌ์šฉํ•  ๋ฐฉ์‹

  • cv2.ORB_HARRIS_SCORE : ํ•ด๋ฆฌ์Šค ์ฝ”๋„ˆ ๊ฒ€์ถœ(default)
  • cv2.ORB_FAST_SCORE : FAST ์ฝ”๋„ˆ ๊ฒ€์ถœ

- patchSize(optional) : ๋””์Šคํฌ๋ฆฝํ„ฐ์˜ ํŒจ์น˜ ํฌ๊ธฐ (default=31)
- fastThreshold(optional) : FAST์— ์‚ฌ์šฉํ•  ์ž„๊ณ„ ๊ฐ’ (default=20)

# ORB๋กœ ํŠน์ง•์  ๋ฐ ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฒ€์ถœ
import cv2
import numpy as np

img = cv2.imread('img/house.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# ORB ์ถ”์ถœ๊ธฐ ์ƒ์„ฑ
orb = cv2.ORB_create()
# ํ‚ค ํฌ์ธํŠธ ๊ฒ€์ถœ๊ณผ ์„œ์ˆ ์ž ๊ณ„์‚ฐ
keypoints, descriptor = orb.detectAndCompute(img, None)
# ํ‚ค ํฌ์ธํŠธ ๊ทธ๋ฆฌ๊ธฐ
img_draw = cv2.drawKeypoints(img, keypoints, None, \
             flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
# ๊ฒฐ๊ณผ ์ถœ๋ ฅ
cv2.imshow('ORB', img_draw)
cv2.waitKey()
cv2.destroyAllWindows()

์˜ค์ž‰ ์ด๊ฒŒ ๋จธ๋žŒ

- ๋ญ”๊ฐ€ ์ข‹์•„๋ณด์ด์ง„ ์•Š๋Š”๋ฐ..

- none ์œผ๋กœ ํ•ด์„œ ๊ทธ๋Ÿฐ๊ฐ€

 

# ORB ์ถ”์ถœ๊ธฐ ์ƒ์„ฑ
orb = cv2.ORB_create(100, 1.2, 8, 31, 0, 2, cv2.ORB_FAST_SCORE, 31, 20)

- ์ด๊ฑฐ ์ถ”๊ฐ€ ํ–ˆ๋”๋‹ˆ..

๊ฒ€์ถœ ํŠน์ง• ์ตœ๋Œ€ 100๊ฐœ๋กœ ์ง€์ •, fast ์ฝ”๋„ˆ ๊ฒ€์ถœ

728x90
๋ฐ˜์‘ํ˜•
Comments