人妖在线一区,国产日韩欧美一区二区综合在线,国产啪精品视频网站免费,欧美内射深插日本少妇

新聞動(dòng)態(tài)

圖文詳解OpenCV中光流以及視頻特征點(diǎn)追蹤

發(fā)布日期:2022-02-09 08:27 | 文章來(lái)源:站長(zhǎng)之家

這篇博客將介紹光流的概念以及如何使用 Lucas-Kanade 方法估計(jì)光流,并演示如何使用 cv2.calcOpticalFlowPyrLK() 來(lái)跟蹤視頻中的特征點(diǎn)。

1. 效果圖

光流追蹤效果圖如下:

它顯示了一個(gè)球在連續(xù) 5 幀中移動(dòng)。箭頭表示其位移矢量。

不是很?chē)?yán)謹(jǐn)?shù)摹∈韫饬魈卣鼽c(diǎn)追蹤效果圖如下:

它追蹤了視頻中多個(gè)車(chē)的主駕駛、副駕駛,以及行人的邊緣角點(diǎn)的軌跡:

此代碼不檢查下一個(gè)關(guān)鍵點(diǎn)的正確程度。因此即使圖像中的任何特征點(diǎn)消失,光流也有可能找到下一個(gè)看起來(lái)可能靠近它的點(diǎn)。對(duì)于穩(wěn)健的跟蹤,角點(diǎn)應(yīng)該在特定的時(shí)間間隔內(nèi)檢測(cè)點(diǎn)。

過(guò)程圖其一如下:

優(yōu)化版的——稀疏光流特征點(diǎn)追蹤效果如下:

找到特征點(diǎn),每 30 幀對(duì)光流點(diǎn)向后檢查,只保留還存在于屏幕中的特征點(diǎn)。不會(huì)存在如上圖車(chē)已經(jīng)過(guò)去了,還留存有長(zhǎng)長(zhǎng)的不正確的軌跡追蹤線。

過(guò)程圖其一如下:

原圖 VS 密集光流追蹤 gif 效果圖如下:

原圖 VS 密集光流Hsv效果圖其一如下:

2. 原理

2.1 什么是光流?光流追蹤的前提、原理

光流是由物體或相機(jī)的運(yùn)動(dòng)引起的圖像物體在連續(xù)兩幀之間的明顯運(yùn)動(dòng)的模式。它是 2D 矢量場(chǎng),其中每個(gè)矢量是一個(gè)位移矢量,顯示點(diǎn)從第一幀到第二幀的移動(dòng)。

光流追蹤的前提是:1. 對(duì)象的像素強(qiáng)度在連續(xù)幀之間不會(huì)改變;2. 相鄰像素具有相似的運(yùn)動(dòng)。

光流追蹤的原理:

cv2.goodFeaturesToTrack() :Shi-Tomasi 角點(diǎn)檢測(cè)器確定要追蹤的特征點(diǎn)

cv2.calcOpticalFlowPyrLK(): 追蹤視頻中的稀疏特征點(diǎn)

cv2.calcOpticalFlowFarneback(): 追蹤視頻中的密集特征點(diǎn)

取第一幀,檢測(cè)其中的一些 Shi-Tomasi 角點(diǎn),使用 Lucas-Kanade 光流迭代跟蹤這些點(diǎn)。對(duì)于函數(shù) cv2.calcOpticalFlowPyrLK() 傳遞前一幀、前一個(gè)點(diǎn)和下一幀。它返回下一個(gè)點(diǎn)以及一些狀態(tài)編號(hào),如果找到下一個(gè)點(diǎn),則值為 1,否則為零。然后在下一步中迭代地將這些下一個(gè)點(diǎn)作為前一個(gè)點(diǎn)傳遞。

使用 Harris 角點(diǎn)檢測(cè)器 檢查逆矩陣的相似性。它表示角點(diǎn)是更好的跟蹤點(diǎn)。

Shi-Tomasi 角點(diǎn)檢測(cè)器 比 Harris 角點(diǎn)檢測(cè)器效果更好一些;

