欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

车牌识别代码OpenCV

程序员文章站 2022-03-21 21:37:02
#include #include using namespace cv; using namespace std; int areas; //该函数用来验证是否是我们想要的区域,车牌定位原理其实就是在图片上寻找矩形,我们可以用长宽比例以及 ......

#include<opencv2\opencv.hpp>

#include<iostream> using namespace cv; using namespace std; int areas;

//该函数用来验证是否是我们想要的区域,车牌定位原理其实就是在图片上寻找矩形,我们可以用长宽比例以及面积来验证是否是我们想要的矩形,宽高比为520/110=4.7272 (车牌的长除以宽),区域面积最小为15个像素,最大为125个像素

bool verifysize(rotatedrect candidate) {     float error = 0.4; //40%的误差范围

    float aspect = 4.7272;//宽高比例

    int min = 25 * aspect * 25; //最小像素为15

    int max = 125 * aspect * 125;//最大像素为125

    float rmin = aspect - aspect*error;//最小误差

    float rmax = aspect + aspect*error;//最大误差

    int area = candidate.size.height*candidate.size.width;//求面积

    float r = (float)candidate.size.width / (float)candidate.size.height;//长宽比

    if (r < 1)

        r = 1 / r;

    if (area<min || area>max || r<rmin || r>rmax)

        return false;

    else

        return true; } int main(int argc, char** argv) {

    mat src;

    src = imread("d:\\car1.jpg");//读取含车牌的图片

    if (!src.data)     {

        cout << "could not open car.jph.." << endl;

        return -1;

    }

    mat img_gray;

    cvtcolor(src, img_gray, cv_bgr2gray);//灰度转换

    mat img_blur;

    blur(img_gray, img_blur, size(5, 5));//用来降噪

    mat img_sobel;

    sobel(img_gray, img_sobel, cv_8u, 1, 0, 3);//sobel滤波,对x进行求导,就是强调y方向,对y进行求导,就是强调x方向,在此我们对x求导,查找图片中的竖直边

    mat img_threshold;

    threshold(img_sobel, img_threshold, 0, 255, thresh_binary | thresh_otsu);

    mat element = getstructuringelement(morph_rect, size(21, 5));//这个size很重要!!不同的图片适应不同的size,待会在下面放图,大家就知道区别了

    morphologyex(img_threshold, img_threshold,morph_close,element);//闭操作,就是先膨胀后腐蚀,目的就是将图片联通起来,取决于element的size

。     /*接下来就是提取轮廓*/

    vector<vector<point>>contours;

    findcontours(img_threshold, contours, cv_retr_external, cv_chain_approx_none);

    mat result = mat::zeros(src.size(), cv_8u);

    drawcontours(result, contours, -1, scalar(255));

    vector<rotatedrect> rects; //用来存放旋转矩形的容器

    //mat result1 = mat::zeros(src.size(), cv_8u);

    mat result1;

    src.copyto(result1);

    for (size_t i = 0; i < contours.size(); i++)     {

        point2f vertices[4];//用来存放旋转矩形的四个点

        rotatedrect mr = minarearect(mat(contours[i]));

    //minarearect 寻找最小的矩形

        if (verifysize(mr))//筛选是否是我们需要的区域,如果验证成功,就放到rects里,

        {

            //if (mr.angle > -30) {

            mr.points(vertices);

            for (size_t j = 0; j < 4; j++)

            {

                line(result1, vertices[j], vertices[(j + 1) % 4], scalar(0, 0, 255), 2, 8);

                        cout << "矩形坐标"<<j<<"为" << vertices[j] << endl;

            }

                cout << "height:" << mr.size.height << endl << "weight:" << mr.size.width << endl;

            rects.push_back(mr);

                cout << "矩形角度:" << mr.angle << endl;     //  }

        }

    }

    vector<mat>output;//用于存放识别到的图像

    for (size_t i = 0; i < rects.size(); i++)

    {

        mat dst_warp;

        mat dst_warp_rotate;

        mat rotmat(2, 3, cv_32fc1);

        dst_warp = mat::zeros(src.size(), src.type());

        float r = (float)rects[i].size.width / (float)rects[i].size.height;

        float  angle = rects[i].angle;

        if (r < 1)

            angle = angle + 90;

        rotmat = getrotationmatrix2d(rects[i].center,angle, 1);//其中的angle参数,正值表示逆时针旋转,关于旋转矩形的角度,以为哪个是长哪个是宽,在下面会说到

        warpaffine(src, dst_warp_rotate, rotmat, dst_warp.size());//将矩形修正回来

        size rect_size = rects[i].size;

        if (r < 1)

            swap(rect_size.width, rect_size.height);

        mat dst(rects[i].size, cv_8u);

        getrectsubpix(dst_warp_rotate, rect_size, rects[i].center, dst);//裁剪矩形

        /*以下代码是将裁减到的矩形设置为相同大小,并且提高对比度*/

        mat resultresized;

        resultresized.create(33, 144, cv_8uc3);

        resize(dst, resultresized, resultresized.size(), 0, 0, inter_cubic);

        mat grayresult;

        cvtcolor(resultresized, grayresult, cv_bgr2gray);

        blur(grayresult, grayresult, size(3, 3));

        equalizehist(grayresult, grayresult); //均值化提高对比度

        output.push_back(grayresult); //存放图片

    }

    char name[20] = "";

    for (size_t i = 0; i < output.size(); i++)

    {

  if(i==0){

    imwrite("d:\\ccar.jpg",output[0]);

        sprintf_s(name, "识别到的第%d个车牌", i+1);

        imshow(name, output[i]);

  }

    }

    waitkey(0);

    return 0;

}

