opencv与c++实现车牌轮廓提取

opencv实现车牌提取

主要实现对整张图片中.将车牌分割出来.
需要进行

  1. 转换为灰度值
  2. 阈值分割,去除部分区域
  3. 连通域分析
  4. 分割出车牌所在轮廓
#include
#include
#include
#include
using namespace std;
using namespace cv;
int main(int argc,char** argv)
{
     
    Mat image;
    image = imread("./demo10/02.jpeg",1);   //读取原图像
    imshow("原图像",image);
    Mat gray;
    cvtColor(image,gray,COLOR_BGR2GRAY);    //转换为灰度图
    
    threshold(gray,gray,151,0,THRESH_TOZERO);           //阈值分割,去除无关的内容,低于下限置0
    threshold(gray,gray,255,255,THRESH_TOZERO_INV);     //高于上限置0
    Mat element = getStructuringElement(MORPH_RECT,Size(3,3));      //形态学滤波 3*3的核
    morphologyEx(gray,gray,MORPH_CLOSE,element);                    //进行闭运算
    Mat stats,centroids;                            //连通域分析结果stats:对应各个轮廓的x,y,width,height和面积,centroids:中心点
    Mat labels = Mat::zeros(image.size(),CV_32S);   //表示当前像素是第几个轮廓
    int num_label = connectedComponentsWithStats(gray, labels, stats, centroids,8,4);   //连通域分析,num_label对于连通域个数

    for(int i=0;i<num_label;i++)        //筛选车牌所在连通域,去除其他区域
    {
     
        int area = stats.at<int>(i, CC_STAT_AREA);      //当前连通域区域的面积
        int width = stats.at<int>(i, CC_STAT_WIDTH);    //宽度
        int height = stats.at<int>(i,CC_STAT_HEIGHT);   //高度
        //筛选出车牌所在区域的以外的区域,均不赋予彩色显示,并将其连通域区域的中心点去除
        //面积,宽度,高度的数值,根据实际车牌的尺寸,加上相机内参数等数据可获得,应保证范围适中;
        //不知各参数的,可通过理由该图进行估计
        if((area <6000)|(area >10000)| (width <170)|(width >230) |(height <50) | (height>100))
        {
     
            centroids.at<Vec2d>(i, 0) =0;       //将车牌以外区域的中心点去除,即取消连通域标记
            continue;
        }
    }
    int w = image.cols;     //原图像像素的列数
    int h = image.rows;     //原图像像素的行数

    Mat ROI = Mat::ones(image.size(),image.type());     //车牌提取结果值定义为全黑
    for (int i = 1; i < num_label; i++) {
     
		Vec2d pt = centroids.at<Vec2d>(i, 0);           //各轮廓的中心点
		int x = stats.at<int>(i, CC_STAT_LEFT);         //各轮廓的左上角x坐标
		int y = stats.at<int>(i, CC_STAT_TOP);          //各轮廓的左上角y坐标
		int width = stats.at<int>(i, CC_STAT_WIDTH);    //各轮廓的宽度(x,y)点开始到右下角
		int height = stats.at<int>(i, CC_STAT_HEIGHT);  //各轮廓的高度(x,y)点开始到右下角
		int area = stats.at<int>(i, CC_STAT_AREA);      //各轮廓的面积(x,y)点开始到右下角
        if(pt[0] != 0)          //车牌轮廓的中心点非0
        {
       
            cout<<pt<<endl;     //打印坐标值
            //将车牌区域像素提取到ROI(结果图像)中
            //如车牌图像倾斜,可利用椭圆拟合函数,获得图像角度再进行计算后分割
            for(int xx = x; xx < x+width; xx++)    
                for(int yy =y; yy < y+height; yy++)
                    ROI.at<Vec3b>(yy,xx) = image.at<Vec3b>(yy,xx);
        }
    }
    imshow("车牌提取结果",ROI); //显示结果
    waitKey(0);
    return 0;
}

opencv与c++实现车牌轮廓提取_第1张图片

  • 此为结果程序,具体调试我们需要获取:
  • 最佳的阈值范围
  • 车牌面积的最大范围
  • 车牌宽度,高度的最大范围
  • 可通过链接: opencv与c++ 阈值操作显示窗口.
    等操作来获取.但范围需尽量大,太过局限的范围并没有什么意义

你可能感兴趣的:(opencv,opencv,图像识别,计算机视觉)