๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ’ป Programming/Computer Vision

[OpenCV] Feature Detection & Matching | ํŠน์ง• ๊ฒ€์ถœ๊ณผ ๋งค์นญ | ์ด๋ฏธ์ง€์—์„œ ์œ ์‚ฌํ•œ ํŠน์ง• ์ฐพ์•„๋‚ด๊ธฐ | ์ด๋ฏธ์ง€ ๋Œ€์‘์ 

by ๋ญ…์ฆค 2023. 4. 3.
๋ฐ˜์‘ํ˜•
Feature Detection & Matching

 

์ปดํ“จํ„ฐ๋น„์ „ ๋ถ„์•ผ์—์„œ์˜ feature matching์€ ๋‘ ๊ฐœ ์ด์ƒ์˜ ์ด๋ฏธ์ง€์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ๋‚˜ํƒ€๋‚˜๋Š” ํŠน์ง•์„ ์ฐพ์•„๋‚ด๋Š” ๊ธฐ์ˆ ์ด๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ด๋ฏธ์ง€ ๊ฐ„์˜ ๋Œ€์‘์ ์„ ์ฐพ๊ฑฐ๋‚˜, ์ด๋ฏธ์ง€ ๊ฐ„์˜ ๋ณ€ํ™”๋ฅผ ์ถ”์ ํ•˜๋Š” ๋“ฑ ๋‹ค์–‘ํ•œ ๋ถ„์•ผ์— ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. 
 
์ด๋Ÿฌํ•œ Feature matching์˜ ๊ณผ์ •์€ ํฌ๊ฒŒ ๋‘ ๊ฐ€์ง€ ๋‹จ๊ณ„๋กœ ๋‚˜๋‰œ๋‹ค. ๋จผ์ € ๊ฐ ์ด๋ฏธ์ง€์—์„œ ํŠน์ง•์„ ๊ฒ€์ถœํ•˜๊ณ , ์ด๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ฐ ํŠน์ง•๋“ค์ด ์–ด๋–ป๊ฒŒ ๋งค์นญ๋˜๋Š”์ง€ ์ฐพ์•„๋‚ด๋Š” ๊ฒƒ์ด๋‹ค.
 

1. Feature Detection (ํŠน์ง• ๊ฒ€์ถœ)

์ด๋ฏธ์ง€์—์„œ ํŠน์ง•์„ ๊ฒ€์ถœํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ด๋ฏธ์ง€ ๋‚ด์˜ ํŠน์ดํ•œ ํŒจํ„ด์ด๋‚˜ ๊ตฌ์กฐ๋ฅผ ์ฐพ์•„๋‚ด๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค. ์ด๋ฅผ ์œ„ํ•ด SIFT, SURF, ORB ๋“ฑ์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜๋“ค์€ ์ด๋ฏธ์ง€์—์„œ ํŠน์ง•์ ์„ ๊ฒ€์ถœํ•˜๊ณ , ์ด๋“ค ์ฃผ๋ณ€์—์„œ ์ง€์—ญ์ ์ธ ํŒจํ„ด์„ ์ถ”์ถœํ•˜์—ฌ ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
 

2. Feature Matching (ํŠน์ง• ๋งค์นญ)

๋‘ ์ด๋ฏธ์ง€์—์„œ ์ถ”์ถœํ•œ ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ (Feature Descriptor)๋ฅผ ๋น„๊ตํ•˜์—ฌ ๋Œ€์‘๋˜๋Š” ํŠน์ง•์  ์Œ์„ ์ฐพ์•„๋‚ด๋Š” ๊ฒƒ์ด ํŠน์ง• ๋งค์นญ์˜ ํ•ต์‹ฌ์ด๋‹ค. ๋งค์นญ ๋ฐฉ๋ฒ•์—๋Š” ์ฃผ๋กœ ์ตœ๊ทผ์ ‘ ์ด์›ƒ(Nearest Neighbor) ๋งค์นญ๊ณผ RANSAC(Random Sample Consensus)์„ ์ด์šฉํ•œ ๋งค์นญ์ด ์‚ฌ์šฉ๋œ๋‹ค.

  • Nearest Neighbor Matching (์ตœ๊ทผ์ ‘ ์ด์›ƒ ๋งค์นญ): ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ฐ„์˜ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ๋งค์นญ์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ์ด๋•Œ, ์ด์›ƒ๊ณผ์˜ ๊ฑฐ๋ฆฌ๊ฐ€ ์ผ์ • ์ด์ƒ ์ฐจ์ด๋‚˜๋ฉด ๋งค์นญ์„ ๊ฑฐ๋ถ€ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ฑฐ๋ฆฌ ์ž„๊ณ„๊ฐ’์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • RANSAC : ์ผ๋ถ€ ์ž˜๋ชป๋œ ๋งค์นญ์„ ๊ฑธ๋Ÿฌ๋‚ด๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ, ์ผ์ • ๊ฐœ์ˆ˜์˜ ๋งค์นญ์„ ๋ฌด์ž‘์œ„๋กœ ์„ ํƒํ•˜์—ฌ ์ด๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ชจ๋ธ์„ ์ƒ์„ฑํ•˜๊ณ , ์ด ๋ชจ๋ธ์„ ์ด์šฉํ•˜์—ฌ ๋‚˜๋จธ์ง€ ๋งค์นญ๋“ค์„ ๊ฒ€์ฆํ•˜๊ณ  ์ •ํ™•๋„๊ฐ€ ๋†’์€ ๋งค์นญ๋“ค๋งŒ์„ ์„ ํƒํ•œ๋‹ค.

 

