π 곡λΆνλ μ§μ§μνμΉ΄λ μ²μμ΄μ§?
[v0.33]μμμ²λ¦¬_κ΄ν νλ¦(Optical Flow) λ³Έλ¬Έ
[v0.33]μμμ²λ¦¬_κ΄ν νλ¦(Optical Flow)
μ§μ§μνμΉ΄ 2022. 1. 18. 00:34220118 μμ±
<λ³Έ λΈλ‘κ·Έλ κ·νμ΄ μμ¬λμ λΈλ‘κ·Έλ₯Ό μ°Έκ³ ν΄μ 곡λΆνλ©° μμ±νμμ΅λλ€>
1. κ΄ν νλ¦(Optical Flow)
: κ΄ν νλ¦μ΄λ μμ λ΄ λ¬Όμ²΄μ μμ§μ ν¨ν΄
: μ΄μ νλ μκ³Ό λ€μ νλ μ κ° ν½μ μ΄ μ΄λν λ°©ν₯κ³Ό 거리 λΆν¬
: κ΄ν νλ¦μΌλ‘ μμ λ΄ λ¬Όμ²΄κ° μ΄λ λ°©ν₯μΌλ‘ μΌλ§λ§νΌ μμ§μλμ§ νμ κ°λ₯
: μΆκ° μ°μ°μ νλ©΄ 물체μ μμ§μμ μμΈ‘ κ°λ₯
: κ΄ν νλ¦μ λ€μ λ κ°μ§ μ¬μ€μ κ°μ
1. μ°μλ νλ μ μ¬μ΄μμ μμ§μ΄λ 물체μ ν½μ
κ°λ(intensity)λ λ³ν¨μ΄ μλ€.
2. μ΄μνλ ν½μ
μ λΉμ·ν μμ§μμ κ°λλ€.
: κ΄ν νλ¦μ κ³μ°νλ λ°©λ²μ λ κ°μ§
1. μΌλΆ ν½μ λ§ κ³μ°νλ ν¬μ(sparse) κ΄ν νλ¦
2. μμ μ 체 ν½μ μ λͺ¨λ κ³μ°νλ λ°μ§(dense) κ΄ν νλ¦
2. 루카μ€-μΉ΄λλ°(Lucas-Kanade) μκ³ λ¦¬μ¦
: κ΄ν νλ¦μ μ΄μνλ ν½μ μ΄ λΉμ·νκ² μμ§μΈλ€κ³ κ°μ
: 루카μ€-μΉ΄λλ° μκ³ λ¦¬μ¦μ μ΄ κ°μ μ μ΄μ©νλ μκ³ λ¦¬μ¦
: μ΄μνλ ν½μ μ λΉμ·ν μμ§μμ κ°λλ€κ³ μκ°νκ³ κ΄ν νλ¦μ νμ
: μμ μλ(3 x 3 patch)λ₯Ό μ¬μ©νμ¬ μμ§μμ κ³μ° -> 물체 μμ§μμ΄ ν¬λ©΄ λ¬Έμ (μλ ν¬κΈ°κ° μκΈ° λλ¬Έ)
: κ°μ νκΈ° μν΄ μ΄λ―Έμ§ νΌλΌλ―Έλλ₯Ό μ¬μ©
: μ΄λ―Έμ§ νΌλΌλ―Έλ μμͺ½μΌλ‘ κ°μλ‘(μ΄λ―Έμ§κ° μμμ§μλ‘) μμ μμ§μμ ν°κ° μ λκ³
ν° μμ§μμ μμ μμ§μ κ°μ 보μ (ν° μμ§μλ κ°μ§ κ°λ₯)
nextPts, status, err = cv2.calcOpticalFlowPyrLK(prevImg, nextImg, prevPts, nextPts, status, err, wirnSize, maxLevel, criteria, flags, minEigThreshold)
- prevImg : μ΄μ νλ μ μμ
- nextImg : λ€μ νλ μ μμ
- prevPts : μ΄μ νλ μμ μ½λ νΉμ§μ , cv2.goodFeaturesToTrack()μΌλ‘ κ²μΆ
- nextPst : λ€μ νλ μμμ μ΄λν μ½λ νΉμ§μ
- status : κ²°κ³Ό μν 벑ν°, nextPtsμ κ°μ κΈΈμ΄, λμμ μ΄ μμΌλ©΄ 1, μμΌλ©΄ 0
- err : κ²°κ³Ό μλ¬ λ²‘ν°, λμμ κ°μ μ€μ°¨
- winSize=(21,21) : κ° μ΄λ―Έμ§ νΌλΌλ―Έλμ κ²μ μλ ν¬κΈ°
- maxLevel=3 : μ΄λ―Έμ§ νΌλΌλ―Έλ κ³μΈ΅ μ
- criteria=(COUNT+EPS, 30, 0.01) : λ°λ³΅ νμ μ€μ§ μ건
- cv2.TERM_CRITERIA_EPS : μ νλκ° epsilonλ³΄λ€ μμΌλ©΄ μ€μ§
- cv2.TERM_CRITERIA_MAX_ITER : max_iter νμλ₯Ό μ±μ°λ©΄ μ€μ§
- cv2.TERM_CRITERIA_COUNT : MAX_ITERμ λμΌ
- max_iter : μ΅λ λ°λ³΅ νμ
- epsilon : μ΅μ μ νλ
- flgs=0 : μ°μ° λͺ¨λ
- 0 : prevPtsλ₯Ό nextPtsμ μ΄κΈ° κ°μΌλ‘ μ¬μ©
- cv2.OPTFLOW_USE_INITAL_FLOW : nextPtsμ κ°μ μ΄κΈ° κ°μΌλ‘ μ¬μ©
- cv2.OPTFLOW_LK_GET_MIN_EIGENVALS : μ€μ°¨λ₯Ό μ΅μ κ³ μ κ°μΌλ‘ κ³μ°
- minEigThreshold=1e-4 : λμμ κ³μ°μ μ¬μ©ν μ΅μ μκ³ κ³ μ κ°
: μμ λ΄ ν½μ μ 체λ₯Ό νλ²μ κ³μ°νμ§ μμ
: cv2.goodFeaturesToTrack() ν¨μλ‘ μ»μ νΉμ§μ λ§ νμ©νμ¬ κ³μ°
: λ νΉμ§μ μ΄ μλ‘ λμνλ©΄ status λ³μκ° 1, κ·Έλ μ§ μμΌλ©΄ 0
: maxLevel=0μ΄λ©΄ μ΄λ―Έμ§ νΌλΌλ―Έλλ₯Ό μ¬μ©νμ§ X
# calcOpticalFlowPyrLK μΆμ
import numpy as np, cv2
cap = cv2.VideoCapture('img/walking3.mp4')
fps = cap.get(cv2.CAP_PROP_FPS) # νλ μ μ ꡬνκΈ°
delay = int(1000/fps)
# μΆμ κ²½λ‘λ₯Ό 그리기 μν λλ€ μμ
color = np.random.randint(0,255,(200,3))
lines = None #μΆμ μ μ 그릴 μ΄λ―Έμ§ μ μ₯ λ³μ
prevImg = None # μ΄μ νλ μ μ μ₯ λ³μ
# calcOpticalFlowPyrLK μ€μ§ μ건 μ€μ
termcriteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)
while cap.isOpened():
ret,frame = cap.read()
if not ret:
break
img_draw = frame.copy()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# μ΅μ΄ νλ μ κ²½μ°
if prevImg is None:
prevImg = gray
# μΆμ μ 그릴 μ΄λ―Έμ§λ₯Ό νλ μ ν¬κΈ°μ λ§κ² μμ±
lines = np.zeros_like(frame)
# μΆμ μμμ μν μ½λ κ²μΆ ---β
prevPt = cv2.goodFeaturesToTrack(prevImg, 200, 0.01, 10)
else:
nextImg = gray
# μ΅ν°μ»¬ νλ‘μ°λ‘ λ€μ νλ μμ μ½λμ μ°ΎκΈ° ---β‘
nextPt, status, err = cv2.calcOpticalFlowPyrLK(prevImg, nextImg, \
prevPt, None, criteria=termcriteria)
# λμμ μ΄ μλ μ½λ, μμ§μΈ μ½λ μ λ³ ---β’
prevMv = prevPt[status==1]
nextMv = nextPt[status==1]
for i,(p, n) in enumerate(zip(prevMv, nextMv)):
px,py = p.ravel()
nx,ny = n.ravel()
# μ΄μ μ½λμ μλ‘μ΄ μ½λμ μ 그리기 ---β£
cv2.line(lines, (px, py), (nx,ny), color[i].tolist(), 2)
# μλ‘μ΄ μ½λμ μ 그리기
cv2.circle(img_draw, (nx,ny), 2, color[i].tolist(), -1)
# λμ λ μΆμ μ μ μΆλ ₯ μ΄λ―Έμ§μ ν©μ± ---β€
img_draw = cv2.add(img_draw, lines)
# λ€μ νλ μμ μν νλ μκ³Ό μ½λμ μ΄μ
prevImg = nextImg
prevPt = nextMv.reshape(-1,1,2)
cv2.imshow('OpticalFlow-LK', img_draw)
key = cv2.waitKey(delay)
if key == 27 : # Esc:μ’
λ£
break
elif key == 8: # Backspace:μΆμ μ΄λ ₯ μ§μ°κΈ°
prevImg = None
cv2.destroyAllWindows()
cap.release()
- cv2.goodFeatureToTrack() ν¨μλ‘ μ΄μ νλ μμ νΉμ§μ μ κ²μΆ
- cv2.calcOpticalFlowPyrLK() ν¨μλ‘ κ΄ν νλ¦μ κ³μ°ν΄ λ€μ νλ μμ νΉμ§μ μ°Ύμ
- μ΄μ νλ μκ³Ό λ€μ νλ μ νΉμ§μ μ€ μ λμλλ νΉμ§μ λ§ μ λ³νμ¬ μ κ³Ό μ μΌλ‘ νμ
- μλ³Έ μ΄λ―Έμ§μ μΆμ μ μ ν©μ±νλ λ°©μμΌλ‘ νν
- λλ λ λ―νλ€κ° μ€λ₯ λλΉ... κΉλΉ λ³΄κ³ μΆμλλ°
3. κ΅°λλ₯΄ νλλ°±(Gunner Farneback) μκ³ λ¦¬μ¦
: λ°μ§ λ°©μμΌλ‘ κ΄ν νλ¦μ κ³μ°νλ μκ³ λ¦¬μ¦
: λ°μ§ λ°©μμ μμ μ 체μ ν½μ μ νμ©ν΄ κ΄ν νλ¦μ κ³μ°
flow = cv2.calcOpticalFlowFarneback(prev, next, flow, pyr_scale, levels, winsize, iterations, poly_n, poly_sigma, flags)
- prev, next : μ΄μ , μ΄ν νλ μ
- flow : κ΄ν νλ¦ κ³μ° κ²°κ³Ό, κ° ν½μ
μ΄ μ΄λν 거리 (μ
λ ₯κ³Ό λμΌν ν¬κΈ°)
- pyr_scale : μ΄λ―Έμ§ νΌλΌλ―Έλ μ€μΌμΌ
- levels : μ΄λ―Έμ§ νΌλΌλ―Έλ κ°μ
- winsize : νκ· μλ ν¬κΈ°
- iterations : κ° νΌλΌλ―Έλμμ λ°λ³΅ν νμ
- poly_n : λ€νμ κ·Όμ¬λ₯Ό μν μ΄μ ν¬κΈ°, 5 λλ 7
- poly_sigma : λ€νμ κ·Όμ¬μμ μ¬μ©ν κ°μ°μμ μκ·Έλ§ (poly_n=5μΌ λλ 1.1, poly_n=7μΌ λλ 1.5)
- flags : μ°μ° λͺ¨λ
- cv2.OPTFLOW_USE_INITAL_FLOW : flow κ°μ μ΄κΈ° κ°μΌλ‘ μ¬μ©
- cv2.OPTFLOW_FARNEBACK_GAUSSIAN : λ°μ€ νν° λμ κ°μ°μμ νν° μ¬μ©
: λ°μ§ κ΄ν νλ¦μ ν¬μ κ΄ν νλ¦κ³Ό λ€λ₯΄κ² μμ μ 체 ν½μ μ νμ©ν΄ κ³μ°
: μΆμ ν νΉμ§μ μ λ°λ‘ μ λ¬ν νμκ° μμ
: μ 체 ν½μ μ νμ©ν΄ κ³μ°νλ―λ‘ μλκ° λλ¦Ό
# calcOPticalFlowFarneback μΆμ
import cv2, numpy as np
# νλ‘μ° κ²°κ³Ό 그리기 ---β
def drawFlow(img,flow,step=16):
h,w = img.shape[:2]
# 16ν½μ
κ°κ²©μ 그리λ μΈλ±μ€ ꡬνκΈ° ---β‘
idx_y,idx_x = np.mgrid[step/2:h:step,step/2:w:step].astype(np.int)
indices = np.stack( (idx_x,idx_y), axis =-1).reshape(-1,2)
for x,y in indices: # μΈλ±μ€ μν
# κ° κ·Έλ¦¬λ μΈλ±μ€ μμΉμ μ 그리기 ---β’
cv2.circle(img, (x,y), 1, (0,255,0), -1)
# κ° κ·Έλ¦¬λ μΈλ±μ€μ ν΄λΉνλ νλ‘μ° κ²°κ³Ό κ° (μ΄λ 거리) ---β£
dx,dy = flow[y, x].astype(np.int)
# κ° κ·Έλ¦¬λ μΈλ±μ€ μμΉμμ μ΄λν 거리 λ§νΌ μ 그리기 ---β€
cv2.line(img, (x,y), (x+dx, y+dy), (0,255, 0),2, cv2.LINE_AA )
prev = None # μ΄μ νλ μ μ μ₯ λ³μ
cap = cv2.VideoCapture('img/walking.mp4')
fps = cap.get(cv2.CAP_PROP_FPS) # νλ μ μ ꡬνκΈ°
delay = int(1000/fps)
while cap.isOpened():
ret,frame = cap.read()
if not ret: break
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
# μ΅μ΄ νλ μ κ²½μ°
if prev is None:
prev = gray # 첫 μ΄μ νλ μ --- β₯
else:
# μ΄μ , μ΄ν νλ μμΌλ‘ μ΅ν°μ»¬ νλ‘μ° κ³μ° ---β¦
flow = cv2.calcOpticalFlowFarneback(prev,gray,None,\
0.5,3,15,3,5,1.1,cv2.OPTFLOW_FARNEBACK_GAUSSIAN)
# κ³μ° κ²°κ³Ό 그리기, μ μΈν ν¨μ νΈμΆ ---β§
drawFlow(frame,flow)
# λ€μ νλ μμ μν΄ μ΄μ ---β¨
prev = gray
cv2.imshow('OpticalFlow-Farneback', frame)
if cv2.waitKey(delay) == 27:
break
cap.release()
cv2.destroyAllWindows()
- drawFlow() ν¨μλ‘ 16ν½μ κ°κ²©μΌλ‘ 격μ λͺ¨μμ μ μ μ°μ
- κ° μ μμ ν΄λΉνλ ν½μ μ΄ μ΄λν λ§νΌ μ μΌλ‘ νμ
- ν¬μ κ΄ν νλ¦κ³Ό λ€λ₯΄κ² λ°μ§ κ΄ν νλ¦μ μμ μ 체μμ μΌμ΄λλ μμ§μμ κ°μ§
- μ λ리λ€!!!
κ΅Ώ
'π©βπ» IoT (Embedded) > Image Processing' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[v0.35]μμμ²λ¦¬_νΉμ§ 맀μΉ(Feature Matching) (0) | 2022.01.18 |
---|---|
[v0.34]μμμ²λ¦¬_κ°μ²΄ μΆμ μ μν Tracking API (0) | 2022.01.18 |
[v0.32]μμμ²λ¦¬_λ°°κ²½ μ κ±° (0) | 2022.01.18 |
[v0.31]μμμ²λ¦¬_μ¬λ°λ₯Έ 맀μΉμ μ°ΎκΈ° (0) | 2022.01.17 |
[v0.30]μμμ²λ¦¬_νΉμ§ 맀μΉ(Feature Matching) (0) | 2022.01.16 |