【OpenCV】车辆识别 C++ OpenCV 原理介绍 + 案例实现

目录

前言 

一、图像处理

💻二值化处理

💻膨胀、腐蚀

💻开运算、闭运算

二、案例实现

Step1:灰度处理

Step2:对视频进行帧差处理

Step3:二值化处理

Step4:腐蚀处理

Step5:膨胀处理 

Step6:标记、框选目标

💡完整代码

三、总结 


前言 

本文主要以车辆识别为目标,利用 C++语言 结合 Qt + OpenCV 进行图像处理相关步骤的讲解

一、图像处理

💻二值化处理

二值化:是通过遍历灰度图中点,将图像信息二值化处理,处理过后的图片只有黑白两种色值

📍作用:

  • 图像的二值化就是将图像上的像素点的灰度值设置为0或255,这样将使整个图像呈现出明显的黑白效果
  • 在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓

📍全局阈值:

函数:threshold()

参数:

参数1:InputArray类型的src,输入数组,填单通道 , 8或32位浮点类型的Mat即可 

参数2:OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放输出结果,且和第一个参数中的Mat变量有一样的尺寸和类型

参数3:double类型的thresh,阈值的具体值

参数4:double类型的maxval,当第5个参数阈值类型type取 THRESH_BINARY 或THRESH_BINARY_INV阈值类型时的最大值

参数5:int类型的type,取阀值的算法

📍局部阈值:

函数:adaptiveThreshold()

参数:

参数1:InputArray类型的src,输入图像,填单通道,单8位浮点类型Mat即可

参数2:函数运算后的结果存放在这。即为输出图像

参数3:预设满足条件的最大值

参数4:指定自适应阈值算法,可选择ADAPTIVE_THRESH_MEAN_C 或 ADAPTIVE_THRESH_GAUSSIAN_C两种

参数5:指定阈值类型,可选择THRESH_BINARY或者THRESH_BINARY_INV两种

(即二进制阈值或反二进制阈值)

参数6:表示邻域块大小,用来计算区域阈值,一般选择为3、5、7等

参数7:参数C表示与算法有关的参数,它是一个从均值或加权均值提取的常数,可以是负数

💻膨胀、腐蚀

  • 膨胀和腐蚀是针对图片的二值化数据进行操作的主要是针对高亮部分
  • 膨胀就是使用算法,将图像的边缘扩大些,作用就是将目标的边缘或者是内部的坑填掉 
  • 腐蚀就是使用算法,将图像的边缘腐蚀掉,作用就是将目标的边缘的“毛刺”踢除掉

1️⃣膨胀过程 

膨胀是求局部最大值的操作,核B与图形卷积,即计算核B覆盖的区域的像素点的最大值,并把这个最大值赋值给参考点指定的像素,这样就会使图像中的高亮区域逐渐增长

2️⃣腐蚀过程

腐蚀可以理解为B的中心(锚点)沿着A的内边界走了一圈。腐蚀也是对高亮部分而言,A区域之外的部分 < A的高亮像素,所里里面被外面取代

💻开运算、闭运算

1️⃣开运算:先腐蚀再膨胀,用来消除小物体 

2️⃣闭运算: 先膨胀再腐蚀,用于排除小型黑洞

二、案例实现

Step1:灰度处理

  • 将传入的两帧先进行处理,先将其转化成RGB类型图片再转化为灰度图 
    cvtColor(frontFrame,frontGray,CV_BGR2GRAY);//前一帧灰度处理
    cvtColor(afterFrame,afterGray,CV_BGR2GRAY);//后一帧灰度处理

Step2:对视频进行帧差处理

  • 将两帧图片进行帧差处理,将对比结果存储在diff中
    //【帧差法】对比两帧图像之间差异,捕获运动物体
    //缺点:所有运动的物体都会展现
    Mat diff;
    absdiff(frontGray,afterGray,diff);//前后两帧对比存在diff中
  • 灰度图 + 帧差处理后,效果如下:

