C++如何調(diào)用opencv完成運動目標(biāo)捕捉詳解
使用編譯器:Qt Creator 4.2.1
一、原理說明:
差幀識別原理:將這一幀的圖像和上一幀的圖像進行比對,產(chǎn)生變化的即為運動的目標(biāo)像素塊
二、過程詳解:
1.將傳入的兩幀先進行灰度處理,轉(zhuǎn)化將rgb類型圖片轉(zhuǎn)化為灰度圖,可大大降低處理時間和資源消耗
將轉(zhuǎn)換后的圖片轉(zhuǎn)存至frontGray和afterGray
cvtColor(frontFrame,frontGray,CV_BGR2GRAY);
cvtColor(afterFrame,afterGray,CV_BGR2GRAY);2.將兩幀圖片進行差幀處理
將有差別的像素轉(zhuǎn)存至diff
//幀差處理 找到兩幀之間運動物體差異
//缺點:會捕捉所有運動的物體,沒辦法專門捕捉某個目標(biāo)
absdiff(frontGray,afterGray,diff);效果如下:

3.將圖像二值化,只有黑和白,便于計算機計算,但是會產(chǎn)生噪點(后續(xù)會進行簡單的降噪操作)
//二值化: 使其變得更加黑白分明,便于計算,會產(chǎn)生噪點
threshold(diff,diff,25,255,CV_THRESH_BINARY);效果如下:

一個個單獨的小白點就是噪點,是因為光線反光和樹葉的晃動
4.腐蝕處理,腐蝕掉<x*x方塊大小的像素,我這里設(shè)置了4*4,清除大部分噪點
//腐蝕處理:去除大部分的白色噪點
Mat element = cv::getStructuringElement(MORPH_RECT,Size(4,4));
//小于4*4方塊的白色噪點都會被腐蝕
erode(diff,diff,element);效果如下,噪點確實少了很多,但是運動的物體也被腐蝕掉了很多,可能會出現(xiàn)漏掉運動物體的情況

可以發(fā)現(xiàn),噪點幾乎沒有了,但是車輛的像素也被腐蝕了
5. 膨脹處理,把去除過噪點的像素圖像膨脹,變大,我這里膨脹了30*30
//膨脹處理:將白色區(qū)域變"胖",便于識別
Mat element2=cv::getStructuringElement(MORPH_RECT,Size(30,30));
dilate(diff,diff,element2);效果如下:

小像素變成“大果粒”了
6.將變動過的像素目標(biāo)打上標(biāo)記(注意要在原幀上進行標(biāo)記)
//動態(tài)物體標(biāo)記
vector<vector<Point>>contours;//用于保存關(guān)鍵點
findContours(diff,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE,Point(0,0));
//提取關(guān)鍵點
vector<vector<Point>>contours_poly(contours.size());
vector<Rect>boundRect(contours.size());
int x,y,w,h;
int num=contours.size();
for(int i=0;i<num;i++)
{
approxPolyDP(Mat(contours[i]),contours_poly[i],3,true);
boundRect[i]=boundingRect(Mat(contours_poly[i]));
x=boundRect[i].x;
y=boundRect[i].y;
w=boundRect[i].width;
h=boundRect[i].height;
//繪制
rectangle(resFrame,Point(x,y),Point(x+w,y+h),Scalar(0,255,0),2);
}效果如下:


實際效果,偶爾有樹葉飄動會產(chǎn)生一點點干擾
三、代碼
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
Mat moveCheck(Mat &frontFrame,Mat &afterFrame)
{
Mat frontGray,afterGray,diff;
Mat resFrame=afterFrame.clone();
//灰度處理,節(jié)省運算時間
cvtColor(frontFrame,frontGray,CV_BGR2GRAY);
cvtColor(afterFrame,afterGray,CV_BGR2GRAY);
//幀差處理 找到兩幀之間運動物體差異
//缺點:會捕捉所有運動的物體,沒辦法專門捕捉某個目標(biāo)
absdiff(frontGray,afterGray,diff);
//二值化: 使其變得更加黑白分明,便于計算,會產(chǎn)生噪點
threshold(diff,diff,25,255,CV_THRESH_BINARY);
//腐蝕處理:去除大部分的白色噪點
Mat element = cv::getStructuringElement(MORPH_RECT,Size(4,4));//小于4*4方塊的白色噪點都會被腐蝕
erode(diff,diff,element);
//膨脹處理:將白色區(qū)域變"胖",便于識別
Mat element2=cv::getStructuringElement(MORPH_RECT,Size(30,30));
dilate(diff,diff,element2);
//動態(tài)物體標(biāo)記
vector<vector<Point>>contours;//用于保存關(guān)鍵點
findContours(diff,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE,Point(0,0));
//提取關(guān)鍵點
vector<vector<Point>>contours_poly(contours.size());
vector<Rect>boundRect(contours.size());
int x,y,w,h;
int num=contours.size();
for(int i=0;i<num;i++)
{
approxPolyDP(Mat(contours[i]),contours_poly[i],3,true);
boundRect[i]=boundingRect(Mat(contours_poly[i]));
x=boundRect[i].x;
y=boundRect[i].y;
w=boundRect[i].width;
h=boundRect[i].height;
//繪制
rectangle(resFrame,Point(x,y),Point(x+w,y+h),Scalar(0,255,0),2);
}
return resFrame;
}
int main(int argc, char *argv[])
{
Mat frame;
Mat temp;
Mat res;
int num=0;
VideoCapture cap("D:/VideoTraining/carMove.mp4");
while (cap.read(frame))
{
num++;
if(num==1)
{//如果為第一幀則把當(dāng)前幀傳入(即不產(chǎn)生效果)
res=moveCheck(frame,frame);
}
else
{//從第二幀開始才有差幀
res=moveCheck(temp,frame);
}
temp=frame.clone();//此處注意要調(diào)用.clone深拷貝,否則會出現(xiàn)兩個畫面一樣的情況
imshow("frame",frame);
imshow("res",res);
waitKey(25);
}
return 0;
}QT下配置opencv可以看看這一篇:
識別特定目標(biāo)可以看看這一篇:
C++使用opencv調(diào)用級聯(lián)分類器來識別目標(biāo)物體
總結(jié)
到此這篇關(guān)于C++如何調(diào)用opencv完成運動目標(biāo)捕捉的文章就介紹到這了,更多相關(guān)C++ opencv運動目標(biāo)捕捉內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言對CSV文件從最后往前一行一行讀取的實現(xiàn)方法
今天小編就為大家分享一篇關(guān)于C語言對CSV文件從最后往前一行一行讀取的實現(xiàn)方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12

