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

[v0.28]์˜์ƒ์ฒ˜๋ฆฌ_์ด๋ฏธ์ง€์˜ ํŠน์ง•์ , ํŠน์ง•์  ๊ฒ€์ถœ๊ธฐ ๋ณธ๋ฌธ

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

[v0.28]์˜์ƒ์ฒ˜๋ฆฌ_์ด๋ฏธ์ง€์˜ ํŠน์ง•์ , ํŠน์ง•์  ๊ฒ€์ถœ๊ธฐ

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

220115 ์ž‘์„ฑ

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

https://bkshin.tistory.com/entry/OpenCV-26-%EC%9D%B4%EB%AF%B8%EC%A7%80%EC%9D%98-%ED%8A%B9%EC%A7%95%EA%B3%BC-%ED%82%A4-%ED%8F%AC%EC%9D%B8%ED%8A%B8?category=1148027 

 

OpenCV - 26. ์ด๋ฏธ์ง€์˜ ํŠน์ง•์ (Keypoints)๊ณผ ํŠน์ง•์  ๊ฒ€์ถœ๊ธฐ(Keypoints detector)

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

bkshin.tistory.com

 

 

 

 

์ด๋ฏธ์ง€ ๊ฒ€์ถœํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ด๋ฏธ์ง€์˜ ํŠน์ง•์  ์ฐพ์•„์•ผํ•จ!

 

 

1. ์ด๋ฏธ์ง€ ํŠน์ง•์ 

: ์ด๋ฏธ์ง€์—์„œ ํŠน์ง•์ด ๋˜๋Š” ๋ถ€๋ถ„

: ์ด๋ฏธ์ง€๋ผ๋ฆฌ ์„œ๋กœ ๋งค์นญ์ด ๋˜๋Š”์ง€ ํ™•์ธ์„ ํ•  ๋•Œ ๊ฐ ์ด๋ฏธ์ง€์—์„œ์˜ ํŠน์ง•์ด ๋˜๋Š” ๋ถ€๋ถ„๋ผ๋ฆฌ ๋น„๊ต

: ์ด๋ฏธ์ง€ ๋งค์นญ ์‹œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ ํŠน์ง•์ 

: ํŠน์ง•์ ์€ ์˜์–ด๋กœ ํ‚ค ํฌ์ธํŠธ(Keypoints)

: ๋ณดํ†ต ํŠน์ง•์ ์ด ๋˜๋Š” ๋ถ€๋ถ„์€ ๋ฌผ์ฒด์˜ ๋ชจ์„œ๋ฆฌ๋‚˜ ์ฝ”๋„ˆ

: ๋Œ€๋ถ€๋ถ„์˜ ํŠน์ง•์  ๊ฒ€์ถœ์„ ์ฝ”๋„ˆ ๊ฒ€์ถœ์„ ๋ฐ”ํƒ•์œผ๋กœ ํ•จ

 

 

 

 

2. ํ•ด๋ฆฌ์Šค ์ฝ”๋„ˆ ๊ฒ€์ถœ (Harris Corner Detection)

: ๋ฌผ์ฒด๋ฅผ ์ธ์‹ํ•  ๋•Œ ๋ฌผ์ฒด์˜ ์ฝ”๋„ˆ ๋ถ€๋ถ„์— ๊ด€์‹ฌ์„ ๋‘ 

: ์ด๋ฏธ์ง€ ์ƒ์˜ ์ฝ”๋„ˆ๋ฅผ ์ž˜ ์ฐพ์•„๋‚ธ๋‹ค๋ฉด ๋ฌผ์ฒด๋ฅผ ๋ณด๋‹ค ์‰ฝ๊ฒŒ ์ธ์‹

: ์ฝ”๋„ˆ๋ฅผ ๊ฒ€์ถœํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•

: ํ•ด๋ฆฌ์Šค ์ฝ”๋„ˆ ๊ฒ€์ถœ์€ ์†Œ๋ฒจ(Sobel) ๋ฏธ๋ถ„์œผ๋กœ ๊ฒฝ๊ณ—๊ฐ’์„ ๊ฒ€์ถœํ•˜๋ฉด์„œ ๊ฒฝ๊ณ—๊ฐ’์˜ ๊ฒฝ์‚ฌ๋„ ๋ณ€ํ™”๋Ÿ‰์„ ์ธก์ •ํ•˜์—ฌ