Step3:二值化处理

  • 我们可以看到,公交车的识别区块并不是很明显,因此,接下来我们对视频进行二值化处理
    //【二值化】黑白分明
    //局部阈值
    threshold(diff,diff,25,255,CV_THRESH_BINARY);
  • 黑白更加分明,效果如下:

Step4:腐蚀处理

  • 我们会发现,二值化处理后,比原来多出好多的白色的小点,这时候我们就需要进行腐蚀处理,腐蚀掉<x*x方块大小的像素,这里设置了4*4,来清除大部分噪点 
    //【腐蚀处理】将背景中的白色噪点尽可能去除 降噪处理
    Mat element = cv::getStructuringElement(MORPH_RECT,Size(4,4));//小于4*4方块的白色噪点都会被腐蚀
    erode(diff,diff,element);
  • 腐蚀处理之后,效果如下:

Step5:膨胀处理 

  • 噪点相较于之前确实少了很多,但是运动的物体也被腐蚀掉了很多,可能会识别不到一些移动车辆,这里我们继续进行膨胀处理,将我们的目标像素图像变“胖”
    //【膨胀处理】将白色区域扩大,更加明显,利于目标识别
    Mat element2=cv::getStructuringElement(MORPH_RECT,Size(30,30));
    dilate(diff,diff,element2);
  • 膨胀处理后,效果如下:

Step6:标记、框选目标

  • 最后,将我们的目标像素图像进行标记,并且加一个框把移动的物体框选出来
    //动态物体的位置进行标记
    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;
        h=boundRect[i].height;
        //绘制矩形
        rectangle(resFrame,Point(x,y),Point(x+w,y+h),Scalar(255,0,0),2);//Scalar颜色
    }
  • 完成上述所有步骤后,效果如下: 

💡完整代码

#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;

Mat MoveCheck(Mat &frontFrame,Mat &afterFrame)
{

    Mat frontGray,afterGray;//前后灰度处理
    Mat resFrame = afterFrame.clone();

    //【灰度处理】
    cvtColor(frontFrame,frontGray,CV_BGR2GRAY);//前一帧灰度处理
    cvtColor(afterFrame,afterGray,CV_BGR2GRAY);//后一帧灰度处理

    //【帧差法】对比两帧图像之间差异,捕获运动物体
    //缺点:所有运动的物体都会展现
    Mat diff;
    absdiff(frontGray,afterGray,diff);//前后两帧对比存在diff中
    //imshow("diff",diff);

    //【二值化】黑白分明
    //局部阈值
    threshold(diff,diff,25,255,CV_THRESH_BINARY);
    //imshow("threshold",diff);

    //【腐蚀处理】将背景中的白色噪点尽可能去除 降噪处理
    Mat element = cv::getStructuringElement(MORPH_RECT,Size(4,4));//小于4*4方块的白色噪点都会被腐蚀
    erode(diff,diff,element);
    //imshow("erode",diff);

    //【膨胀处理】将白色区域扩大,更加明显,利于目标识别
    Mat element2=cv::getStructuringElement(MORPH_RECT,Size(30,30));
    dilate(diff,diff,element2);
    //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;
        h=boundRect[i].height;
        //绘制矩形
        rectangle(resFrame,Point(x,y),Point(x+w,y+h),Scalar(255,0,0),2);//Scalar颜色
    }
    return resFrame;
}
int main(int argc, char *argv[])
{

    Mat frame;
    Mat temp;
    Mat res;
    int count = 0;
    VideoCapture cap("C:/Users/86177/Desktop/image/carMove.mp4");//视频路径

    while(cap.read(frame))
    {
        count++;
        if(count == 1)
        {
            res = MoveCheck(frame,frame);
        }
        else
        {
            res = MoveCheck(temp,frame);
        }
        temp = frame.clone();
        imshow("frame",frame);
        imshow("res",res);
        waitKey(25);//延时
    }

    return 0;
}

