Opencv計算機視覺編程攻略-第十三節 跟蹤視頻中的物品

? ? ? 這是opencv系列的最后一節,主要學習視頻序列,上一節介紹了讀取、處理和存儲視頻的工具,本文將介紹幾種跟蹤圖像序列中運動物體的算法。可見運動或表觀運動,是物體以不同的速度在不同的方向上移動,或者是因為相機在移動(或者兩者都有)。在很多應用程序中,跟蹤表觀運動都是極其重要的。它可用來追蹤運動中的物體,以測定它們的速度、判斷它們的目的地。對于手持攝像機拍攝的視頻,可以用這種方法消除抖動或減小抖動幅度,使視頻更加平穩。運動估值還可用于視頻編碼,用以壓縮視頻,便于傳輸和存儲。

目錄

1. 跟蹤視頻中的特征點

2. 估算光流

3. 跟蹤視頻中的物體


1. 跟蹤視頻中的特征點

? ? ? ? ?被跟蹤的運動可以是稀疏的(圖像的少數位置上有運動,稱為稀疏運動),也可以是稠密的(圖像的每個像素都有運動,稱為稠密運動)。在啟動跟蹤過程時,首先要在最初的幀中檢測特征點,然后在下一幀中跟蹤這些特征點,如果想找到特征點在下一幀的新位置,就必須在它原來位置的周圍進行搜索。這個功能由函數cv::calcOpticalFlowPyrLK 實現。在函數中輸入兩個連續的幀和第一幅圖像中特征點的向量,將返回新的特征點位置的向量。

? ? ? 要逐幀地跟蹤特征點,就必須在后續幀中定位特征點的新位置。假設每個幀中特征點的強度
值是不變的,這個過程就是尋找如下的位移(u, v):

? ? ? 其中It 和It+1 分別是當前幀和下一個瞬間的幀。強度值不變的假設普遍適用于相鄰圖像上的
微小位移。我們可使用泰勒展開式得到近似方程式(包含圖像導數):

? ? ? ?根據第二個方程式,可以得到另一個方程式(根據強度值不變的假設,去掉了兩個表示強度
值的項)

? ? ? ? 這就是基本的光流約束方程,也稱作亮度恒定方程,Lukas-Kanade 特征跟蹤算法使用了這個約束方程。除此之外,該算法還做了一個假設,即特征點鄰域中所有點的位移量是相等的。因此,我們可以將光流約束應用到所有位移量為(u, v)的點(u 和v 還是未知的)。這樣就得到了更多的方程式,數量超過未知數的個數(兩個),因此可以在均方意義下解出這個方程組。

? ? ? ?在實際應用中,我們采用迭代的方法來求解。為了使搜索更高效且適應更大的位移量,OpenCV? 還提供了在不同分辨率下進行計算的方法:默認的圖像等級數量為3,窗口大小為15,還可以設定一個終止條件,符合這個條件時就停止迭代搜索。

? ? ? cv::calcOpticalFlowPyrLK 函數的第六個參數是剩余均方誤差,用于評定跟蹤的質量。第五個參數包含二值標志,表示是否成功跟蹤了對應的點

// 1. 特征點檢測方法
void detectFeaturePoints() {// 檢測特征點cv::goodFeaturesToTrack(gray, // 圖像features, // 輸出檢測到的特征點max_count, // 特征點的最大數量qlevel, // 質量等級minDist); // 特征點之間的最小差距
}// 2 法根據應用程序定義的條件剔除部分被跟蹤的特征點。這里剔除靜止的特征點(還有不能被cv::calcOpticalFlowPyrLK 函數跟蹤的特征點)。我們假定靜止的點屬于背景部分,可以忽略:
// 判斷需要保留的特征點
bool acceptTrackedPoint(int i) {return status[i] &&// 如果特征點已經移動(abs(points[0][i].x-points[1][i].x)+(abs(points[0][i].y-points[1][i].y))>2);
}// 3 處理被跟蹤的特征點,具體做法是在當前幀畫直線,連接特征點和它們的初始位置(即第一次檢測到它們的位置):
// 處理當前跟蹤的特征點
void handleTrackedPoints(cv:: Mat &frame, cv:: Mat &output) {// 遍歷所有特征點for (int i= 0; i < points[1].size(); i++ ) {// 畫線和圓cv::line(output, initial[i], // 初始位置points[1][i], // 新位置cv::Scalar(255,255,255));cv::circle(output, points[1][i], 3,cv::Scalar(255,255,255),-1);
}
}


