每一帧一个动作,连接起形成一个动画 帧差法:对每一帧进行分析,对帧内分为动态和静态物体,前一帧与后一帧相对移动的物体识别出。 opencv中有专门对帧差的函数,以识别运动中的物体 原视频图像:
函数设计: 返回Mat,前后两帧传入 1、对画面进行灰度处理,图片降到原来1/3,前后两帧都要做
cvtColor(frontFrame,FrontGray,CV_BGR2GRAY);
cvtColor(afterFrame,afterGray,CV_BGR2GRAY);
2、帧差处理,找到帧与帧之间运动的物体(绝对值对比) 前提:必须灰度
absdiff(FrontGray,afterGray,diff);
imshow("diff",diff);
处理结果 缺陷:会把除车辆外其他会动的物体算进来
3、二值化:图像更加灰白分明
threshold(diff,diff,25,255,CV_THRESH_BINARY);
imshow("threshold",diff);
局部阈值:控制二值化,导致产生大量白色噪点
4、腐蚀处理:去除白色噪点,不能完全去除,车辆也会被腐蚀
Mat element=cv::getStructuringElement(MORPH_RECT,Size(3,3));
//处理的,处理后存储,小方块(卷积核)
erode(diff,diff,element);
imshow("erode",diff);
腐蚀原理:创建的方块对原图进行描边,以中心点算缩小的图像边
5、膨胀处理:白色区域变明显 针对二值化数据进行操作,主要针对高亮部分
Mat element1=cv::getStructuringElement(MORPH_RECT,Size(20,20));
dilate(diff,diff,element1);
膨胀原理:方块中心点描图像边,方块外边为图像膨胀后的图形边
膨胀和腐蚀分两种情况: 开运算:先腐蚀在膨胀,消除多余的白色噪点(降噪) 闭运算:先膨胀在腐蚀,排除小型黑洞(填充)
6、动态物体标记:
vector<vector<Point>>contours;
findContours(diff,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE,Point(0,0));
//提取关键点
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;
y=boundRect[i].height;
rectangle(resFrame,Point(x,y+400),Point(x+w,y+300),Scalar(0,255,0),2);
}
全部代码
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
Mat moveche(Mat &frontFrame,Mat &afterFrame)
{
//第一帧灰度,第二帧灰度
Mat FrontGray,afterGray,diff;
Mat resFrame=afterFrame.clone();
//灰度处理 两帧都要做
cvtColor(frontFrame,FrontGray,CV_BGR2GRAY);
cvtColor(afterFrame,afterGray,CV_BGR2GRAY);
//帧差处理找到每帧之间运动的物体
//缺点:会把其他的运动物算进
absdiff(FrontGray,afterGray,diff);
imshow("diff",diff);
//二值化/黑白分名,但是会有白色噪点
threshold(diff,diff,25,255,CV_THRESH_BINARY);
imshow("threshold",diff);
//腐蚀:去噪点,不完全去除,主要物体也会腐蚀
Mat element=cv::getStructuringElement(MORPH_RECT,Size(3,3));
erode(diff,diff,element);
imshow("erode",diff);
//膨胀:将白色区域变明显
Mat element1=cv::getStructuringElement(MORPH_RECT,Size(20,20));
dilate(diff,diff,element1);
imshow("dilate",diff);
//开运算:先腐蚀在膨胀,消除多余的白色噪点
//闭运算:先膨胀在腐蚀,排除小型黑洞
//动态物体标记
vector<vector<Point>>contours;
findContours(diff,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE,Point(0,0));
//提取关键点
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;
y=boundRect[i].height;
rectangle(resFrame,Point(x,y),Point(x+w,y+h),Scalar(0,255,0),2);
}
return resFrame;
}
int main()
{
//当前帧画面
Mat frame;
//上一帧画面
Mat temp;
//检测是否有处理结果
Mat res;
//判断是否第一帧
int count=0;
//加载视频
VideoCapture cap("./carMove.mp4");
//读取视频的每一帧
while(cap.read(frame))
{
count++;
//是第一帧
if(count==1)
{
res=moveche(frame,frame);
}
//不是第一帧
else
{
res=moveche(temp,frame);
}
temp=frame.clone();
imshow("frame",frame);
imshow("res",res);
waitKey(25);
}
return 0;
}
缺陷:帧和帧间所有运动的物体都会被识别
择优:级联分类器
|