๋ณ€ํ™”๋Ÿ‰์ด ์ˆ˜์ง, ์ˆ˜ํ‰, ๋Œ€๊ฐ์„  ๋ฐฉํ–ฅ์œผ๋กœ ํฌ๊ฒŒ ๋ณ€ํ™”ํ•˜๋Š” ๊ฒƒ์„ ์ฝ”๋„ˆ๋กœ ํŒ๋‹จ

dst = cv2.cornerHarris(src, blockSize, ksize, k, dst, borderType)
- src : ์ž…๋ ฅ ์ด๋ฏธ์ง€, ๊ทธ๋ ˆ์ด ์Šค์ผ€์ผ
- blockSize : ์ด์›ƒ ํ”ฝ์…€ ๋ฒ”์œ„
- ksize : ์†Œ๋ฒจ ๋ฏธ๋ถ„ ํ•„ํ„ฐ ํฌ๊ธฐ
- k(optional) : ์ฝ”๋„ˆ ๊ฒ€์ถœ ์ƒ์ˆ˜ (๋ณดํ†  0.04~0.06)
- dst(optional) : ์ฝ”๋„ˆ ๊ฒ€์ถœ ๊ฒฐ๊ณผ (src์™€ ๊ฐ™์€ ํฌ๊ธฐ์˜ 1 ์ฑ„๋„ ๋ฐฐ์—ด, ๋ณ€ํ™”๋Ÿ‰์˜ ๊ฐ’, ์ง€์—ญ ์ตœ๋Œ€ ๊ฐ’์ด ์ฝ”๋„ˆ์ ์„ ์˜๋ฏธ)
- borderType(optional) : ์™ธ๊ณฝ ์˜์—ญ ๋ณด์ • ํ˜•์‹

# ํ•ด๋ฆฌ์Šค ์ฝ”๋„ˆ ๊ฒ€์ถœ
import cv2
import numpy as np

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

# ํ•ด๋ฆฌ์Šค ์ฝ”๋„ˆ ๊ฒ€์ถœ ---โ‘ 
corner = cv2.cornerHarris(gray, 2, 3, 0.04)

# ๋ณ€ํ™”๋Ÿ‰ ๊ฒฐ๊ณผ์˜ ์ตœ๋Œ€๊ฐ’ 10% ์ด์ƒ์˜ ์ขŒํ‘œ ๊ตฌํ•˜๊ธฐ ---โ‘ก
coord = np.where(corner > 0.1* corner.max())
coord = np.stack((coord[1], coord[0]), axis=-1)

# ์ฝ”๋„ˆ ์ขŒํ‘œ์— ๋™๊ทธ๋ฆฌ๋ฏธ ๊ทธ๋ฆฌ๊ธฐ ---โ‘ข
for x, y in coord:
    cv2.circle(img, (x,y), 5, (0,0,255), 1, cv2.LINE_AA)

# ๋ณ€ํ™”๋Ÿ‰์„ ์˜์ƒ์œผ๋กœ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ 0~255๋กœ ์ •๊ทœํ™” ---โ‘ฃ
corner_norm = cv2.normalize(corner, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)

# ํ™”๋ฉด์— ์ถœ๋ ฅ
corner_norm = cv2.cvtColor(corner_norm, cv2.COLOR_GRAY2BGR)
merged = np.hstack((corner_norm, img))
cv2.imshow('Harris Corner', merged)
cv2.waitKey()
cv2.destroyAllWindows()

ํ•ด๋ฆฌ์Šค ์ฝ”๋„ˆ ๊ฒ€์ถœ ๋กœ ์ฝ”๋„ˆ ๊ฒ€์ถœํ•˜๊ธฐ !! ์ฝ”๋„ˆ๊ฐ€ ๋นจ๊ฐ„ ๋™๊ทธ๋ผ๋ฏธ!

: ์˜ค๋ฅธ์ชฝ ์ด๋ฏธ์ง€๋Š” ํ•ด๋ฆฌ์Šค ์ฝ”๋„ˆ ๊ฒ€์ถœ์„ ์‹คํ–‰ํ•˜์—ฌ ๊ทธ ๊ฒฐ๊ณผ์˜ ์ตœ๋Œ€ ๊ฐ’์˜ 10% ์ด์ƒ์ธ ์ขŒํ‘œ์—๋งŒ ๋นจ๊ฐ„์ƒ‰ ๋™๊ทธ๋ผ๋ฏธ ํ‘œ์‹œ

: ์ฝ”๋„ˆ์—์„œ ํ”ฝ์…€์˜ ๋ณ€ํ™”๋Ÿ‰์ด ๊ฐ€์žฅ ํฌ๋‹ค