Feature matching์€ ์ด๋ฏธ์ง€ ๊ฒ€์ƒ‰, ๊ฐ์ฒด ์ธ์‹, ์˜์ƒ ๋ถ„๋ฅ˜ ๋“ฑ์˜ ๋ถ„์•ผ์—์„œ ํ™œ์šฉ๋˜์–ด ์™”๊ณ , ํŠนํžˆ multi-view stereo ์ฒ˜๋Ÿผ ์—ฌ๋Ÿฌ ์žฅ์˜ ์„œ๋กœ ๋‹ค๋ฅธ ์‹œ์ ์˜ ์ด๋ฏธ์ง€๋“ค ์†์—์„œ ๋Œ€์‘์ ์„ ์ฐพ๊ธฐ ์œ„ํ•ด ์ž์ฃผ ์‚ฌ์šฉ๋œ๋‹ค.
 
 

OpenCV Feature Detection

 

OpenCV์—์„œ ์ œ๊ณตํ•˜๋Š” ๋Œ€ํ‘œ์ ์ธ feature detection ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ๋Š” SIFT, SURF, ORB, FAST, BRISK, AKAZE ๋“ฑ์ด ์žˆ๋‹ค. ๊ฐ€์žฅ ์„ฑ๋Šฅ์ด ์ข‹์€ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์ด๋ฏธ์ง€์˜ ์—ฌ๋Ÿฌ ํŠน์„ฑ (ํฌ๊ธฐ, ๋ฐฉํ–ฅ์„ฑ, ๋…ธ์ด์ฆˆ, ํŒจํ„ด์˜ ๋ณต์žก์„ฑ,...)์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ๋Š” ํŠน์ง•์ด ๋‹จ์ˆœํ•œ ๊ฒฝ์šฐ์—๋Š” FAST๋‚˜ BRISK ๊ฐ™์€ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์ ํ•ฉํ•˜๊ณ  ์ด๋ฏธ์ง€๊ฐ€ ํฌ๊ฑฐ๋‚˜ ํŠน์ง•์ด ๋ณต์žกํ•œ ๊ฒฝ์šฐ SIFT, SURF, AKAZE์™€ ๊ฐ™์€ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์ ํ•ฉํ•˜๋‹ค.
 

  • SIFT(Scale-Invariant Feature Transform)
    • ์ด๋ฏธ์ง€์˜ ํฌ๊ธฐ์™€ ํšŒ์ „์— ๋Œ€ํ•œ ๋ถˆ๋ณ€์„ฑ์„ ๊ฐ€์ง€๋Š” ํŠน์ง•์  ๊ฒ€์ถœ ์•Œ๊ณ ๋ฆฌ์ฆ˜
    • ์ด๋ฏธ์ง€์˜ ํฌ๊ธฐ์™€ ํšŒ์ „์— ๊ฐ•ํ•œ ํŠน์ง•์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด ๋Œ€๋ถ€๋ถ„์˜ ์ƒํ™ฉ์—์„œ ์•ˆ์ •์ ์ธ ์„ฑ๋Šฅ์„ ๋ณด์—ฌ์คŒ
    • ํ•˜์ง€๋งŒ SIFT๋Š” ์ปดํ“จํŒ… ๋ฆฌ์†Œ์Šค๊ฐ€ ๋งŽ์ด ์†Œ์š”
  • SURF(Speeded-Up Robust Features)
    • SIFT์—์„œ ํŠน์ง•์  ๊ฒ€์ถœ ๋ฐ ๊ธฐ์ˆ ์ž ๊ณ„์‚ฐ ์†๋„๋ฅผ ๊ฐœ์„ ํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜
    • SIFT์™€ ๋น„์Šทํ•œ ์„ฑ๋Šฅ์„ ๊ฐ€์ง€๋ฉด์„œ๋„ ๋” ๋น ๋ฅธ ์†๋„๋ฅผ ์ œ๊ณต
  • ORB(Oriented FAST and Rotated BRIEF)
    • FAST์™€ BRIEF ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ฒฐํ•ฉํ•œ ๋ฐฉ์‹์œผ๋กœ, SIFT์™€ SURF ๋Œ€๋น„ ์†๋„๊ฐ€ ๋งค์šฐ ๋น ๋ฅด๋ฉด์„œ๋„ ์ข‹์€ ์„ฑ๋Šฅ์„ ๊ฐ€์ง„ ์•Œ๊ณ ๋ฆฌ์ฆ˜
    • ์ด๋ฏธ์ง€๋ฅผ ํšŒ์ „ํ•˜๊ฑฐ๋‚˜ ํฌ๊ธฐ๋ฅผ ๋ฐ”๊ฟจ์„ ๋•Œ ํŠน์ง•์  ๊ฒ€์ถœ ๊ฒฐ๊ณผ๊ฐ€ ๋ฐ”๋€Œ์ง€ ์•Š๋Š” ํŠน์ง•
    • ํŠนํžˆ, ์ž„๋ฒ ๋””๋“œ ๊ธฐ๊ธฐ๋‚˜ ๋ชจ๋ฐ”์ผ ์•ฑ ๋“ฑ์—์„œ์˜ ์‹ค์‹œ๊ฐ„ ์—ฐ์‚ฐ์— ์ ํ•ฉํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋ผ ํญ๋„“๊ฒŒ ์‚ฌ์šฉ
  • FAST(Features from Accelerated Segment Test)
    • ์ด๋ฏธ์ง€์—์„œ ๋น ๋ฅด๊ฒŒ ํŠน์ง•์ ์„ ๊ฒ€์ถœํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜
    • ๋‹จ์ˆœํ•˜๊ณ  ๋น ๋ฅธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ์•Œ๊ณ ๋ฆฌ์ฆ˜๋“ค๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜์–ด, ์ดˆ๊ธฐ ํŠน์ง•์  ๊ฒ€์ถœ ํ›„, ๋ณด๋‹ค ์ •ํ™•ํ•œ ๊ฒ€์ถœ ์•Œ๊ณ ๋ฆฌ์ฆ˜(์˜ˆ: BRIEF, SIFT, SURF)์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Œ
  • BRISK( Binary Robust Invariant Scalable Keypoints)
    • 2011๋…„์— ๋…ผ๋ฌธ์œผ๋กœ ๋ฐœํ‘œ๋œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ, ์ด๋ฏธ์ง€์—์„œ ํŠน์ง•์ ์„ ๊ฒ€์ถœํ•˜๊ธฐ ์œ„ํ•ด ์Šค์ผ€์ผ ๊ณต๊ฐ„(scale space)์—์„œ ํŠน์ •ํ•œ ํฌ๊ธฐ์˜ ํŒจ์น˜(patch)๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ํŒจ์น˜ ๋‚ด์˜ intensity difference๋ฅผ ์ด์šฉํ•˜์—ฌ FAST ๋ฐฉ๋ฒ•์œผ๋กœ ํŠน์ง•์ ์„ ๊ฒ€์ถœ
    • ํŠน์ง•์ ์„ ๋ฌ˜์‚ฌํ•˜๊ธฐ ์œ„ํ•ด intensity difference ๊ฐ’๋“ค์˜ ๋ถ„ํฌ๋ฅผ ์ด์šฉํ•˜์—ฌ ํŠน์ง•์ ์„ ๊ธฐ์ˆ ํ•˜๋Š” binary descriptor๋ฅผ ์‚ฌ์šฉ
  • AKAZE(Accelerated-KAZE)
    • 2013๋…„์— ๋ฐœํ‘œ๋œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ, ์ด๋ฏธ์ง€์—์„œ ํŠน์ง•์ ์„ ๊ฒ€์ถœํ•˜๊ธฐ ์œ„ํ•ด KAZE ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉ 
    • KAZE๋Š” ์ด๋ฏธ์ง€์˜ ์Šค์ผ€์ผ ๊ณต๊ฐ„์—์„œ multiscale ๋ฐฉ์‹์œผ๋กœ ์ด๋ฏธ์ง€๋ฅผ ๋ธ”๋Ÿฌ๋งํ•˜๊ณ , Difference of Gaussian(DoG)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ scale-space ๋‚ด์—์„œ ๊ทนํ•œ ๊ฐ’(extrema)์„ ์ฐพ์Œ. ์ดํ›„, extrema์—์„œ Hessian matrix๋ฅผ ์ด์šฉํ•˜์—ฌ ํŠน์ง•์ ์„ ๊ฒ€์ถœ
    • AKAZE๋Š” KAZE์˜ ๋ณ€ํ˜•์œผ๋กœ, ์ด๋ฅผ ๋” ๋น ๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„
    • AKAZE์—์„œ๋Š” scale-space ๋‚ด์—์„œ ํŠน์ง•์ ์„ ๊ฒ€์ถœํ•œ ์ดํ›„, ๊ทธ ํŠน์ง•์ ์— ๋Œ€ํ•œ ๋ฐฉํ–ฅ(direction)์„ ์ถ”์ถœํ•˜์—ฌ, ๊ทธ ๋ฐฉํ–ฅ์— ๋”ฐ๋ผ ํŠน์ง•์ ์˜ ๋ฌ˜์‚ฌ(descriptor)๋ฅผ ์ƒ์„ฑ

 

