【QT】OpenCV车牌识别之第一部分:车牌定位

摘要
车牌识别主要包括三大方面:车牌定位、字符分割、字符识别,今天先整理第一部分
主要处理步骤如下,方法不单一,也可以在HSV图做车牌定位,我这里用了灰度图

  • 灰度处理
  • 二值化
  • 边缘检测
  • 生态学检测

一、灰度处理
把RGB图处理成灰度图,方便二值化

//灰度处理
Mat MainWindow::GRAY(Mat img)
{
    
    
    Mat img_gray;
    cvtColor(img, img_gray, COLOR_BGR2GRAY);//颜色空间转换
    return img_gray;
}

在这里插入图片描述
二、二值化处理
这里主要利用了opencv的threshold()函数,255是最大阈值,120是当前阈值,根据实际情况更改

//二值化处理
Mat MainWindow::Two_Value(Mat img)
{
    
    
    Mat two_value_img;
    threshold(img, two_value_img, 150, 255, THRESH_BINARY);
    return two_value_img;
}

在这里插入图片描述
这个奥迪二值化完了好酷,忍不住贴出来
在这里插入图片描述

或者可以用adaptiveThreshold函数,自适应二值化,可以更改底色,需要添加#include <opencv2/imgproc.hpp>

//二值化处理
Mat MainWindow::Two_Value(Mat img)
{
    
    
    Mat two_value_img;
    adaptiveThreshold(img, two_value_img,255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, 9);
    /** @brief 自适应二值化
      *@param _src     要二值化的灰度图
      *@param _dst     二值化后的图
      *@param maxValue    二值化后要设置的那个值
      *@param method 块计算的方法(ADAPTIVE_THRESH_MEAN_C 平均值,ADAPTIVE_THRESH_GAUSSIAN_C 高斯分布加权和)
      *@param type     二值化类型(CV_THRESH_BINARY 大于为最大值,CV_THRESH_BINARY_INV 小于为最大值)
      *@param blockSize    块大小(奇数,大于1)
      *@param delta 差值(正值底色为白色)
      */
    return two_value_img;
}

在这里插入图片描述
三、边缘检测(膨胀腐蚀)
提取出图像中的轮廓,这里直接用的canny算子,也可以单独膨胀腐蚀处理,程序在下面

//边缘检测
Mat MainWindow::EDGE(Mat img)
{
    
    
    Mat edge_img;
    Canny(img,edge_img,120,100,3);
//    edge_img = Dilate(img);
//    edge_img = Erode(edge_img);
//    edge_img = Dilate(edge_img);
    return edge_img;
}
//膨胀
Mat MainWindow::Dilate(Mat img)
{
    
    
    Mat edge_img;
    Mat element = getStructuringElement(MORPH_RECT, Size(3, 3), Point(1, 1));
    dilate(img, edge_img, element);
    return edge_img;
}
//腐蚀
Mat MainWindow::Erode(Mat img)
{
    
    
    Mat edge_img;
    Mat element = getStructuringElement(MORPH_RECT, Size(3, 3), Point(1, 1));
    erode(img, edge_img, element);
    return edge_img;
}

在这里插入图片描述
换张图试一下,二值化的程度不太一样,大众轮廓效果有点差,下面我还是开奥迪吧!
在这里插入图片描述

四、生态学检测
1、车牌比例
(1)去Bing图片找到中国车牌的标准,尺寸为440mm*140mm,比例大概是3.14,程序可以放宽这个比例,比如2.5到4来寻找符合要求的轮廓
(2)但是感觉上面奥迪那个车标外边框看起来也是这个比例,有可能成为干扰项
在这里插入图片描述
2.定位车牌
(1)核心程序是使用findContours函数检测车牌的轮廓
函数定义如下→来剽窃一下函数用法

findContours( InputOutputArray image, OutputArrayOfArrays contours,
                              OutputArray hierarchy, int mode,
                              int method, Point offset=Point());

  • 先建立一个单通道幕布来显示轮廓 ,因为画到原图上是看不出来的,下面是按照大小创建的->Mat8种创建方式
    int with = ui->target_img_label->width();//设置宽度
    int height = ui->target_img_label->height();//设置高度
    Mat target_img = Mat::ones(Size(height,with),CV_8UC1);

像这样
在这里插入图片描述

  • 将轮廓从canny处理过的图中用findContours提取出来
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    float temp = 0;
    findContours(edge_img,contours,hierarchy,CV_RETR_TREE,CV_CHAIN_APPROX_NONE,Point());
  • 把轮廓画到幕布上
//生态学检测
Mat MainWindow::MORG(Mat img)
{
    
    
    for(int i=0;i<contours.size();i++)
    {
    
    
        //计算每个轮廓的面积
        temp = fabs(contourArea(contours[i]));
        if(temp>1000)
        {
    
    
            //绘制出contours向量内第i个轮廓
            drawContours(target_img,contours,i,Scalar(255),1,8,hierarchy);
            cout<<"i="<<i<<"  Contour_Area="<<temp<<endl;
        }
    }
    return target_img;
}

在这里插入图片描述
有两点跟我想的不一样:我把大于1000的轮廓画出来了,幸运的发现就是车牌;虽然提取出来了,但是是个斜的?
感觉上是因为幕布不够大,像素放不下,错位了,那么改大一点试试

Mat target_img = Mat::ones(Size(500,400),CV_8UC1);

在这里插入图片描述
果然,但是效果真辣鸡
实际上应该按照比例找轮廓的,就不演示了,下班下班

猜你喜欢

转载自blog.csdn.net/qq_33033059/article/details/108338664