: cv2.cornerHarris() ํ•จ์ˆ˜์˜ ๋ณ€ํ™˜ ๊ฒฐ๊ณผ๋Š” ์ž…๋ ฅ ์ด๋ฏธ์ง€์™€ ํฌ๊ธฐ๊ฐ€ ๊ฐ™์€ 1์ฐจ์› ๋ฐฐ์—ด

: ๊ฒฐ๊ณผ ๊ฐ’์˜ ์ง€์—ญ ์ตœ๋Œ€ ๊ฐ’(Local Maximum)์€ ์ฝ”๋„ˆ๋ฅผ ์˜๋ฏธ

 

: ์™ผ์ชฝ ์ด๋ฏธ์ง€๋Š” ํ•ด๋ฆฌ์Šค ์ฝ”๋„ˆ ๊ฒ€์ถœ ๊ฒฐ๊ณผ๋ฅผ 0~255๋กœ ์ •๊ทœํ™”ํ•˜์—ฌ ๋‚˜ํƒ€๋‚ธ ๊ฒƒ

: ์˜ค๋ฅธ์ชฝ ์ด๋ฏธ์ง€์—์„œ ๋นจ๊ฐ„์ƒ‰ ๋™๊ทธ๋ผ๋ฏธ๊ฐ€ ํ‘œ์‹œ๋˜์–ด ์žˆ๋Š” ์ฝ”๋„ˆ ๋ถ€๋ถ„์ด ์™ผ์ชฝ ์ด๋ฏธ์ง€์—์„œ๋„ ๊ฐ€์žฅ ์ง™๊ฒŒ ํ‘œ์‹œ๋จ

 

 

 

 

3. ์‹œ-ํ† ๋งˆ์‹œ ๊ฒ€์ถœ (Shi & Tomasi Detection)

: ํ•ด๋ฆฌ์Šค ์ฝ”๋„ˆ ๊ฒ€์ถœ์„ ์ข€ ๋” ๊ฐœ์„ ํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜

 

corners = cv2.goodFeaturesToTrack(img, maxCorners, qualityLevel, minDistance, corners, mask, blockSize, useHarrisDetector, k)
- img : ์ž…๋ ฅ ์ด๋ฏธ์ง€
- maxCorners : ์–ป๊ณ  ์‹ถ์€ ์ฝ”๋„ˆ์˜ ๊ฐœ์ˆ˜, ๊ฐ•ํ•œ ๊ฒƒ ์ˆœ์œผ๋กœ
- qualityLevel : ์ฝ”๋„ˆ๋กœ ํŒ๋‹จํ•  ์Šค๋ ˆ์‹œํ™€๋“œ ๊ฐ’
- minDistance : ์ฝ”๋„ˆ ๊ฐ„ ์ตœ์†Œ ๊ฑฐ๋ฆฌ
- mask(optional) : ๊ฒ€์ถœ์— ์ œ์™ธํ•  ๋งˆ์Šคํฌ
- blockSize(optional)=3 : ์ฝ”๋„ˆ ์ฃผ๋ณ€ ์˜์—ญ์˜ ํฌ๊ธฐ

- useHarrisDetector(optional)=False : ์ฝ”๋„ˆ ๊ฒ€์ถœ ๋ฐฉ๋ฒ• ์„ ํƒ (True: ํ•ด๋ฆฌ์Šค ์ฝ”๋„ˆ ๊ฒ€์ถœ, False: ์‹œ์™€ ํ† ๋งˆ์‹œ ์ฝ”๋„ˆ ๊ฒ€์ถœ)

- k(optional) : ํ•ด๋ฆฌ์Šค ์ฝ”๋„ˆ ๊ฒ€์ถœ ๋ฐฉ๋ฒ•์— ์‚ฌ์šฉํ•  k ๊ณ„์ˆ˜

- corners : ์ฝ”๋„ˆ ๊ฒ€์ถœ ์ขŒํ‘œ ๊ฒฐ๊ณผ, N x 1 x 2 ํฌ๊ธฐ์˜ ๋ฐฐ์—ด, ์‹ค์ˆ˜ ๊ฐ’์ด๋ฏ€๋กœ ์ •์ˆ˜๋กœ ๋ณ€ํ˜• ํ•„์š”

# ์‹œ์™€ ํ† ๋งˆ์‹œ ์ฝ”๋„ˆ ๊ฒ€์ถœ
import cv2
import numpy as np

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