OpenCV Feature Matching

 
OpenCV์—์„œ feature matching์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋Œ€ํ‘œ์ ์œผ๋กœ SIFT, SURF, ORB ๋“ฑ์˜ feature detection ๋ฐ detection ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜๊ณ , ์ดํ›„ feature matching ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ๋Š” ๋Œ€ํ‘œ์ ์œผ๋กœ brute-force matching, FLANN matching ๋“ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
 

  • cv2.BFMatcher()
    • ๋ธŒ๋ฃจํŠธ ํฌ์Šค ๋งค์นญ(brute-force matching) ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ ํŠน์ง• ๋งค์นญ์„ ์ˆ˜ํ–‰
    • ํŠนํžˆ ์ž‘์€ ๋ฐ์ดํ„ฐ ์…‹์—์„œ ๋†’์€ ์ •ํ™•๋„๋ฅผ ๋ณด์ด๋ฉฐ, ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ์—๋Š” cv2.FlannBasedMatcher() ๋ณด๋‹ค ๋Š๋ฆฌ์ง€๋งŒ ๋” ๋‚˜์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Œ

 

  • cv2.FlannBasedMatcher()
    • ๋น ๋ฅธ Nearest Neighbor ๊ฒ€์ƒ‰์„ ์œ„ํ•œ ํŠน์ง• ๋งค์นญ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ค‘ ํ•˜๋‚˜
    • FLANN (Fast Library for Approximate Nearest Neighbors) ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ ํŠน์ง• ๋””์Šคํฌ๋ฆฝํ„ฐ ์‚ฌ์ด์˜ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์ด์›ƒ(Nearest Neighbor)์„ ์ฐพ์Œ
    • ํŠน์ง• ๊ธฐ์ˆ ์ž๋“ค์˜ ์ง‘ํ•ฉ์—์„œ k-NN(k-Nearest Neighbor)์„ ๊ฒ€์ƒ‰ํ•˜์—ฌ ๋‘ ์ด๋ฏธ์ง€์—์„œ ์œ ์‚ฌํ•œ ํŠน์ง•์„ ๋งค์นญ. ๊ธฐ๋ณธ์ ์œผ๋กœ, cv2.FlannBasedMatcher๋Š” k=2๋กœ ์„ค์ •
      • index_params: Flann ๊ธฐ๋ฐ˜ ๋งค์นญ์—์„œ ์ธ๋ฑ์Šค๋ฅผ ์„ค์ •ํ•˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ. ๋”•์…”๋„ˆ๋ฆฌ ํ˜•ํƒœ๋กœ ์ „๋‹ฌ๋˜๋ฉฐ, algorithm๊ณผ trees ๋‘ ๊ฐ€์ง€ ํ•˜์œ„ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ฐ€์ง
        • algorithm : ๋งค์นญ์— ์‚ฌ์šฉํ•  ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋‚˜ํƒ€๋‚ด๋ฉฐ, ๋ณดํ†ต์€ cv2.flann.IndexParams ํด๋ž˜์Šค์˜ ์ƒ์ˆ˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉ
        • trees : ๋งค์นญ์— ์‚ฌ์šฉ๋  ํŠธ๋ฆฌ์˜ ๊ฐœ์ˆ˜
      • search_params: ๋งค์นญ์„ ์ˆ˜ํ–‰ํ•  ๋•Œ ๊ฒ€์ƒ‰ํ•  ์ด์›ƒ์˜ ๊ฐœ์ˆ˜์™€ ๊ฒ€์ƒ‰ํ•  ์ตœ๋Œ€ ๊ฑฐ๋ฆฌ๋ฅผ ์„ค์ •ํ•˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ. ๋”•์…”๋„ˆ๋ฆฌ ํ˜•ํƒœ๋กœ ์ „๋‹ฌ๋˜๋ฉฐ, checks์™€ eps ๋‘ ๊ฐ€์ง€ ํ•˜์œ„ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ฐ€์ง
        • checks : ๊ฒ€์ƒ‰ํ•  ์ด์›ƒ์˜ ๊ฐœ์ˆ˜
        • eps : ๊ฒ€์ƒ‰ํ•  ์ตœ๋Œ€ ๊ฑฐ๋ฆฌ

 

