車牌識別代碼OpenCV


#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;

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM