অধ্যায়Phase 3 · ক্লাসিক্যাল কম্পিউটার ভিশন
3.4 20 মিনিট পড়া

Optical Flow

Pixel-এর গতি ট্র্যাক করা।

🎬 গল্প দিয়ে শুরু
একটি গাড়ি ভিডিওতে কত speed-এ চলছে? একটি pixel এক frame থেকে পরের frame-এ কোথায় গেল? এই প্রশ্নের উত্তর — Optical Flow

ধারণা

Optical flow = consecutive দুটি frame-এর মধ্যে pixel-এর apparent motion vector। দুটি ধরন:

  • Sparse — কিছু selected keypoint-এর motion (Lucas-Kanade)।
  • Dense — প্রতিটি pixel-এর motion (Farneback)।

Lucas-Kanade (Sparse)

python
lk_flow.py
import cv2, numpy as np

cap = cv2.VideoCapture("road.mp4")
ret, prev = cap.read()
prev_g = cv2.cvtColor(prev, cv2.COLOR_BGR2GRAY)

p0 = cv2.goodFeaturesToTrack(prev_g, maxCorners=100,
                             qualityLevel=0.3, minDistance=7)
mask = np.zeros_like(prev)

while True:
    ret, frame = cap.read()
    if not ret: break
    g = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    p1, st, err = cv2.calcOpticalFlowPyrLK(prev_g, g, p0, None)
    good_new = p1[st==1]; good_old = p0[st==1]

    for (a,b),(c,d) in zip(good_new, good_old):
        cv2.line(mask, (int(a),int(b)), (int(c),int(d)), (0,255,0), 2)
        cv2.circle(frame, (int(a),int(b)), 4, (0,0,255), -1)

    out = cv2.add(frame, mask)
    cv2.imshow("LK", out)
    if cv2.waitKey(30) == 27: break

    prev_g = g.copy()
    p0 = good_new.reshape(-1,1,2)
কেন pyrLK?
Pyramid-এ multi-scale flow হিসাব করে — বড় motion-ও ধরা যায়।

Farneback (Dense)

python
import cv2, numpy as np

cap = cv2.VideoCapture("crowd.mp4")
ret, prev = cap.read()
prev_g = cv2.cvtColor(prev, cv2.COLOR_BGR2GRAY)
hsv = np.zeros_like(prev); hsv[...,1] = 255

while True:
    ret, frame = cap.read()
    if not ret: break
    g = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    flow = cv2.calcOpticalFlowFarneback(
        prev_g, g, None,
        0.5, 3, 15, 3, 5, 1.2, 0)

    mag, ang = cv2.cartToPolar(flow[...,0], flow[...,1])
    hsv[...,0] = ang * 180 / np.pi / 2
    hsv[...,2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)
    bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
    cv2.imshow("Dense flow", bgr)
    if cv2.waitKey(30) == 27: break
    prev_g = g

রং = motion direction, brightness = speed। Crowd analysis, weather radar — সব এই pattern।

Application ideas

  • Vehicle speed estimation (pixel/frame × calibration → m/s)।
  • Crowd density ও flow direction।
  • Stabilization — camera shake হিসেব করে inverse apply।
  • Sport analytics — player movement heatmap।
প্র্যাকটিস টাস্ক
  1. নিজের webcam-এ হাত নাড়িয়ে LK flow দেখান।
  2. Farneback flow magnitude > threshold দিয়ে motion-region mask তৈরি করুন।
  3. একটি traffic video থেকে শুধু left-to-right চলা গাড়ির flow আলাদা করে দেখান।

সারসংক্ষেপ

  • Optical flow = frame-to-frame pixel motion vector।
  • Lucas-Kanade = sparse keypoint, fast; Farneback = dense, expensive।
  • Pyramid version বড় motion সহ্য করে।
  • Tracking, stabilization, behavior analysis-এর ভিত্তি।