2. 估算光流

? ? ? ? 通常關注視頻序列中運動的部分,即場景中不同元素的三維運動在成像平面上的投影。三維運動向量的投影圖被稱作運動場。但是在只有一個相機傳感器的情況下,是不可能直接測量三維運動的,我們只能觀察到幀與幀之間運動的亮度模式,亮度模式上的表觀運動被稱作光流。通常認為運動場和光流是等同的,但其實不一定:典型的例子是觀察均勻的物體;例如相機在白色的墻壁前移動時就不產生光流。

? ? ? 估算光流其實就是量化圖像序列中亮度模式的表觀運動。首先來看視頻中某個時刻的一幀畫
面。觀察當前幀的某個像素(x, y),我們要知道它在下一幀會移動到哪個位置。也就是說,這個點
的坐標在隨著時間變化(表示為(x(t), y(t))),而我們要估算出這個點的速度(dx/dt, dy/dt),對應的幀中獲取這個點在t 時刻的亮度,表示為I(x(t), y(t),t),根據圖像亮度恒定的假設:

? ? ? 這個約束條件可以用基于光流的拉普拉斯算子的公式表示:

? ? ? ?現在要做的就是找到光流場,使亮度恒定公式的偏差和光流向量的拉普拉斯算子都達到最
小值,估算稠密光流的方法有很多,可以使用cv::Algorithm的子類cv::DualTVL1OpticalFlow。

? ? ? ? 所得結果是二維向量(cv::Point)組成的圖像,每個二維向量表示一個像素在兩個幀之
間的變化值。要展示結果,就必須顯示這些向量。為此我們創建了一個函數,用來創建光流場的圖像映射。為控制向量的可見性,需要使用兩個參數:步長(間隔一定像素)和縮放因子,

// 1. 創建光流算法
cv::Ptr<cv::DualTVL1OpticalFlow> tvl1 = cv::createOptFlow_DualTVL1();
這個實例已經可以使用了,所以只需調用計算兩個幀之間的光流場的方法即可:
cv::Mat oflow; // 二維光流向量的圖像
// 計算frame1 和frame2 之間的光流
tvl1->calc(frame1, frame2, oflow);// 2. 繪制光流向量圖
void drawOpticalFlow(const cv::Mat& oflow, // 光流
cv::Mat& flowImage, // 繪制的圖像
int stride, // 顯示向量的步長
float scale, // 放大因子
const cv::Scalar& color) // 顯示向量的顏色
{
// 必要時創建圖像
if (flowImage.size() != oflow.size()) {
flowImage.create(oflow.size(), CV_8UC3);
flowImage = cv::Vec3i(255,255,255);
}
// 對所有向量,以stride 作為步長
for (int y = 0; y < oflow.rows; y += stride)
for (int x = 0; x < oflow.cols; x += stride) {
// 獲取向量
cv::Point2f vector = oflow.at< cv::Point2f>(y, x);
// 畫線條
cv::line(flowImage, cv::Point(x,y),
cv::Point(static_cast<int>(x + scale*vector.x + 0.5),
static_cast<int>(y + scale*vector.y + 0.5)),
color);
// 畫頂端圓圈
cv::circle(flowImage,
cv::Point(static_cast<int>(x + scale*vector.x + 0.5),
static_cast<int>(y + scale*vector.y + 0.5)),
1, color, -1);
}
}