2.2 光流的應(yīng)用

光流在以下領(lǐng)域有許多應(yīng)用:

  • 運(yùn)動(dòng)的結(jié)構(gòu)
  • 視頻壓縮
  • 視頻穩(wěn)定

2.3 光流的2種方法

OpenCV提供了倆種算法計(jì)算光流,分別通過(guò):cv2.calcOpticalFlowPyrLK()、cv2.calcOpticalFlowFarneback實(shí)現(xiàn);

  • 稀疏光流: 通過(guò) Lucas-Kanade 方法計(jì)算稀疏特征集的光流(使用 Shi-Tomasi 算法檢測(cè)到的角點(diǎn))。
  • 密集光流: 通過(guò) Gunner Farneback 來(lái)尋找密集光流。它計(jì)算幀中所有點(diǎn)的光流。

稀疏光流計(jì)算:

該方法傳遞前一幀、前一個(gè)點(diǎn)和下一幀;
它返回下一個(gè)點(diǎn)以及一些狀態(tài)編號(hào),如果找到下一個(gè)點(diǎn),則值為 1,否則為零。

p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, winSize=(15, 15), maxLevel=2, criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))

- old_gray: 上一幀單通道灰度圖
- frame_gray: 下一幀單通道灰度圖
- prePts:p0上一幀坐標(biāo)pts
- nextPts: None
- winSize: 每個(gè)金字塔級(jí)別上搜索窗口的大小
- maxLevel: 最大金字塔層數(shù)
- criteria:指定迭代搜索算法的終止條件,在指定的最大迭代次數(shù) 10 之后或搜索窗口移動(dòng)小于 0.03

密集光流計(jì)算:

該方法將得到一個(gè)帶有光流向量 (u,v) 的 2 通道陣列??梢哉业剿鼈兊拇笮『头较?,然后對(duì)結(jié)果進(jìn)行顏色編碼以實(shí)現(xiàn)更好的可視化。
在HSV圖像中,方向?qū)?yīng)于圖像的色調(diào),幅度對(duì)應(yīng)于價(jià)值平面。

flow = cv2.calcOpticalFlowFarneback(prvs, next, None, 0.5, 3, 15, 3, 5, 1.2, 0)

- prvs: 上一幀單通道灰度圖
- next: 下一幀單通道灰度圖
- flow: 流 None
- pyr_scale: 0.5經(jīng)典金字塔,構(gòu)建金字塔縮放scale
- level:3 初始圖像的金字塔層數(shù)
- winsize:3 平均窗口大小,數(shù)值越大,算法對(duì)圖像的魯棒性越強(qiáng)
- iterations:15 迭代次數(shù)
- poly_n:5 像素鄰域的參數(shù)多邊形大小,用于在每個(gè)像素中找到多項(xiàng)式展開(kāi)式;較大的值意味著圖像將使用更平滑的曲面進(jìn)行近似,從而產(chǎn)生更高的分辨率、魯棒算法和更模糊的運(yùn)動(dòng)場(chǎng);通常多邊形n=5或7。
- poly_sigma:1.2 高斯標(biāo)準(zhǔn)差,用于平滑導(dǎo)數(shù)
- flags: 可以是以下操作標(biāo)志的組合:OPTFLOW_USE_INITIAL_FLOW:使用輸入流作為初始流近似值。OPTFLOW_FARNEBACK_GAUSSIAN: 使用GAUSSIAN過(guò)濾器而不是相同尺寸的盒過(guò)濾器;

3. 源碼

3.2 稀疏光流追蹤