# ์‹œ-ํ† ๋งˆ์Šค์˜ ์ฝ”๋„ˆ ๊ฒ€์ถœ ๋ฉ”์„œ๋“œ
corner1 = cv2.goodFeaturesToTrack(gray, 80, 0.01, 10)
# ์‹ค์ˆ˜ ์ขŒํ‘œ๋ฅผ ์ •์ˆ˜ ์ขŒํ‘œ๋กœ ๋ณ€ํ™˜
corner1 = np.int32(corner1)

# ์ขŒํ‘œ์— ๋™๊ทธ๋ผ๋ฏธ ํ‘œ์‹œ
for corner in corner1:
    x, y = corner[0]
    cv2.circle(img, (x, y), 5, (0,0,255), 1, cv2.LINE_AA)

# ---------------------------------------------------- 
# ํ•ด๋ฆฌ์Šค ์ฝ”๋„ˆ ๊ฒ€์ถœ ---โ‘ 
corner2 = cv2.cornerHarris(gray, 2, 3, 0.04)

# ๋ณ€ํ™”๋Ÿ‰ ๊ฒฐ๊ณผ์˜ ์ตœ๋Œ€๊ฐ’ 10% ์ด์ƒ์˜ ์ขŒํ‘œ ๊ตฌํ•˜๊ธฐ ---โ‘ก
coord = np.where(corner2 > 0.1* corner2.max())
coord = np.stack((coord[1], coord[0]), axis=-1)

# ์ฝ”๋„ˆ ์ขŒํ‘œ์— ๋™๊ทธ๋ฆฌ๋ฏธ ๊ทธ๋ฆฌ๊ธฐ ---โ‘ข
for x, y in coord:
    cv2.circle(img1, (x,y), 5, (0,0,255), 1, cv2.LINE_AA)

merged = np.hstack((img, img1))

cv2.imshow('Shi & Tomasi Detection, Harris Corner Detection', merged)
cv2.waitKey()
cv2.destroyAllWindows()

์‹œ-ํ† ๋งˆ์‹œ ๊ฒ€์ถœ ์™€ ํ•ด๋ฆฌ์Šค ์ฝ”๋„ˆ ๊ฒ€์ถœ ๋น„๊ตํ•˜๊ธฐ

: ์‹œ-ํ† ๋งˆ์‹œ ๊ฒ€์ถœ๊ฐ€ ๋” ๋งŽ์€ ์ฝ”๋„ˆ ๊ฒ€์ถœ๋จ

 

 

 

 

4. ํŠน์ง•์  ๊ฒ€์ถœ๊ธฐ

: ๊ฐ๊ฐ์˜ ํŠน์ง•์ ๋„ ์ขŒํ‘œ(x, y) ์ด์™ธ์— ๋‹ค์–‘ํ•œ ์ •๋ณด๋ฅผ ๊ฐ€์ง„๋‹ค

: ํ•ด๋ฆฌ์Šค ์ฝ”๋„ˆ ๊ฒ€์ถœ๊ณผ ์‹œ-ํ† ๋งˆ์‹œ ๊ฒ€์ถœ์˜ ํ•จ์ˆ˜ ๋ฐ˜ํ™˜ ๊ฒฐ๊ณผ๋Š” ๋‹จ์ง€ ํŠน์ง•์ ์˜ ์ขŒํ‘œ

: ํŠน์ง•์  ๊ฒ€์ถœ๊ธฐ๋“ค์˜ ๋ฐ˜ํ™˜ ๊ฒฐ๊ณผ๋Š” ํŠน์ง•์ ์˜ ์ขŒํ‘œ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋‹ค์–‘ํ•œ ์ •๋ณด๋“ค๋„ ํ•จ๊ป˜ ๋ฐ˜ํ™˜

 

keypoints = detector.detect(img, mask)

: ํŠน์ง•์  ๊ฒ€์ถœ ํ•จ์ˆ˜


- img : ์ž…๋ ฅ ์ด๋ฏธ์ง€
- mask(optional) : ๊ฒ€์ถœ ์ œ์™ธ ๋งˆ์Šคํฌ
- keypoints : ํŠน์ง•์  ๊ฒ€์ถœ ๊ฒฐ๊ณผ (KeyPoint์˜ ๋ฆฌ์ŠคํŠธ)

 

Keypoint

: ํŠน์ง•์  ์ •๋ณด๋ฅผ ๋‹ด๋Š” ๊ฐ์ฒด