Feature Detection & Matching ์˜ˆ์‹œ

 

  • ๊ธ€๋ฆฌ์ฝ”์ƒ ์ด๋ฏธ์ง€์™€ ๋„ํ†ค๋ณด๋ฆฌ ๋ฐฐ๊ฒฝ ์ด๋ฏธ์ง€ ๊ฐ„ feature matching
  • Feature Detection ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ SIFT, ORB, BRISK, AKAZE ์‚ฌ์šฉ
  • Matching ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ brute-force์™€ flann-based ๋ฐฉ๋ฒ• ์ค‘ ์„ ํƒ 
  • ๋งค์นญ ๊ฒฐ๊ณผ ์‹œ๊ฐํ™”
  • ๋งค์นญ ํฌ์ธํŠธ (ํ”ฝ์…€ ์œ„์น˜) ์ถœ๋ ฅ
import cv2

# ์ด๋ฏธ์ง€ ์ฝ๊ธฐ
img1 = cv2.imread('๊ธ€๋ฆฌ์ฝ”์ƒ.png')
img2 = cv2.imread('๊ธ€๋ฆฌ์ฝ”์ƒ1.jpg')

using_FAST = False

feature_detector = dict(SIFT = cv2.SIFT_create(), 
                        ORB = cv2.ORB_create(),
                        brisk = cv2.BRISK_create(),
                        akaze = cv2.AKAZE_create())

