一、帧差法(移动目标识别):
好处:开销小,不怎么消耗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;
}