#include <iostream> #include <opencv2/opencv.hpp>

using namespace std; using namespace cv;

int main(){

    mat img = imread("d:\\ccar.jpg",1);

      /*  第一个参数是图片的绝对地址  第二个参数表示图片读入的方式(flags可以缺省,缺省时flags=1,表示以彩色图片方式读入图片)  flags>0时表示以彩色方式读入图片  flags=0时表示以灰度图方式读入图片  flags<0时表示以图片的本来的格式读入图片     */

   imshow("123", img); 

   //“123”是显示框的名字

   int a = waitkey(10000); 

    //通过整型变量a获取waitkey函数的返回值

       cout << a << endl;   

    /*     waitkey(x)  表示等x毫秒,在这期间如果有按键按下,则返回按键的ascii码,等待结束则会返回-1.     如果x=0,那么无限等待下去,直到有按键按下     !!!另外,在imshow之后如果没有waitkey语句则不会正常显示图像。即imshow不会生效!!!

    */  

  //estroyallwindows();

   //销毁窗口

 rect rect1(5,0,17,27);

   //创建一个rect框,属于cv中的类,四个参数代表x,y,width,height

    mat image_cut1 = mat(img, rect1); 

     //从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy

   mat image_copy1 = image_cut1.clone();

  //clone函数创建新的图片

    imshow("1",image_copy1);

    waitkey();  

   imwrite( "d:\\bar1.jpg", image_copy1); 

  //保存mat格式的图片成jpg格式,或者png,bmp格式,文件大小依次递增

  rect rect2(23,0,16,27);

//创建一个rect框,属于cv中的类,四个参数代表x,y,width,height

    mat image_cut2 = mat(img, rect2);

      //从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy

    mat image_copy2 = image_cut2.clone(); 

  //clone函数创建新的图片

    imshow("2",image_copy2);

    waitkey();  

    imwrite( "d:\\bar2.jpg", image_copy2); 

  //保存mat格式的图片成jpg格式,或者png,bmp格式,文件大小依次递增

rect rect3(45,0,18,27);

//创建一个rect框,属于cv中的类,四个参数代表x,y,width,height

    mat image_cut3 = mat(img, rect3);

      //从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy

    mat image_copy3 = image_cut3.clone();

   //clone函数创建新的图片

   imshow("3",image_copy3);    waitkey();  

    imwrite( "d:\\bar3.jpg", image_copy3);

   //保存mat格式的图片成jpg格式,或者png,bmp格式,文件大小依次递增

 rect rect4(63,0,16,27);

//创建一个rect框,属于cv中的类,四个参数代表x,y,width,height

    mat image_cut4 = mat(img, rect4);

      //从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy

    mat image_copy4 = image_cut4.clone(); 

  //clone函数创建新的图片

   imshow("4",image_copy4);

   waitkey();  

    imwrite( "d:\\bar4.jpg", image_copy4); 

  //保存mat格式的图片成jpg格式,或者png,bmp格式,文件大小依次递增

 rect rect5(79,0,16,27);

//创建一个rect框,属于cv中的类,四个参数代表x,y,width,height

    mat image_cut5 = mat(img, rect5); 

     //从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy

    mat image_copy5 = image_cut5.clone(); 

  //clone函数创建新的图片

   imshow("5",image_copy5);

   waitkey();  

    imwrite( "d:\\bar5.jpg", image_copy5); 

  //保存mat格式的图片成jpg格式,或者png,bmp格式,文件大小依次递增

 rect rect6(95,0,16,27);

//创建一个rect框,属于cv中的类,四个参数代表x,y,width,height

    mat image_cut6 = mat(img, rect6); 

     //从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy

    mat image_copy6 = image_cut6.clone(); 

  //clone函数创建新的图片

   imshow("6",image_copy6);

   waitkey();  

    imwrite( "d:\\bar6.jpg", image_copy6); 

  //保存mat格式的图片成jpg格式,或者png,bmp格式,文件大小依次递增

 rect rect7(111,0,16,27);

//创建一个rect框,属于cv中的类,四个参数代表x,y,width,height

    mat image_cut7 = mat(img, rect7);

      //从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy

    mat image_copy7 = image_cut7.clone(); 

  //clone函数创建新的图片    imshow("7",image_copy7);

   waitkey();  

    imwrite( "d:\\bar7.jpg", image_copy7); 

  //保存mat格式的图片成jpg格式,或者png,bmp格式,文件大小依次递增

    return 0;

}