๐ ๊ณต๋ถํ๋ ์ง์ง์ํ์นด๋ ์ฒ์์ด์ง?
[v0.35]์์์ฒ๋ฆฌ_ํน์ง ๋งค์นญ(Feature Matching) ๋ณธ๋ฌธ
[v0.35]์์์ฒ๋ฆฌ_ํน์ง ๋งค์นญ(Feature Matching)
์ง์ง์ํ์นด 2022. 1. 18. 01:41220118 ์์ฑ
<๋ณธ ๋ธ๋ก๊ทธ๋ ๊ทํ์ด ์์ฌ๋์ ๋ธ๋ก๊ทธ๋ฅผ ์ฐธ๊ณ ํด์ ๊ณต๋ถํ๋ฉฐ ์์ฑํ์์ต๋๋ค>
OpenCV - 33. HOG(Histogram of Oriented Gradient) ๋์คํฌ๋ฆฝํฐ
์ด๋ฒ ํฌ์คํ ์์๋ HOG ๋์คํฌ๋ฆฝํฐ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค. ์ด๋ฒ์๋ 'ํ์ด์ฌ์ผ๋ก ๋ง๋๋ OpenCV ํ๋ก์ ํธ(์ด์ธ์ฐ ์ )'๋ฅผ ์ ๋ฆฌํ์ต๋๋ค. ๊ธฐ์ธ๊ธฐ ๋ฒกํฐ(Gradient Vectors) ๊ธฐ์ธ๊ธฐ ๋ฒกํฐ๋ ์์ ๋ด ํ๋์
bkshin.tistory.com
1. ๊ธฐ์ธ๊ธฐ ๋ฒกํฐ(Gradient Vectors)
: ๊ธฐ์ธ๊ธฐ ๋ฒกํฐ๋ ์์ ๋ด ํ๋์ ํฝ์ ์ ๊ธฐ์ค์ผ๋ก ์ฃผ๋ณ ํฝ์ ์ ๋ํ ๊ธฐ์ธ๊ธฐ๋ฅผ ๋ํ๋ด๋ ๋ฒกํฐ
: ๋นจ๊ฐ ์ ์ผ๋ก ํ์๋ ํฝ์ ์ ๊ธฐ์ค์ผ๋ก ์ผ์ชฝ์ Gray Scale ๊ฐ์ 56์ด๊ณ , ์ค๋ฅธ์ชฝ์ ๊ฐ์ 94
: Gray Scale์ ๊ฒฝ์ฐ 0์ด๋ฉด ๊ฒ์์์ด๊ณ 255์ด๋ฉด ํฐ์
: Gray Scale ๊ฐ 94๊ฐ 56๋ณด๋ค ๋ฐ์
: ๋นจ๊ฐ ์ ์ผ๋ก ํ์๋ ํฝ์ ์ ์ฅ์์ x์ถ ๋ฐฉํฅ์ ๋ณํ๋(gx)์ (94 - 56) = 38
=> ์ด ๊ฐ์ด x์ถ ๋ฐฉํฅ ๊ธฐ์ธ๊ธฐ ๋ณํ๋
: y์ถ ๋ฐฉํฅ,, ๋นจ๊ฐ ์ ์ ๊ธฐ์ค์ผ๋ก ์์ชฝ Gray Scale ๊ฐ์ 93์ด๊ณ , ์๋์ชฝ ๊ฐ์ 55
=> y์ถ ๋ฐฉํฅ์ ๊ธฐ์ธ๊ธฐ ๋ณํ๋์ (93 - 55) = 38
: x์ถ ๋ฐฉํฅ ๊ธฐ์ธ๊ธฐ ๋ณํ๋, y์ถ ๋ฐฉํฅ ๊ธฐ์ธ๊ธฐ ๋ณํ๋์ด ๋ชจ๋ 38
=> x์ถ ๋ฐฉํฅ ๊ธฐ์ธ๊ธฐ ๋ณํ๋, y์ถ ๋ฐฉํฅ ๊ธฐ์ธ๊ธฐ ๋ณํ๋์ ํจ๊ป ํํํ ๊ฐ์ด ๊ธฐ์ธ๊ธฐ ๋ฒกํฐ(gradient vector)
2. ํฝ์ (Pixels), ์ (Cells), ๋ธ๋ก(Blocks)
ํฝ์ : ๋ง ๊ทธ๋๋ก ์์ ๋ด ํ๋์ ํฝ์ ๊ฐ์ ์๋ฏธ
์ : ์ด ํฝ์ ๋ค์ ๋ช ๊ฐ ๋ฌถ์ด์ ์๊ทธ๋ฃน์ผ๋ก ๋ง๋ ๊ฒ
๋ธ๋ก : ๋ค์ ์ ์ ๋ช ๊ฐ ๋ฌถ์ด์ ๊ทธ๋ฃน์ผ๋ก ๋ง๋ ๊ฒ
=> ํ๋์ ๋ธ๋ก ์์ ์ ์ฌ๋ฌ ๊ฐ๊ฐ ์๊ณ , ํ๋์ ์ ์์ ํฝ์ ์ฌ๋ฌ ๊ฐ๊ฐ ์์
3. HOG(Histogram of Oriented Gradient)
: HOG๋ ๋ณดํ์ ๊ฒ์ถ์ ์ํด ๋ง๋ค์ด์ง ํน์ง ๋์คํฌ๋ฆฝํฐ
: HOG๋ ์ด๋ฏธ์ง ๊ฒฝ๊ณ์ ๊ธฐ์ธ๊ธฐ ๋ฒกํฐ ํฌ๊ธฐ(magnitude)์ ๋ฐฉํฅ(direction)์ ํ์คํ ๊ทธ๋จ์ผ๋ก ๋ํ๋ด ๊ณ์ฐ
: HOG ๋์คํฌ๋ฆฝํฐ๋ฅผ ๋ง๋ค๊ธฐ ์ํด์๋ ์์ ์์์ ๊ฒ์ถํ๊ณ ์ ํ๋ ์์ญ์ ์๋ฆ
: ์๋ผ๋ธ ์์ญ์ ์๋(window)
import cv2
import numpy as np
img = cv2.imread('img/jk.jpg')
img = np.float32(img) / 255.0
gx = cv2.Sobel(img, cv2.CV_32F, 1, 0)
gy = cv2.Sobel(img, cv2.CV_32F, 0, 1)
magnitude, angle = cv2.cartToPolar(gx, gy)
: ๊ฐ ํฝ์ ์ ๊ธฐ์ค์ผ๋ก ๊ธฐ์ธ๊ธฐ ๋ฒกํฐ๋ฅผ ๊ตฌํด์ผํจ
: ํ์ดํ๋ก ํ์๋ ๊ฒ์ด ๊ธฐ์ธ๊ธฐ ๋ฒกํฐ์
: ๊ธฐ์ธ๊ธฐ ๋ฒกํฐ์ ํฌ๊ธฐ์ ๋ฐฉํฅ์ ํ์คํ ๊ทธ๋จ์ผ๋ก ๋ํ๋ธ ๊ฒ
: ๊ธฐ์ธ๊ธฐ ๋ฒกํฐ์ ๋ฐฉํฅ์ ๊ณ๊ธ(bin)์ผ๋ก ํ๊ณ ํฌ๊ธฐ๋ฅผ ๊ฐ์ผ๋ก ๋์ ํ ํ์คํ ๊ทธ๋จ
: ๊ณ๊ธ(bin)์ 180๋๋ฅผ 20๋์ฉ ์ด 9๊ฐ์ ๊ตฌ๊ฐ์ผ๋ก ๋๋์ด ์ฌ
: 360๋๊ฐ ์๋ 180๋๋ก ํ๋ ์ด์ ๋ ๊ธฐ์ธ๊ธฐ์ ์์์ ์์๊ฐ ๊ฐ์ ๋ฐฉํฅ์ ๋ํ๋
: ์๋ ์ ์ฒด๋ฅผ ํ๋์ ํ์คํ ๊ทธ๋จ์ผ๋ก ๊ณ์ฐํ๋ ๊ฒ์ด ์๋๋ผ ํ๋์ ์ ์ ๊ธฐ์ค์ผ๋ก ํ์คํ ๊ทธ๋จ์ ๊ณ์ฐ
: ํ์คํ ๊ทธ๋จ ๊ณ์ฐ์ ๋ง์น๋ฉด ์ ๊ทํ(normalization) ๊ณผ์ ์ ๊ฑฐ์น๊ธฐ
: ๊ฒฝ๊ณ ๊ฐ ๊ธฐ์ธ๊ธฐ๋ ๋ฐ๊ธฐ์ ๋ฏผ๊ฐ => ๋ฏผ๊ฐ์ฑ์ ์์ ์ฃผ๋ ค๊ณ ์ ๊ทํ
: ์ ๊ทํ๋ฅผ ์ ์ฉํ๋ ค๋ฉด ์๋๋ฅผ ํน์ ํฌ๊ธฐ๋ก ๋๋๊ธฐ => ๋๋๋ ์์ญ์ ๋ธ๋ก(block)
: ๋ธ๋ก ํฌ๊ธฐ๋ ์ผ๋ฐ์ ์ผ๋ก ์ ํฌ๊ธฐ์ 2๋ฐฐ
: ๊ฐ ๋ธ๋ก์ ์ ์ฒด ์๋๋ฅผ ์ํํ๋ฉด์ ์ ๊ทํ => ๊ฒน์น๋ ๋ถ๋ถ์ด ๋ฐ์ํ๋๋ฐ ์ด ๋ถ๋ถ์ ๋ธ๋ก ์คํธ๋ผ์ด๋(blcok stride)
=> ์๋ณธ ์์์์ ๋ณดํ์์ ํด๋นํ๋ ๋ถ๋ถ์ ์๋ฅธ ์์ญ์ ์๋(window)
=> ์ฌ๋์ ๊ฒ์ถํ ๋๋ ๋ณดํต 64 x 128 ํฌ๊ธฐ๋ก ์๋๋ฅผ ์ ํจ
=> ์๋ฅธ ์๋์์ ๊ฐ ํฝ์ ์ ๋ํด ๊ธฐ์ธ๊ธฐ ๋ฒกํฐ๋ฅผ ๊ตฌํจ
=> ํน์ ์์ญ์ ์ค์ฌ์ผ๋ก ๊ธฐ์ธ๊ธฐ ๋ฒกํฐ ํฌ๊ธฐ์ ๋ฐฉํฅ์ ๋ํ ํ์คํ ๊ทธ๋จ์ ๊ตฌํจ
=> ํ์คํ ๊ทธ๋จ์ ๊ณ์ฐํ๊ธฐ ์ํ ์์ญ์ ์ (cell) ์ ์ ๋ณดํต 8 x 8 ํฌ๊ธฐ
=> ํ์คํ ๊ทธ๋จ์ ๊ณ์ฐํ ๋ค ์ ๊ทํ
=> ์ ๊ทํํ๋ ค๋ฉด ์๋๋ฅผ ๋ค์ ์๊ฒ ๋๋์ด์ผ ํ๋๋ฐ, ์ด๋ฅผ ๋ธ๋ก(block)
=> ๋ธ๋ก ํฌ๊ธฐ๋ ๋๊ฒ ์ ํฌ๊ธฐ์ 2๋ฐฐ, ๋ธ๋ก์ ์ ์ฒด ์๋๋ฅผ ์ํํ๋ฉด์ ์ ๊ทํํ๋๋ฐ
=> ๋ธ๋ก์ด ํ๋ฒ์ ์ด๋ํ๋ ๊ฑฐ๋ฆฌ๋ฅผ ๋ธ๋ก ์คํธ๋ผ์ด๋(block stride)
4. HOG ๋์คํฌ๋ฆฝํฐ๋ฅผ ํ์ฉํ ๋ณดํ์ ์ธ์
descriptor = cv2.HOGDescriptor(winSize, blockSize, blockStride, cellSize, nbins)
: HOG ๋์คํฌ๋ฆฝํฐ ์ถ์ถ๊ธฐ ์์ฑ
: ๋ฏธ๋ฆฌ ํ๋ จ๋ SVM ๋ชจ๋ธ(pretrained SVM model)์ ์ ๋ฌ๋ฐ์ ๋ณดํ์๋ฅผ ์ถ์ถ ๊ฐ๋ฅ
- winSize : ์๋ ํฌ๊ธฐ, HOG ์ถ์ถ ์์ญ
- blockSize : ๋ธ๋ก ํฌ๊ธฐ, ์ ๊ทํ ์์ญ
- blockStride : ์ ๊ทํ ๋ธ๋ก ๊ฒน์นจ ํฌ๊ธฐ
- cellSize : ์
ํฌ๊ธฐ, ํ์คํ ๊ทธ๋จ ๊ณ์ฐ ์์ญ
- nbins : ํ์คํ ๊ทธ๋จ ๊ณ๊ธ ์
- descriptor : HOG ํน์ง ๋์คํฌ๋ฆฝํฐ ์ถ์ถ๊ธฐ
hog = descriptor.compute(img)
: HOG ๊ณ์ฐ
- img : ๊ณ์ฐ ๋์ ์ด๋ฏธ์ง
- hog : HOG ํน์ง ๋์คํฌ๋ฆฝํฐ ๊ฒฐ๊ณผ
+ ๋ณดํ์ ์ธ์์ ์ํ ์ฌ์ ํ๋ จ API๋ฅผ ์ ๊ณต
scvmdetector = cv2.HOGDescriptor_getDefaultPeopleDetector() : 64 x 128 ์๋ ํฌ๊ธฐ๋ก ํ๋ จ๋ ๋ชจ๋ธ
scvmdetector = cv2.HOGDescriptor_getDaimlerPeopleDetector() : 48 x 96 ์๋ ํฌ๊ธฐ๋ก ํ๋ จ๋ ๋ชจ๋ธ
descriptor = cv2.HOGDescriptor(winSize, blockSize, blockStride, cellSize, nbins) : HOG ์์ฑ
descriptor.setSVMDetector(svmdetector) : ํ๋ จ๋ SVM ๋ชจ๋ธ ์ค์
rects, weights = descriptor.detectMultiScale(img) : ๊ฐ์ฒด ๊ฒ์ถ
- img : ๊ฒ์ถํ๊ณ ์ ํ๋ ์ด๋ฏธ์ง
- rects : ๊ฒ์ถ๋ ๊ฒฐ๊ณผ ์์ญ ์ขํ N x 4 (x, y, w, h)
- weights : ๊ฒ์ถ๋ ๊ฒฐ๊ณผ ๊ณ์ N x 1
# HOG-SVM ๋ณดํ์ ๊ฒ์ถ
import cv2
# default ๋๋ฑํฐ๋ฅผ ์ํ HOG ๊ฐ์ฒด ์์ฑ ๋ฐ ์ค์ --- โ
hogdef = cv2.HOGDescriptor()
hogdef.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
# dailer ๋๋ฑํฐ๋ฅผ ์ํ HOG ๊ฐ์ฒด ์์ฑ ๋ฐ ์ค์ --- โก
hogdaim = cv2.HOGDescriptor((48,96), (16,16), (8,8), (8,8), 9)
hogdaim.setSVMDetector(cv2.HOGDescriptor_getDaimlerPeopleDetector())
cap = cv2.VideoCapture('img/walking.mp4')
mode = True # ๋ชจ๋ ๋ณํ์ ์ํ ํ๋๊ทธ ๋ณ์
print('Toggle Space-bar to change mode.')
while cap.isOpened():
ret, img = cap.read()
if ret :
if mode:
# default ๋ํ
ํฐ๋ก ๋ณดํ์ ๊ฒ์ถ --- โข
found, _ = hogdef.detectMultiScale(img)
for (x,y,w,h) in found:
cv2.rectangle(img, (x,y), (x+w, y+h), (0,255,255))
else:
# daimler ๋ํ
ํฐ๋ก ๋ณดํ์ ๊ฒ์ถ --- โฃ
found, _ = hogdaim.detectMultiScale(img)
for (x,y,w,h) in found:
cv2.rectangle(img, (x,y), (x+w, y+h), (0,255,0))
cv2.putText(img, 'Detector:%s'%('Default' if mode else 'Daimler'), \
(10,50 ), cv2.FONT_HERSHEY_DUPLEX,1, (0,255,0),1)
cv2.imshow('frame', img)
key = cv2.waitKey(1)
if key == 27:
break
elif key == ord(' '):
mode = not mode
else:
break
cap.release()
cv2.destroyAllWindows()
- Default ๋ณดํ์ ๊ฒ์ถ๊ธฐ์ Daimler ๋ณดํ์ ๊ฒ์ถ๊ธฐ๋ฅผ ์ด์ฉํด ๋ณดํ์๋ฅผ ๊ฒ์ถ
- ์คํ์ด์ค ๋ฐ๋ฅผ ๋๋ฅด๋ฉด ๊ฒ์ถ๊ธฐ ๋ณ๊ฒฝ ๊ฐ๋ฅ
- ๋ ธ๋์ ๋ฐ์ค๋ก ๋ณดํ์๋ฅผ ์ธ์ํ ๊ฒ Default ๋ณดํ์ ๊ฒ์ถ๊ธฐ
- ์ด๋ก์ ๋ฐ์ค๋ก ๋ณดํ์๋ฅผ ์ธ์ํ ๊ฒ Daimler ๋ณดํ์ ๊ฒ์ถ๊ธฐ
- Default ๋ณดํ์ ๊ฒ์ถ๊ธฐ๋ ๋ถํ์ํ ๊ฒ์ถ์ด ์ ์ ๋์ ๋ฉ๋ฆฌ ์๋ ์์ ๋ณดํ์๋ ๊ฒ์ถํ์ง ๋ชปํจ
- Daimler ๋ณดํ์ ๊ฒ์ถ๊ธฐ๋ ๋ฉ๋ฆฌ ์๋ ์์ ๋ณดํ์๋ ๊ฒ์ถํ์ง๋ง ์ผ๊ฐ๋๋ ๊ฑด๋ฌผ ๊ทธ๋ฆผ์๋ ๋ณดํ์๋ก ์ธ์
์์ฐ~ ๋์์๋๋ ๋๋ฆฌ๋น
ํฌ๊ธฐ๊ฐ ์ปค์ ๋ง์ด ์๋ฆฐ๋ค ใ ใ กใ
'๐ฉโ๐ป IoT (Embedded) > Image Processing' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
2D ์์์ฒ๋ฆฌ์ 3D ์์์ฒ๋ฆฌ (0) | 2022.10.18 |
---|---|
1. ๋ฒ ์ด์ฆ ํ๋ฅ ๋ก ์์น ์์ธกํ๊ธฐ โ์ค์ข ๋ ๋ํ์ ์ ์์ ์ฐพ์๋ผโ (0) | 2022.10.17 |
[v0.34]์์์ฒ๋ฆฌ_๊ฐ์ฒด ์ถ์ ์ ์ํ Tracking API (0) | 2022.01.18 |
[v0.33]์์์ฒ๋ฆฌ_๊ดํ ํ๋ฆ(Optical Flow) (0) | 2022.01.18 |
[v0.32]์์์ฒ๋ฆฌ_๋ฐฐ๊ฒฝ ์ ๊ฑฐ (0) | 2022.01.18 |