# 光流追蹤
# 光流追蹤的前提是:1. 對(duì)象的像素強(qiáng)度在連續(xù)幀之間不會(huì)改變;2. 相鄰像素具有相似的運(yùn)動(dòng)。
# - cv2.goodFeaturesToTrack() 確定要追蹤的特征點(diǎn)
# - cv2.calcOpticalFlowPyrLK() 追蹤視頻中的特征點(diǎn)
# 取第一幀,檢測(cè)其中的一些 Shi-Tomasi 角點(diǎn),使用 Lucas-Kanade 光流迭代跟蹤這些點(diǎn)。
# 對(duì)于函數(shù) cv2.calcOpticalFlowPyrLK() 傳遞前一幀、前一個(gè)點(diǎn)和下一幀。它返回下一個(gè)點(diǎn)以及一些狀態(tài)編號(hào),如果找到下一個(gè)點(diǎn),則值為 1,否則為零。
# 然后在下一步中迭代地將這些下一個(gè)點(diǎn)作為前一個(gè)點(diǎn)傳遞。
# USAGE
# python video_optical_flow.py
import imutils
import numpy as np
import cv2
cap = cv2.VideoCapture('images/slow_traffic_small.mp4')
# ShiTomasi角點(diǎn)檢測(cè)的參數(shù)
feature_params = dict(maxCorners=100,
 qualityLevel=0.3,
 minDistance=7,
 blockSize=7)
# Lucas Kanada光流檢測(cè)的參數(shù)
lk_params = dict(winSize=(15, 15),
  maxLevel=2,
  criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
# 構(gòu)建隨機(jī)顏色
color = np.random.randint(0, 255, (100, 3))
# 獲取第一幀并發(fā)現(xiàn)角點(diǎn)
ret, old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)
# 為繪制光流追蹤圖,構(gòu)建一個(gè)Mask
mask = np.zeros_like(old_frame)
num = 0
while (1):
 ret, frame = cap.read()
 if not ret:
  break
 frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
 # 使用迭代Lucas Kanade方法計(jì)算稀疏特征集的光流
 # - old_gray: 上一幀單通道灰度圖
 # - frame_gray: 下一幀單通道灰度圖
 # - prePts:p0上一幀坐標(biāo)pts
 # - nextPts: None
 # - winSize: 每個(gè)金字塔級(jí)別上搜索窗口的大小
 # - maxLevel: 最大金字塔層數(shù)
 # - criteria:指定迭代搜索算法的終止條件,在指定的最大迭代次數(shù)criteria.maxCount之后或搜索窗口移動(dòng)小于criteria.epsilon
 p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)
 # 選擇軌跡點(diǎn)
 good_new = p1[st == 1]
 good_old = p0[st == 1]
 # 繪制軌跡
 for i, (new, old) in enumerate(zip(good_new, good_old)):
  a, b = new.ravel()
  c, d = old.ravel()
  mask = cv2.line(mask, (a, b), (c, d), color[i].tolist(), 2)
  frame = cv2.circle(frame, (a, b), 5, color[i].tolist(), -1)
 img = cv2.add(frame, mask)
 cv2.imshow('frame', img)
 cv2.imwrite('videoof-imgs/' + str(num) + '.jpg', imutils.resize(img, 500))
 print(str(num))
 num = num + 1
 k = cv2.waitKey(30) & 0xff
 if k == 27:
  break
 # 更新之前的幀和點(diǎn)
 old_gray = frame_gray.copy()
 p0 = good_new.reshape(-1, 1, 2)
cv2.destroyAllWindows()
cap.release()

3.2 優(yōu)化版稀疏光流追蹤

# 優(yōu)化后的光流追蹤—Lucas-Kanade tracker
# (當(dāng)不見(jiàn)檢查下一個(gè)關(guān)鍵點(diǎn)的正確程度時(shí),即使圖像中的任何特征點(diǎn)消失,光流也有可能找到下一個(gè)看起來(lái)可能靠近它的點(diǎn)。實(shí)際上對(duì)于穩(wěn)健的跟蹤,角點(diǎn)應(yīng)該在特定的時(shí)間間隔內(nèi)檢測(cè)點(diǎn)。
# 找到特征點(diǎn)后,每 30 幀對(duì)光流點(diǎn)的向后檢查,只選擇好的。)
# Lucas Kanade稀疏光流演示。使用GoodFeatures跟蹤用于跟蹤初始化和匹配驗(yàn)證的回溯幀之間。
# Lucas-Kanade sparse optical flow demo. Uses goodFeaturesToTrack for track initialization and back-tracking for match verification between frames.
# Usage
# pyhton lk_track.py images/slow_traffic_small.mp4
# 按 ESC鍵退出
from __future__ import print_function
import imutils
import numpy as np
import cv2

