一、幀差法(移動目標識別):
好處:開銷小,不怎么消耗CPU的算力,對硬件要求不高,但只適合固定攝像頭
1、優點
-
計算效率高,硬件要求
-
響應速度快,實時性強
直接利用連續幀的像素差異檢測運動,延遲極低,可實時捕捉動態目標的運動軌跡。 -
無需背景建模,適應動態變化
不依賴靜態背景模型(如高斯混合模型 GMM),因此對光照突變、背景微小變化(如樹葉晃動)不敏感,魯棒性優于部分背景差分法。 -
內存占用少
僅需存儲前一幀或前幾幀圖像,內存開銷小,適合資源受限的系統。
2、缺點
-
僅適用于固定攝像頭場景
-
無法檢測靜止目標
若目標在相鄰幀間無位移(如短暫靜止的行人),差分結果中目標區域像素差異為零,會被誤認為背景,導致漏檢。 -
對噪聲敏感,檢測精度低
微小噪聲(如傳感器噪聲、光線波動)會導致差分圖像出現大量 “偽運動區域”,需依賴形態學操作(如腐蝕、膨脹)降噪,但可能模糊目標邊界或丟失細節。 -
目標 “空洞化” 與 “斷裂” 問題
當目標內部像素變化較小時(如純色物體),差分后可能出現 “空洞”;若目標運動速度快,相鄰幀重疊區域少,可能導致檢測結果不連續(如車輛被分割為多個碎片)。 -
無法提供目標完整信息
僅能檢測運動區域的位置和輪廓,無法獲取目標類別(如人、車)、尺寸、歷史軌跡關聯等高級信息,需結合其他算法(如目標跟蹤、深度學習分類)補充。
步驟 | 目的 | 核心操作 / 算法 |
---|---|---|
1. 讀取圖像 | 獲取視頻流中的連續幀(如第?t?幀和第?t+1?幀) | VideoCapture ?+?read() |
2. 灰度轉換 | 減少計算復雜度,突出亮度變化 | cvtColor() |
3. 幀差分計算 | 計算相鄰幀像素差異,突出運動區域 | absdiff() |
4. 二值化處理 | 將差分結果轉換為二值圖像(前景為運動區域,背景為靜止區域) | threshold() |
5. 降噪 | 去除噪聲,連接斷裂的運動區域 | 腐蝕(erode() )+ 膨脹(dilate() ) |
6. 多邊擬合 | 提取運動目標輪廓,過濾無效噪聲 | findContours() ?+ 輪廓面積過濾 |
7. 結果輸出 | 在原圖標記目標區域并顯示 / 保存 | rectangle() ?+?imshow() |
3.開、閉運算
開運算:先腐蝕在膨脹,用來消除圖像周邊小白點
閉運算:先膨脹在腐蝕,用來消除物體內部的小黑點
二、opencv級聯分類器:
正樣本數據采集:需要檢測的物體圖片
負樣本數據采集:非檢測物的圖片(是正樣本的3倍)
1.優點
- 可檢測特定目標,泛化能力較強(需充分訓練)。
- 計算效率高(級聯結構快速排除非目標區域)。
- 無需視頻時序信息,適用于單圖像檢測。
2.缺點
- 需要大量標注數據進行訓練,且訓練過程耗時。
- 僅能檢測預定義目標,無法檢測未知類型目標。
- 對目標尺度、姿態變化敏感(需多尺度檢測或重新訓練)。
3.步驟:
-
1.灰度處理
Mat gray;
cvtColor(frame,gray,CV_BGR2GRAY);
-
2.壓縮到原來一半
Mat small(cvRound(frame.rows/scale),cvRound(frame.cols/scale),CV_8UC1);
resize(gray,small,small.size(),0,0,INTER_LINEAR);
-
3.直方圖均衡化
equalizeHist(small,small);
-
4.用級聯分類識別車輛
?vector<Rect> cars;
cascade.detectMultiScale(small,cars,1.1,2,0|CV_HAAR_SCALE_IMAGE,Size(30,30));
-
5.繪制矩形
vector<Rect>::const_iterator iter;
for(iter=cars.begin();iter!=cars.end();iter++){
? ? rectangle(frame,
? ? ? ? ?cvPoint(cvRound(iter->x*scale),cvRound(iter->y*scale)),
? ? ? ? ?cvPoint(cvRound((iter->x+iter->width)*scale),cvRound((iter->y+iter->height)*scale)),
? ? ? ? ?Scalar(0,255,0),
? ? ? ? ?2,3
? ? ? ? );}
#include <iostream>
#include <opencv2/opencv.hpp>using namespace cv;
using namespace std;void detec_car(Mat& frame,CascadeClassifier& cascade,double scale)
{//1.灰度處理Mat gray;cvtColor(frame,gray,CV_BGR2GRAY);//2.壓縮到原來一半Mat small(cvRound(frame.rows/scale),cvRound(frame.cols/scale),CV_8UC1);resize(gray,small,small.size(),0,0,INTER_LINEAR);//3.直方圖均衡化equalizeHist(small,small);//4.用級聯分類識別車輛vector<Rect> cars;cascade.detectMultiScale(small,cars,1.1,2,0|CV_HAAR_SCALE_IMAGE,Size(30,30));//5.繪制矩形vector<Rect>::const_iterator iter;for(iter=cars.begin();iter!=cars.end();iter++){rectangle(frame,cvPoint(cvRound(iter->x*scale),cvRound(iter->y*scale)),cvPoint(cvRound((iter->x+iter->width)*scale),cvRound((iter->y+iter->height)*scale)),Scalar(0,255,0),2,3);}imshow("res",frame);
}int main()
{Mat frame;//加載級聯分類器CascadeClassifier cascade;cascade.load("xml/cars.xml");VideoCapture video("video/carMove.mp4");while(video.read(frame)){imshow("video",frame);detec_car(frame,cascade,2.0);waitKey(40);}return 0;
}
三、透視變換
將傾斜的圖片物品扯平變正
(1)findHomography函數
Mat findHomography( InputArray srcPoints, InputArray dstPoints,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?int method = 0, double ransacReprojThreshold = 3,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?OutputArray mask=noArray(), const int maxIters = 2000,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const double confidence = 0.995);//輸入點擊坐標順序,接收順序(都是存在容器當中)
通過原圖四個坐標和轉化后四個坐標計算映射矩陣
Mat homo=findHomography(data.points,obj,CV_FM_RANSAC);
(2)warpPerspective函數
void warpPerspective( InputArray src, OutputArray dst,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?InputArray M, Size dsize,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?int flags = INTER_LINEAR,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?int borderMode = BORDER_CONSTANT,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const Scalar& borderValue = Scalar());
?warpPerspective(img,result,homo,result.size());
#include <iostream>#include <opencv2/opencv.hpp>using namespace cv;
using namespace std;typedef struct{Mat img;//需操作的圖像vector<Point2f> points;//保存每次鼠標點擊的位置信息
}DATA;void mouseHandle(int event,int x,int y,int flag,void* arg){DATA* pd=(DATA*)arg;if(event==EVENT_LBUTTONDOWN){//鼠標左鍵按下//圖片,中心坐標,半徑,圓顏色,邊緣粗細,線條類型circle(pd->img,Point(x,y),3,Scalar(0,255,0),3,CV_AA);if(pd->points.size()<4){pd->points.push_back(Point2f(x,y));}imshow("book",pd->img);}}
int main()
{//行列(高寬)Mat result=Mat::zeros(400,800,CV_8UC1);Mat img=imread("image/1.jpg");imshow("book",img);DATA data;data.img=img;setMouseCallback("book",mouseHandle,&data);waitKey(0);//設置轉換后的坐標//這個順序要與點擊順序一致,左上為開始,順時針vector<Point2f> obj;obj.push_back(Point2f(0,0));obj.push_back(Point2f(800,0));obj.push_back(Point2f(800,400));obj.push_back(Point2f(0,400));//通過原圖四個坐標和轉化后四個坐標計算映射矩陣Mat homo=findHomography(data.points,obj,CV_FM_RANSAC);imshow("homo",homo);//四個參數類型//InputArray src, OutputArray dst, InputArray M, Size dsizewarpPerspective(img,result,homo,result.size());imshow("result",result);waitKey(0);return 0;
}