• 车牌识别代码OpenCV


    #include<opencv2opencv.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;

    }

  • 相关阅读:
    Maven入门指南12:将项目发布到私服
    Groovy学习:第四章 Groovy特性深入
    jQuery部分疑问及小结
    Windows自动化---模拟鼠标键盘
    适配器
    object都有string
    spinner
    context
    OnclickListener
    学习-----领进门,看个人
  • 原文地址:https://www.cnblogs.com/hole/p/11311945.html
Copyright © 2020-2023  润新知