- pt : ํŠน์ง•์  ์ขŒํ‘œ(x, y), float ํƒ€์ž…์œผ๋กœ ์ •์ˆ˜ ๋ณ€ํ™˜ ํ•„์š”
- size : ์˜๋ฏธ ์žˆ๋Š” ํŠน์ง•์  ์ด์›ƒ์˜ ๋ฐ˜์ง€๋ฆ„
- angle : ํŠน์ง•์  ๋ฐฉํ–ฅ (์‹œ๊ณ„๋ฐฉํ–ฅ, -1=์˜๋ฏธ ์—†์Œ)
- response : ํŠน์ง•์  ๋ฐ˜์‘ ๊ฐ•๋„ (์ถ”์ถœ๊ธฐ์— ๋”ฐ๋ผ ๋‹ค๋ฆ„)
- octave : ๋ฐœ๊ฒฌ๋œ ์ด๋ฏธ์ง€ ํ”ผ๋ผ๋ฏธ๋“œ ๊ณ„์ธต
- class_id : ํŠน์ง•์ ์ด ์†ํ•œ ๊ฐ์ฒด ID

 

: detector.detect() ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ ๊ฒฐ๊ณผ์ธ Keypoints์—๋Š” ๋‹ค์–‘ํ•œ ์ •๋ณด๋“ค์ด ๋‹ด๊ฒจ์žˆ์Œ

: Keypoints๋Š” ํŠน์ง•์ ์˜ ์ขŒํ‘œ ์ •๋ณด์ธ pt ์†์„ฑ์„ ํ•ญ์ƒ ๊ฐ–์ง€๋งŒ

๋‚˜๋จธ์ง€ ์†์„ฑ์€ ์‚ฌ์šฉํ•˜๋Š” ๊ฒ€์ถœ๊ธฐ์— ๋”ฐ๋ผ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์Œ

: ๊ฒ€์ถœํ•œ ํŠน์ง•์ ์€ cv2.circle() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ‘œ์‹œํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ ํŠน์ง•์ ์„ ํ‘œ์‹œํ•ด์ฃผ๋Š” ์ „์šฉ ํ•จ์ˆ˜๋„ ๊ฐ€๋Šฅ

 

outImg = cv2.drawKeypoints(img, keypoints, outImg, color, flags)

: ํŠน์ง•์ ์„ ํ‘œ์‹œํ•ด์ฃผ๋Š” ์ „์šฉ ํ•จ์ˆ˜

 

- img : ์ž…๋ ฅ ์ด๋ฏธ์ง€
- keypoints : ํ‘œ์‹œํ•  ํŠน์ง•์  ๋ฆฌ์ŠคํŠธ
- outImg : ํŠน์ง•์ ์ด ๊ทธ๋ ค์ง„ ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€
- color(optional) : ํ‘œ์‹œํ•  ์ƒ‰์ƒ (default : ๋žœ๋ค)
- flags(optional) : ํ‘œ์‹œ ๋ฐฉ๋ฒ•

  • cv2.DRAW_MATCHES_FLAGS_DEFAULT : ์ขŒํ‘œ ์ค‘์‹ฌ์— ๋™๊ทธ๋ผ๋ฏธ๋งŒ ๊ทธ๋ฆผ(default)
  • cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS : ๋™๊ทธ๋ผ๋ฏธ์˜ ํฌ๊ธฐ๋ฅผ size์™€ angle์„ ๋ฐ˜์˜ํ•ด์„œ ๊ทธ๋ฆผ

 

 

5. GFTTDetector

: cv2.goodFeaturesToTrack() ํ•จ์ˆ˜๋กœ ๊ตฌํ˜„๋œ ํŠน์ง•์  ๊ฒ€์ถœ๊ธฐ <์‹œ-ํ† ๋งˆ์‹œ ์ฝ”๋„ˆ ๊ฒ€์ถœ ๋ฐฉ๋ฒ•>

: GFTTDetector ๊ฒ€์ถœ๊ธฐ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํŠน์ง•์ ์„ ๊ฒ€์ถœํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•˜๋Š” ํ•จ์ˆ˜๋Š” detect() ํ•จ์ˆ˜์™€ ๊ฐ™์Œ

 

detector = cv2.GFTTDetector_create(img, maxCorners, qualityLevel, minDistance, corners, mask, blockSize, useHarrisDetector, k)

: GFTTDetector ํ•จ์ˆ˜์˜ ์ƒ์„ฑ

 