def draw_str(dst, target, s):
 x, y = target
 cv2.putText(dst, s, (x + 1, y + 1), cv2.FONT_HERSHEY_PLAIN, 1.0, (0, 0, 0), thickness=2, lineType=cv2.LINE_AA)
 cv2.putText(dst, s, (x, y), cv2.FONT_HERSHEY_PLAIN, 1.0, (255, 255, 255), lineType=cv2.LINE_AA)

lk_params = dict(winSize=(15, 15),
  maxLevel=2,
  criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
feature_params = dict(maxCorners=500,
 qualityLevel=0.3,
 minDistance=7,
 blockSize=7)

class App:
 def __init__(self, video_src):
  self.track_len = 10
  self.detect_interval = 30
  self.tracks = []
  self.cam = cv2.VideoCapture(video_src)
  self.frame_idx = 0
 def run(self):
  while True:
_ret, frame = self.cam.read()
if not _ret:
 break
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
vis = frame.copy()
if len(self.tracks) > 0:
 img0, img1 = self.prev_gray, frame_gray
 p0 = np.float32([tr[-1] for tr in self.tracks]).reshape(-1, 1, 2)
 p1, _st, _err = cv2.calcOpticalFlowPyrLK(img0, img1, p0, None, **lk_params)
 p0r, _st, _err = cv2.calcOpticalFlowPyrLK(img1, img0, p1, None, **lk_params)
 d = abs(p0 - p0r).reshape(-1, 2).max(-1)
 good = d < 1
 new_tracks = []
 for tr, (x, y), good_flag in zip(self.tracks, p1.reshape(-1, 2), good):
  if not good_flag:continue
  tr.append((x, y))
  if len(tr) > self.track_len:del tr[0]
  new_tracks.append(tr)
  cv2.circle(vis, (x, y), 2, (0, 255, 0), -1)
 self.tracks = new_tracks
 cv2.polylines(vis, [np.int32(tr) for tr in self.tracks], False, (0, 255, 0))
 draw_str(vis, (20, 20), 'track count: %d' % len(self.tracks))
if self.frame_idx % self.detect_interval == 0:
 mask = np.zeros_like(frame_gray)
 mask[:] = 255
 for x, y in [np.int32(tr[-1]) for tr in self.tracks]:
  cv2.circle(mask, (x, y), 5, 0, -1)
 p = cv2.goodFeaturesToTrack(frame_gray, mask=mask, **feature_params)
 if p is not None:
  for x, y in np.float32(p).reshape(-1, 2):self.tracks.append([(x, y)])
self.prev_gray = frame_gray
cv2.imshow('lk_track', vis)
print(self.frame_idx)
cv2.imwrite('videoOof-imgs/' + str(self.frame_idx) + '.jpg', imutils.resize(vis, 500))
self.frame_idx += 1
ch = cv2.waitKey(1)
if ch == 27:
 break
def main():
 import sys
 try:
  video_src = sys.argv[1]
 except:
  video_src = 0
 App(video_src).run()
 print('Done')

if __name__ == '__main__':
 print(__doc__)
 main()
 cv2.destroyAllWindows()

3.3 密集光流追蹤

# OpenCV中的密集光流
# Lucas-Kanade 方法計(jì)算稀疏特征集的光流(使用 Shi-Tomasi 算法檢測(cè)到的角點(diǎn))。
# OpenCV 提供了另一種算法: Gunner Farneback 來(lái)尋找密集光流。它計(jì)算幀中所有點(diǎn)的光流。
# 通過(guò)cv2.calcOpticalFlowFarneback() 將得到一個(gè)帶有光流向量 (u,v) 的 2 通道陣列??梢哉业剿鼈兊拇笮『头较?,然后對(duì)結(jié)果進(jìn)行顏色編碼以實(shí)現(xiàn)更好的可視化。
# 在HSV圖像中,方向?qū)?yīng)于圖像的色調(diào),幅度對(duì)應(yīng)于價(jià)值平面。
import cv2
import imutils
import numpy as np
cap = cv2.VideoCapture('images/slow_traffic_small.mp4')
ret, frame1 = cap.read()
prvs = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
hsv = np.zeros_like(frame1)
hsv[..., 1] = 255
num = 0
while (1):
 ret, frame2 = cap.read()
 if not ret:
  break
 next = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
 # 使用迭代Gunner Farneback 方法計(jì)算密集特征的光流
 # - prvs: 上一幀單通道灰度圖
 # - next: 下一幀單通道灰度圖
 # - flow: 流 None
 # - pyr_scale: 0.5經(jīng)典金字塔,構(gòu)建金字塔縮放scale
 # - level:3 初始圖像的金字塔層數(shù)
 # - winsize:3 平均窗口大小,數(shù)值越大,算法對(duì)圖像的魯棒性越強(qiáng)
 # - iterations:15 迭代次數(shù)
 # - poly_n:5 像素鄰域的參數(shù)多邊形大小,用于在每個(gè)像素中找到多項(xiàng)式展開(kāi)式;較大的值意味著圖像將使用更平滑的曲面進(jìn)行近似,從而產(chǎn)生更高的分辨率、魯棒算法和更模糊的運(yùn)動(dòng)場(chǎng);通常多邊形n=5或7。
 # - poly_sigma:1.2 高斯標(biāo)準(zhǔn)差,用于平滑導(dǎo)數(shù)
 # - flags: 可以是以下操作標(biāo)志的組合:OPTFLOW_USE_INITIAL_FLOW:使用輸入流作為初始流近似值。OPTFLOW_FARNEBACK_GAUSSIAN: 使用GAUSSIAN過(guò)濾器而不是相同尺寸的盒過(guò)濾器;
 flow = cv2.calcOpticalFlowFarneback(prvs, next, 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)
 rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
 cv2.imshow('Origin VS frame2', np.hstack([frame2, rgb]))
 cv2.imwrite('dof-imgs/' + str(num) + '.jpg', imutils.resize(np.hstack([frame2, rgb]), 600))
 k = cv2.waitKey(30) & 0xff
 num = num + 1
 if k == 27:
  break
 elif k == ord('s'):
  cv2.imwrite('dof-imgs/origin VS dense optical flow HSVres' + str(num) + ".jpg",
  imutils.resize(np.hstack([frame2, rgb]), width=800))
 prvs = next
cap.release()
cv2.destroyAllWindows()

參考 https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_video/py_lucas_kanade/py_lucas_kanade.html#lucas-kanade

總結(jié)

到此這篇關(guān)于OpenCV中光流以及視頻特征點(diǎn)追蹤的文章就介紹到這了,更多相關(guān)OpenCV光流及視頻特征點(diǎn)追蹤內(nèi)容請(qǐng)搜索本站以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持本站!

香港服務(wù)器租用

版權(quán)聲明:本站文章來(lái)源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請(qǐng)保持原文完整并注明來(lái)源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來(lái)源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來(lái),僅供學(xué)習(xí)參考,不代表本站立場(chǎng),如有內(nèi)容涉嫌侵權(quán),請(qǐng)聯(lián)系alex-e#qq.com處理。

相關(guān)文章

實(shí)時(shí)開(kāi)通

自選配置、實(shí)時(shí)開(kāi)通

免備案

全球線路精選!

全天候客戶服務(wù)

7x24全年不間斷在線

專(zhuān)屬顧問(wèn)服務(wù)

1對(duì)1客戶咨詢顧問(wèn)

在線
客服

在線客服:7*24小時(shí)在線

客服
熱線

400-630-3752
7*24小時(shí)客服服務(wù)熱線

關(guān)注
微信

關(guān)注官方微信
頂部