matching_type = 'flann' # 'bruteforce' or 'flann'

for type in list(feature_detector.keys()):
    # SIFT ์ƒ์„ฑ
    detector = feature_detector[type]

    # ๊ฐ ์ด๋ฏธ์ง€์—์„œ ํ‚คํฌ์ธํŠธ ๋ฐ ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ณ„์‚ฐ
    if using_FAST == True :
        fast = cv2.FastFeatureDetector_create()
        kp1 = fast.detect(img1, None)
        kp2 = fast.detect(img2, None)
        kp1, des1 = detector.compute(img1, kp1)
        kp2, des2 = detector.compute(img2, kp2)
    else:
        kp1, des1 = detector.detectAndCompute(img1, None)
        kp2, des2 = detector.detectAndCompute(img2, None)

    # ๋งค์นญ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์„ ์ •
    if matching_type == 'bruteforce':
        matcher = cv2.BFMatcher()
    elif matching_type == 'flann':
        if type == 'SIFT' or type == 'FAST':
            # SIFT ํŒŒ๋ผ๋ฏธํ„ฐ
            FLANN_INDEX_KDTREE = 1
            index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
            search_params = dict(checks=50)
        elif type == 'ORB' :
            # ORB ํŒŒ๋ผ๋ฏธํ„ฐ
            FLANN_INDEX_LSH = 6
            index_params= dict(algorithm = FLANN_INDEX_LSH,
                            table_number = 6,
                            key_size = 12,
                            multi_probe_level = 1)
            search_params=dict(checks=32)
        matcher = cv2.FlannBasedMatcher(index_params, search_params)


    # ๋งค์นญ ๋ฐ ๋งค์นญ๋œ ํฌ์ธํŠธ ๊ฑฐ๋ฆฌ ์ •๋ ฌ
    matches = matcher.match(des1, des2)
    matches = sorted(matches, key=lambda x:x.distance)
    good_matches = matches[:30]
    
    # ๋งค์นญ ๊ฒฐ๊ณผ ์‹œ๊ฐํ™”
    img3 = cv2.drawMatches(img1, kp1, img2, kp2, good_matches, None, flags=2)
    cv2.imshow("Matching result", img3)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    # ๋งค์นญ๋œ ์ง€์ ์˜ ํ”ฝ์…€ ์œ„์น˜ ์ถ”์ถœ
    matched_points1 = []
    matched_points2 = []
    for match in good_matches:
        # queryIdx: ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์—์„œ์˜ ํ‚คํฌ์ธํŠธ ์ธ๋ฑ์Šค
        # trainIdx: ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์—์„œ์˜ ํ‚คํฌ์ธํŠธ ์ธ๋ฑ์Šค
        pt1 = kp1[match.queryIdx].pt
        pt2 = kp2[match.trainIdx].pt
        matched_points1.append((int(pt1[0]), int(pt1[1])))
        matched_points2.append((int(pt2[0]), int(pt2[1])))

    # ํ”ฝ์…€ ์œ„์น˜ ์ถœ๋ ฅ
    print("Matched Points in Image1:", matched_points1)
    print("Matched Points in Image2:", matched_points2)

 