三、总结

  • 本文主要讲解了OpenCV图像处理基本的原理,包括帧差法二值化膨胀腐蚀开运算闭运算
  • 以车辆识别为例子,详细讲解了图像处理相关操作,在各个步骤是怎么样的一个效果
  • 车辆识别在我们日常生活中非常常见,是一个很经典的案例,本案例算是初步实现,但是,通过案例也发现,帧差法的缺点显而易见,测试视频存在很多干扰,比如说其他移动的物体,例如,风比较大,树叶跟着动,我们的框选位置就会受到干扰,不一定是我们预期想要的目标,接下来也会继续对这方面进行深入探究和学习,争取做到更好!

以上就是本文的全部内容啦!如果对您有帮助,麻烦点赞啦!收藏啦!欢迎各位评论区留言!!!

  • 253
    点赞
  • 824
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 132
    评论
车辆识别计算机视觉领域的一个重要应用,主要用于智能交通、安防等领域。C++结合OpenCV是一种广泛应用的车辆识别实现方式,下面介绍其基本原理案例实现。 1. 原理 车辆识别的基本原理是先对车辆图片进行预处理,提取车辆轮廓、特征等信息,然后使用机器学习算法对车辆进行分类识别。具体步骤如下: 1.1 图像预处理 对车辆图片进行预处理,包括图像增强、图像分割、特征提取等步骤。常用的预处理方法有灰度化、高斯滤波、边缘检测、形态学操作等。 1.2 特征提取 对车辆图片进行特征提取,包括颜色、纹理、形状等方面的特征。常用的特征提取方法有LBP、HOG、SIFT等。 1.3 机器学习算法 使用机器学习算法对车辆进行分类识别。常用的算法有支持向量机、神经网络、随机森林等。在训练模型时,需要准备大量的车辆图片数据,进行数据清洗和数据增强等操作,以提高识别准确率。 2. 案例实现 以下是一个基于C++OpenCV车辆识别案例实现: 2.1 数据准备 首先准备车辆图片数据集,包括不同品牌、不同颜色、不同角度等多个方面的数据。对数据进行分类标注,方便后续的机器学习算法训练。 2.2 图像预处理 对车辆图片进行预处理,包括灰度化、高斯滤波、边缘检测等操作。代码示例: ``` Mat src = imread("car.jpg"); Mat gray; cvtColor(src, gray, COLOR_BGR2GRAY); Mat blur; GaussianBlur(gray, blur, Size(3, 3), 0); Mat canny; Canny(blur, canny, 50, 150); ``` 2.3 特征提取 对车辆图片进行特征提取,包括颜色、纹理、形状等方面的特征。代码示例: ``` // 计算LBP特征 Mat lbp; Ptr<LBPHFaceRecognizer> recognizer = LBPHFaceRecognizer::create(); recognizer->train(images, labels); recognizer->predict(testSample, predictedLabel, confidence); // 计算HOG特征 HOGDescriptor hog(Size(64, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9); vector<float> descriptors; hog.compute(image, descriptors); ``` 2.4 机器学习算法 使用机器学习算法对车辆进行分类识别。常用的算法有支持向量机、神经网络、随机森林等。代码示例: ``` // 训练SVM模型 Ptr<SVM> svm = SVM::create(); svm->setType(SVM::C_SVC); svm->setKernel(SVM::LINEAR); svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6)); svm->train(trainData, ROW_SAMPLE, trainLabels); // 使用SVM模型进行预测 Mat testSample = imread("car_test.jpg"); testSample = preprocess(testSample); Mat testFeature = extractFeature(testSample); Mat testResponse; svm->predict(testFeature, testResponse); ``` 以上是一个基于C++OpenCV车辆识别案例实现,其中包括了图像预处理、特征提取和机器学习算法等多个方面的内容。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 132
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿力猪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值