当前位置: 首页 > news >正文

【OpenCV】帧差法、级联分类器、透视变换

一、帧差法(移动目标识别):

好处:开销小,不怎么消耗CPU的算力,对硬件要求不高,但只适合固定摄像头

1、优点

  1. 计算效率高,硬件要求

  2. 响应速度快,实时性强

    直接利用连续帧的像素差异检测运动,延迟极低,可实时捕捉动态目标的运动轨迹。
  3. 无需背景建模,适应动态变化

    不依赖静态背景模型(如高斯混合模型 GMM),因此对光照突变、背景微小变化(如树叶晃动)不敏感,鲁棒性优于部分背景差分法。
  4. 内存占用少

    仅需存储前一帧或前几帧图像,内存开销小,适合资源受限的系统。

2、缺点

  1. 仅适用于固定摄像头场景

  2. 无法检测静止目标

    若目标在相邻帧间无位移(如短暂静止的行人),差分结果中目标区域像素差异为零,会被误认为背景,导致漏检。
  3. 对噪声敏感,检测精度低

    微小噪声(如传感器噪声、光线波动)会导致差分图像出现大量 “伪运动区域”,需依赖形态学操作(如腐蚀、膨胀)降噪,但可能模糊目标边界或丢失细节
  4. 目标 “空洞化” 与 “断裂” 问题

    当目标内部像素变化较小时(如纯色物体),差分后可能出现 “空洞”;若目标运动速度快,相邻帧重叠区域少,可能导致检测结果不连续(如车辆被分割为多个碎片)。
  5. 无法提供目标完整信息

    仅能检测运动区域的位置和轮廓,无法获取目标类别(如人、车)、尺寸、历史轨迹关联等高级信息,需结合其他算法(如目标跟踪、深度学习分类)补充。
步骤目的核心操作 / 算法
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;
}

相关文章:

  • 基于51单片机温控风扇—PWM调速、2挡、数码管显示
  • 计算机发展的历程
  • 【Mysql】详解InnoDB存储引擎以及binlog,redelog,undolog+MVCC
  • 【springboot】HttpClient快速入门
  • 电子电路:什么是高频电路以及都有哪些应用?
  • 基于STM32的INA226电压电流检测仪
  • 混合学习:Bagging与Boosting的深度解析与实践指南
  • 《崩坏·星穹铁道2.2指令服》Linux架设教程(附资源工具)
  • 大模型在腰椎间盘突出症预测与治疗方案制定中的应用研究
  • 数据分析 —— 数据预处理
  • 博客打卡-求解流水线调度
  • ARM (Attention Refinement Module)
  • 51单片机课设基于GM65模块的二维码加条形码识别
  • 无法加载文件 E:\Program Files\nodejs\npm.ps1,因为在此系统上禁止运行脚本
  • 2025年【道路运输企业安全生产管理人员】考试题库及道路运输企业安全生产管理人员考试内容
  • 1688 数据接口调用秘籍:高效获取商品实时信息的开发指南
  • MySQL多条件查询深度解析
  • MySQL 聚簇索引与非聚簇索引:底层原理与实战深度解析
  • Redis设计与实现——Redis命令参考与高级特性
  • 【Java】应对高并发的思路
  • 2024年全国博物馆接待观众14.9亿人次
  • 倒票“黄牛”屡禁不绝怎么破?业内:强化文旅市场票务公开制度
  • 盐城经济技术开发区党工委书记王旭东接受纪律审查和监察调查
  • 南宁一学校发生伤害案件,警方通报:嫌疑人死亡,2人受伤
  • 国家统计局向多省份反馈统计督察意见
  • “16+8”“生酮饮食”,网红减肥法究竟靠谱吗?