? ? ? 前面使用的方法被稱作雙DV L1 方法,由兩部分組成。第一部分使用光滑約束,使光流梯度的絕對值(不是平方值)最小化;選用絕對值可以削弱平滑度帶來的影響,尤其是對于不連續的區域,運動物體和背景部分的光流向量的差別很大。第二部分使用一階泰勒近似,使亮度恒定約束公式線性化。?


3. 跟蹤視頻中的物體

? ? ?在很多應用程序中,更希望能夠跟蹤視頻中一個特定的運動物體。為此要先標識出該物體,然后在很長的圖像序列中對它進行跟蹤。這是一個很有挑戰性的課題,因為隨著物體在場景中的運動,物體的圖像會因視角和光照改變、非剛體運動、被遮擋等原因而不斷變化

import cv2	 # type: ignore
import numpy as np
# Illustration of the Median Tracker principle
image1 = cv2.imread("E:/CODE/images/goose/goose130.bmp", 0)
image_show = cv2.imread("E:/CODE/images/goose/goose130.bmp")
#define a regular grid of points
grid = []
x,y,width,height = 290, 100, 65, 40
for i in range(10):for j in range(10):p = (x+i*width/10,y+j*height/10)grid.append(p)
grid = np.array(grid, dtype=np.float32)
#track in next image
image2 = cv2.imread("E:/CODE/images/goose/goose131.bmp",0)
lk_params = []lk_params = dict(winSize=(10, 10),maxLevel=2,criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
# ShiTomasi corner detection的參數
feature_params = dict(maxCorners=300,qualityLevel=0.3,minDistance=7,blockSize=7)p0 = cv2.goodFeaturesToTrack(image1, mask=None, **feature_params)
#grid 從22*2 維度調整為22*1*2
grid = grid.reshape(-1,1,2)
kp2, st, err =cv2.calcOpticalFlowPyrLK(image1, image2, grid, None, **lk_params)   
#good_new = kp2[st == 1]
for i in grid:cv2.circle(image_show, (int(i[0][0]),int(i[0][1])), 1, (255, 255, 255), 3)for i in kp2:cv2.circle(image_show, (int(i[0][0]),int(i[0][1])), 1, (255, 0, 255), 3)cv2.imshow("Tracked points", image_show)cv2.waitKey()

? ? ? ?開始跟蹤前,要先在一個幀中標識出物體,然后從這個位置開始跟蹤。標識物體的方法就是指定一個包含該物體的矩形(YOLO),而跟蹤模塊的任務就是在后續的幀中重新識別出這個物體。OpenCV 中的物體跟蹤框架類cv::Tracker 包含兩個主方法,一個是init 方法,用于定義初始目標矩形;另一個是update 方法,輸出新的幀中對應的矩形。中值流量跟蹤算法的基礎是特征點跟蹤。它先在被跟蹤物體上定義一個點陣。你也可以改為檢測物體的興趣點,例如采用第8 章介紹的FAST 算子檢測興趣點。但是使用預定位置的點有很多好處:它不需要計算興趣點,因而節約了時間;它可以確保用于跟蹤的點的數量足夠多,還能確保這些點分布在整個物體上。默認情況下,中值流量法采用10×10 的點陣。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/78964.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/78964.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/78964.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

001 藍橋杯嵌入式賽道備賽——基礎

個人筆記&#xff0c;不扭扭捏捏&#xff0c;一口氣到位。方便自己也方便大家 00 時鐘線 cubeMX已經完成了大多數工作 01 LED&#xff08;GPIO輸出&#xff09; 在使用LED的時候先把SN74HC573鎖存器PD2置高電平&#xff0c;然后寫入LED所要的高低電平&#xff0c;然后置PD2低…

案例-索引對于并發Insert性能優化測試

前言 最近因業務并發量上升,開發反饋對訂單表Insert性能降低。應開發要求對涉及Insert的表進行分析并提供優化方案。 ??一般對Insert 影響基本都在索引,涉及表已按創建日期做了分區表,索引全部為普通索引未做分區索引。 優化建議: 1、將UNIQUE改為HASH(64) GLOBAL IND…

【技術文章的標準結構與內容指南】

技術文章的標準結構與內容指南 技術文章是傳遞專業知識、分享實踐經驗的重要媒介。一篇高質量的技術文章不僅能夠幫助讀者解決問題&#xff0c;還能促進技術交流與創新。以下是技術文章通常包含的核心內容與結構指南。 1. 標題 一個好的技術文章標題應當&#xff1a; 簡潔明…

豪越消防一體化安全管控平臺:構建消防“一張圖”新生態

在城市化進程加速、建筑規模與功能日益復雜的當下&#xff0c;消防救援工作面臨著諸多嚴峻挑戰。火災隱患如同隱藏在暗處的“定時炸彈”&#xff0c;廣泛分布于城市的各個角落&#xff0c;想要快速、精準定位絕非易事。信息傳遞的不順暢更是雪上加霜&#xff0c;導致救援效率大…

重學Redis:Redis常用數據類型+存儲結構(源碼篇)

一、SDS 1&#xff0c;SDS源碼解讀 sds (Simple Dynamic String)&#xff0c;Simple的意思是簡單&#xff0c;Dynamic即動態&#xff0c;意味著其具有動態增加空間的能力&#xff0c;擴容不需要使用者關心。String是字符串的意思。說白了就是用C語言自己封裝了一個字符串類型&a…

抖音IP屬地可以隨便選擇地址嗎?深度解析

在當今社交媒體盛行的時代&#xff0c;抖音作為受歡迎的短視頻平臺之一&#xff0c;其IP屬地顯示功能引發了廣泛關注。許多用戶好奇&#xff1a;抖音的IP屬地是否可以隨意更改&#xff1f;是否存在方法可以“偽裝”自己的位置&#xff1f;?本文將深入探討這一話題。 一、抖音I…

SOLID原則詳解:提升軟件設計質量的關鍵

前言 關于設計原則SOLID具體指的是什么&#xff0c;怎么理解這些設計原則&#xff0c;我覺得有必要記錄一筆&#xff0c;畢竟這個設計原則確實經常在關鍵技術文檔中提及&#xff0c;在編程思想中提及&#xff0c;在日常的開發中使用&#xff0c;但是對我來說&#xff0c;似乎知…

如何使用 ONLYOFFICE 恢復之前的文件版本?

如何使用 ONLYOFFICE 恢復之前的文件版本&#xff1f; https://www.onlyoffice.com/blog/zh-hans/2023/04/how-to-use-version-history

簡簡單單實現一個Python+Selenium的自動化測試框架

什么是Selenium&#xff1f; Selenium是一個基于瀏覽器的自動化測試工具&#xff0c;它提供了一種跨平臺、跨瀏覽器的端到端的web自動化解決方案。Selenium主要包括三部分&#xff1a;Selenium IDE、Selenium WebDriver 和Selenium Grid。 Selenium IDE&#xff1a;Firefox的…

Java設計模式之中介者模式:從入門到架構級實踐

一、什么是中介者模式&#xff1f; 中介者模式&#xff08;Mediator Pattern&#xff09;是一種行為型設計模式&#xff0c;其核心思想是通過引入一個中介對象來封裝多個對象之間的交互關系。這種模式將原本復雜的網狀通信結構轉換為星型結構&#xff0c;類似于現實生活中的機…

Trinity三位一體開源程序是可解釋的 AI 分析工具和 3D 可視化

一、軟件介紹 文末提供源碼和程序下載學習 Trinity三位一體開源程序是可解釋的 AI 分析工具和 3D 可視化。Trinity 提供性能分析和 XAI 工具&#xff0c;非常適合深度學習系統或其他執行復雜分類或解碼的模型。 二、軟件作用和特征 Trinity 通過結合具有超維感知能力的不同交…

LeetCode 熱題 100_單詞拆分(86_139_中等_C++)(動態規劃)

LeetCode 熱題 100_單詞拆分&#xff08;86_139&#xff09; 題目描述&#xff1a;輸入輸出樣例&#xff1a;題解&#xff1a;解題思路&#xff1a;思路一&#xff08;動態規劃&#xff09;&#xff1a; 代碼實現代碼實現&#xff08;思路一&#xff08;動態規劃&#xff09;&a…

VM虛擬機安裝及Ubuntu安裝配置

VM虛擬機安裝及Ubuntu安裝配置 1、VM虛擬機安裝2、創建虛擬機3、Ubuntu系統安裝4、編譯環境配置4.1 、Ubuntu和 Windows文件互傳 文件互傳4.1.1、 開啟Ubunt下的FTP服務 4.2、 Ubuntu下NFS和SSH服務開啟4.2.1、 NFS服務開啟4.2.2、 SSH服務開啟 4.3、 交叉編譯器安裝4.3.1 安裝…

【KWDB 創作者計劃】_產品技術解讀_1

【KWDB 創作者計劃】_產品技術解讀_1 一、存儲引擎:高性能混合存儲架構1. 存儲模型設計2. 存儲壓縮與編碼3. 持久化策略二、KWDB 組件源碼解析1. 核心模塊分層架構2. 關鍵組件源碼剖析三、KWDB 特性代碼通讀1. 實時分析能力(Real-Time OLAP)2. 混合負載隔離(HTAP)3. 智能索…

高速電路中的電阻、電容的選型及應用

2.1 電阻的應用 2.1.1 與電阻相關的經典案例 如果說芯片是電路的骨架&#xff0c;那么電阻就是在芯片之間起連接作用的關節。電阻的阻值、布放位置等&#xff0c;對設計的成功起著至關重要的作用。 【案例2.1】串聯電阻過大&#xff0c;導致板間告警失敗 某產品由業務板和主…

springBoot接入文心一言

文章目錄 效果接入步驟項目接入配置類&#xff1a;WenXinYiYan前端vue代碼js代碼 后端mapper層service層controller層 測試代碼 效果 先來看一下最后實現的效果 &#xff08;1&#xff09;未點擊前的功能頁面 &#xff08;2&#xff09;點擊后的頁面 &#xff08;3&#xff…

css解決邊框四個角有顏色

效果 html <div class"gradient-corner">2021年</div>css background:/* 左上角橫線 */linear-gradient(90deg, rgb(5, 150, 247) 9px, transparent 0) 0 0,/* 左上角豎線 */linear-gradient(0deg, rgb(5, 150, 247) 9px, transparent 0) 0 0,/* 右上…

自動化三維掃描:CASAIM外觀尺寸智能檢測

制造業向智能化、數字化加速轉型&#xff0c;傳統檢測方式因效率低、精度差、數據斷層等問題&#xff0c;已難以滿足現代工業對精密測量與實時質控的需求。CASAIM依托前沿技術實力&#xff0c;以自動化三維掃描為核心&#xff0c;為工業檢測提供了從數據采集到智能分析的全流程…

突破亞馬遜壁壘,Web Unlocker API 助您輕松獲取數據

目錄 一、Web Unlocker API簡介二、開始使用Web Unlocker API1、首先進入控制臺頁面&#xff0c;點擊左側第一個tab鍵“代理 & 抓取基礎設施”&#xff0c;找到“網頁解鎖器”&#xff0c;開始使用。2、進入網頁解鎖器頁面后&#xff0c;填寫通道名稱&#xff0c;添加簡短描…

【力扣05】最長回文子串

0. 引言 ●子串(substring&#xff09;&#xff1a;原始字符串的一個連續子集; ●子序列&#xff08;subsequence&#xff09;&#xff1a;原始字符串的一個子集。 1. 什么叫回文串&#xff1f; 如果一個字符串正著讀和反著讀是一樣的&#xff0c;那它就是回文串。[1] 例如&…