- ๋ชจ๋“  ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” cv2.goodFeaturesToTrack()๊ณผ ๋™์ผ

- ๊ฒ€์ถœํ•œ ๊ฒฐ๊ณผ๋Š” ํŠน์ง•์  ์ขŒํ‘œ(pt) ์†์„ฑ๋งŒ ์žˆ๊ณ  ๋‚˜๋จธ์ง€ ์†์„ฑ ๊ฐ’์€ ๋ชจ๋‘ ๋น„์—ˆ์Œ

# GFTTDetector๋กœ ํŠน์ง•์  ๊ฒ€์ถœ
import cv2
import numpy as np
 
img = cv2.imread("img/house.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Good feature to trac ๊ฒ€์ถœ๊ธฐ ์ƒ์„ฑ ---โ‘ 
gftt = cv2.GFTTDetector_create() 
# ํŠน์ง•์  ๊ฒ€์ถœ ---โ‘ก
keypoints = gftt.detect(gray, None)
# ํŠน์ง•์  ๊ทธ๋ฆฌ๊ธฐ ---โ‘ข
img_draw = cv2.drawKeypoints(img, keypoints, None)

# ๊ฒฐ๊ณผ ์ถœ๋ ฅ ---โ‘ฃ
cv2.imshow('GFTTDectector', img_draw)
cv2.waitKey(0)
cv2.destrolyAllWindows()

GFTTDetector๋กœ ๊ฒ€์ถœํ•œ ํŠน์ง•์ ์„ ํ‘œ์‹œ

: ํ•ด๋ฆฌ์Šค ์ฝ”๋„ˆ ๊ฒ€์ถœ๊ณผ ์‹œ์™€ ํ† ๋งˆ์‹œ ์ฝ”๋„ˆ ๊ฒ€์ถœ๋ณด๋‹ค ๋” ๋งŽ์€ ์ฝ”๋„ˆ๊ฐ€ ๊ฒ€์ถœ

: ํŠน์ง•์ ์„ ํ‘œ์‹œํ•œ ๋™๊ทธ๋ผ๋ฏธ์˜ ์ƒ‰์ƒ์ด ๋‹ค์–‘

: ํŠน์ง•์ ์„ ํ‘œ์‹œํ•˜๋Š” ํ•จ์ˆ˜์ธ cv2.drawKeypoints() ํ•จ์ˆ˜์—์„œ color ์†์„ฑ์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๋žœ๋คํ•œ ์ƒ‰์ƒ

 

 

 

 

6. FAST(Feature from Accelerated Segment Test)

: FAST๋Š” ๊ธฐ์กด ๊ฒ€์ถœ๊ธฐ๋ณด๋‹ค ์†๋„๊ฐ€ ๋น ๋ฅธ ๊ฒ€์ถœ๊ธฐ

: ์ฝ”๋„ˆ๋ฅผ ๊ฒ€์ถœํ•  ๋•Œ ๋ฏธ๋ถ„ ์—ฐ์‚ฐ์„ ํ•˜์ง€ ์•Š์Œ

: ํ”ฝ์…€์„ ์ค‘์‹ฌ์œผ๋กœ ํŠน์ • ๊ฐœ์ˆ˜์˜ ํ”ฝ์…€๋กœ ์›์„ ๊ทธ๋ ค์„œ ๊ทธ ์•ˆ์˜ ํ”ฝ์…€๋“ค์ด ์ค‘์‹ฌ ํ”ฝ์…€ ๊ฐ’๋ณด๋‹ค ์ž„๊ณ„ ๊ฐ’ ์ด์ƒ ๋ฐ๊ฑฐ๋‚˜ ์–ด๋‘์šด ๊ฒƒ์ด ์ผ์ • ๊ฐœ์ˆ˜ ์ด์ƒ ์—ฐ์†๋˜๋ฉด ์ฝ”๋„ˆ๋กœ ํŒ๋‹จ

์ถœ์ฒ˜: https://wiserloner.tistory.com/879

detector = cv2.FastFeatureDetector_create(threshold, nonmaxSuppression, type)

: ํŠน์ง•์  ๊ฒ€์ถœ ์‹œ์—๋Š” detect() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉ

 

- threshold(optional) : ์ฝ”๋„ˆ ํŒ๋‹จ ์ž„๊ณ„ ๊ฐ’ (default=10)
- nonmaxSuppression(optional) : ์ตœ๋Œ€ ์ ์ˆ˜๊ฐ€ ์•„๋‹Œ ์ฝ”๋„ˆ ์–ต์ œ (default=True)
- type(optional) : ์—ฃ์ง€ ๊ฒ€์ถœ ํŒจํ„ด

  • cv2.FastFeatureDetector_TYPE_9_16 : 16๊ฐœ ์ค‘ 9๊ฐœ ์—ฐ์†(default)
  • cv2.FastFeatureDetector_TYPE_7_12 : 12๊ฐœ ์ค‘ 7๊ฐœ ์—ฐ์†
  • cv2.FastFeatureDetector_TYPE_5_8 : 8๊ฐœ ์ค‘ 5๊ฐœ ์—ฐ์†
# FAST๋กœ ํŠน์ง•์  ๊ฒ€์ถœ
import cv2
import numpy as np

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

# FASt ํŠน์ง• ๊ฒ€์ถœ๊ธฐ ์ƒ์„ฑ ---โ‘ 
fast = cv2.FastFeatureDetector_create(50)
# ํŠน์ง•์  ๊ฒ€์ถœ ---โ‘ก
keypoints = fast.detect(gray, None)
# ํŠน์ง•์  ๊ทธ๋ฆฌ๊ธฐ ---โ‘ข
img = cv2.drawKeypoints(img, keypoints, None)
# ๊ฒฐ๊ณผ ์ถœ๋ ฅ ---โ‘ฃ
cv2.imshow('FAST', img)
cv2.waitKey()
cv2.destroyAllWindows()

์†๋„๊ฐ€ ๋น ๋ฅธ ๊ฒ€์ถœ๊ธฐ..

 

 

 

 

7. SimpleBlobDetector

: BLOB(Binary Large Object)๋Š” ์ด์ง„ ์Šค์ผ€์ผ๋กœ ์—ฐ๊ฒฐ๋œ ํ”ฝ์…€ ๊ทธ๋ฃน

: SimpleBlobDetector๋Š” ์ž์ž˜ํ•œ ๊ฐ์ฒด๋Š” ๋…ธ์ด์ฆˆ๋กœ ์—ฌ๊ธฐ๊ณ  ํŠน์ • ํฌ๊ธฐ ์ด์ƒ์˜ ํฐ ๊ฐ์ฒด๋งŒ ์ฐพ์•„๋‚ด๋Š” ๊ฒ€์ถœ๊ธฐ

 

detector = cv2.SimpleBlobDetector_create([parameters])

: BLOB ๊ฒ€์ถœ๊ธฐ ์ƒ์„ฑ์ž

 

  • cv2.SimpleBlobDetector_Params()
    • minThreshold, maxThreshold, thresholdStep : BLOB๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ๊ฒฝ๊ณ„ ๊ฐ’ (minThreshold์—์„œ maxThreshold๋ฅผ ๋„˜์ง€ ์•Š์„ ๋•Œ๊นŒ์ง€ thresholdStep๋งŒํผ ์ฆ๊ฐ€)
    • minRepeatability : BLOB์— ์ฐธ์—ฌํ•˜๊ธฐ ์œ„ํ•œ ์—ฐ์†๋œ ๊ฒฝ๊ณ„ ๊ฐ’์˜ ๊ฐœ์ˆ˜
    • minDistBetweenBlobs : ๋‘ BLOB์„ ํ•˜๋‚˜์˜ BLOB์œผ๋กœ ๊ฐ„์ฃผํ•˜๋Š” ๊ฑฐ๋ฆฌ
    • filterByArea : ๋ฉด์  ํ•„ํ„ฐ ์˜ต์…˜
    • minArea, maxArea : min~max ๋ฒ”์œ„์˜ ๋ฉด์ ๋งŒ BLOB์œผ๋กœ ๊ฒ€์ถœ
    • filterByCircularity : ์›ํ˜• ๋น„์œจ ํ•„ํ„ฐ ์˜ต์…˜
    • minCircularity, maxCircularity : min~max ๋ฒ”์œ„์˜ ์›ํ˜• ๋น„์œจ๋งŒ BLOB์œผ๋กœ ๊ฒ€์ถœ
    • filterByColor : ๋ฐ๊ธฐ๋ฅผ ์ด์šฉํ•œ ํ•„ํ„ฐ ์˜ต์…˜
    • blobColor : 0 = ๊ฒ€์€์ƒ‰ BLOB ๊ฒ€์ถœ, 255 = ํฐ์ƒ‰ BLOB ๊ฒ€์ถœ
    • filterByConvexity : ๋ณผ๋ก ๋น„์œจ ํ•„ํ„ฐ ์˜ต์…˜
    • minConvexity, maxConvexity : min~max ๋ฒ”์œ„์˜ ๋ณผ๋ก ๋น„์œจ๋งŒ BLOB์œผ๋กœ ๊ฒ€์ถœ
    • filterByInertia : ๊ด€์„ฑ ๋น„์œจ ํ•„ํ„ฐ ์˜ต์…˜
    • minInertiaRatio, maxInertiaRatio : min~max ๋ฒ”์œ„์˜ ๊ด€์„ฑ ๋น„์œจ๋งŒ BLOB์œผ๋กœ ๊ฒ€์ถœ
# SimpleBolbDetector ๊ฒ€์ถœ๊ธฐ
import cv2
import numpy as np
 
img = cv2.imread("img/house.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# SimpleBlobDetector ์ƒ์„ฑ ---โ‘ 
detector = cv2.SimpleBlobDetector_create()
# ํ‚ค ํฌ์ธํŠธ ๊ฒ€์ถœ ---โ‘ก
keypoints = detector.detect(gray)
# ํ‚ค ํฌ์ธํŠธ๋ฅผ ๋นจ๊ฐ„์ƒ‰์œผ๋กœ ํ‘œ์‹œ ---โ‘ข
img = cv2.drawKeypoints(img, keypoints, None, (0,0,255),\
                flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
 
cv2.imshow("Blob", img)
cv2.waitKey(0)

ํฐ ์ฝ”๋„ˆ๋งŒ ๊ฒ€์ถœ

: ์ž์ž˜ํ•œ ์ฝ”๋„ˆ๋Š” ๋…ธ์ด์ฆˆ๋กœ ๊ฐ„์ฃผํ•˜๊ณ  ํŠน์ • ํฌ๊ธฐ ์ด์ƒ์˜ ๊ฐ์ฒด๋งŒ ๊ฒ€์ถœ

 

 

+) SimpleBlobDetector์— ํ•„ํ„ฐ ์˜ต์…˜์„ ์ฃผ์–ด ์‹คํ–‰

# ํ•„ํ„ฐ ์˜ต์…˜์œผ๋กœ ์ƒ์„ฑํ•œ SimpleBlobDetector ๊ฒ€์ถœ๊ธฐ
import cv2
import numpy as np
 
img = cv2.imread("img/house.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# blob ๊ฒ€์ถœ ํ•„ํ„ฐ ํŒŒ๋ผ๋ฏธํ„ฐ ์ƒ์„ฑ ---โ‘ 
params = cv2.SimpleBlobDetector_Params()

# ๊ฒฝ๊ณ„๊ฐ’ ์กฐ์ • ---โ‘ก
params.minThreshold = 10
params.maxThreshold = 240
params.thresholdStep = 5
# ๋ฉด์  ํ•„ํ„ฐ ์ผœ๊ณ  ์ตœ์†Œ ๊ฐ’ ์ง€์ • ---โ‘ข
params.filterByArea = True
params.minArea = 200
  
# ์ปฌ๋Ÿฌ, ๋ณผ๋ก ๋น„์œจ, ์›ํ˜•๋น„์œจ ํ•„ํ„ฐ ์˜ต์…˜ ๋„๊ธฐ ---โ‘ฃ
params.filterByColor = False
params.filterByConvexity = False
params.filterByInertia = False
params.filterByCircularity = False 

# ํ•„ํ„ฐ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ blob ๊ฒ€์ถœ๊ธฐ ์ƒ์„ฑ ---โ‘ค
detector = cv2.SimpleBlobDetector_create(params)
# ํ‚ค ํฌ์ธํŠธ ๊ฒ€์ถœ ---โ‘ฅ
keypoints = detector.detect(gray)
# ํ‚ค ํฌ์ธํŠธ ๊ทธ๋ฆฌ๊ธฐ ---โ‘ฆ
img_draw = cv2.drawKeypoints(img, keypoints, None, None,\
                     cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
# ๊ฒฐ๊ณผ ์ถœ๋ ฅ ---โ‘ง
cv2.imshow("Blob with Params", img_draw)
cv2.waitKey(0)

ํŒŒ๋ผ๋ฏธํ„ฐ ์˜ต์…˜ ์ถ”๊ฐ€

: ์ด์ „๋ณด๋‹ค ๋” ๋งŽ์€ ๊ฐ์ฒด ๊ฒ€์ถœ!

 

 

 

 

 

 

 

 

 

 

๋~

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