๊ฒฐ๊ณผ 

# cv2.drawMatches ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•œ ๋งค์นญํฌ์ธํŠธ ์‹œ๊ฐํ™”

  • ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์™€ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์—์„œ ์ถ”์ถœ๋œ ํŠน์ง•์ ๋“ค ์ค‘์—์„œ ๋งค์นญ๋œ ํฌ์ธํŠธ๋“ค์„ ์ด์–ด์„œ ์‹œ๊ฐํ™”
  • ๊ฐ์ฒด์˜ ์‹œ๊ฐ์  ํŠน์ง•์— ๋”ฐ๋ผ ํŠน์ง•์ ์ด ์ž˜ ์ถ”์ถœ๋˜๋Š” feature detection ๋ฐฉ๋ฒ•์ด ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์‹œ๊ฐํ™” ํ…Œ์ŠคํŠธ๊ฐ€ ์ค‘์š”

์ขŒ : SIFT ๋งค์นญ, ์šฐ : ORB ๋งค์นญ
์ขŒ : BRISK ๋งค์นญ, ์šฐ : AKAZE ๋งค์นญ

# ๋งค์นญ ํฌ์ธํŠธ ์ถœ๋ ฅ

  • ๋งค์นญ ํฌ์ธํŠธ์˜ ํ”ฝ์…€ ์œ„์น˜๋ฅผ ์•Œ๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ ์ถ”์ถœ ๊ฐ€๋Šฅ
  • ์œ„ ์˜ˆ์‹œ์˜ ๊ฒฝ์šฐ ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€์—์„œ ๊ธ€๋ฆฌ์ฝ”์ƒ์ด ์กด์žฌํ•˜๋Š” ์œ„์น˜ ํŒŒ์•… ๊ฐ€๋Šฅ
  • ์ œํ•œ๋œ ํ™˜๊ฒฝ์—์„œ ๊ฐ์ฒด ๊ฒ€์ถœ์ด ๊ฐ€๋Šฅ
Matched Points in Image1: [(111, 131), (211, 128), (114, 130), (159, 266), (156, 271), (218, 128), (220, 128), (216, 114), (119, 131), (122, 143), (119, 131), (129, 209), (212, 131), (143, 120), (125, 207), (212, 127), (215, 114), (179, 322), (114, 114), (161, 267), (120, 130), (121, 141), (173, 229), (71, 93), (130, 209), (156, 79), (199, 211), (118, 150), (171, 229), (183, 75)]

Matched Points in Image2: [(73, 234), (115, 247), (73, 234), (92, 315), (92, 315), (119, 248), (119, 249), (268, 385), (76, 234), (78, 243), (76, 234), (81, 280), (115, 247), (87, 232), (79, 279), (91, 297), (269, 387), (104, 372), (73, 234), (93, 316), (77, 234), (78, 242), (97, 298), (92, 296), (81, 280), (94, 214), (109, 290), (734, 548), (98, 297), (248, 176)]

 

๋ฐ˜์‘ํ˜•