• 《图像处理实例》 之 车牌定位


    目标:  提取车牌所在的区域

           PS:现在还没学习文字检测,以后再来补充~~

    思路:

        1.利用形态学+梯度+轮廓检测,但是这个形态学要求比较高,得调节到适当的参数。

        2.利用HSV颜色分离+梯度+形态学+轮廓检测,这个方法的适应度比较高,行比较上面的方法较难理解。

    本文使用第二种方法实现:

    PS:不要问为什么用这种方法,没有为什么的方法,只有解决问题的方法,手动操作一下就懂了。

    先上效果图:

    梯度检测图(1-1)

     

    S空间图(1-2)

     

    S空间分离蓝色图(1-3)

    (HSV图像分离+梯度)结合图(1-4)

     

    轮廓检测处理图(1-5)

     

    最终效果图(1-6)

     上代码:

      1 #if 1
      2 #include <opencv2/opencv.hpp>
      3 #include <iostream>
      4 #include "math.h"
      5 
      6 using namespace cv;
      7 using namespace std;
      8 
      9 int main(int argc, char**argv)
     10 {
     11     Mat input_image;
     12     input_image = imread("car.jpg");
     13     if (input_image.data == NULL) {
     14         return -1; cout << "can't open image.../";
     15     }
     16     //-----------------------------------------------------------------------------------//
     17     //------------------------------梯度检测图像--------------------------------------//
     18     //-----------------------------------------------------------------------------------//
     19     Mat input_image1;
     20     input_image.copyTo(input_image1);
     21     cvtColor(input_image1, input_image1, CV_BGR2GRAY);
     22     input_image1.convertTo(input_image1, CV_32FC1);
     23     Mat sobelx = (Mat_<float>(3, 3) << -0.125, 0, 0.125, -0.25, 0, 0.25, -0.125, 0, 0.125);
     24     filter2D(input_image1, input_image1, input_image1.type(), sobelx);
     25     Mat mul_image;
     26     multiply(input_image1, input_image1, mul_image);
     27     const int scaleValue = 4;
     28     double threshold = scaleValue * mean(mul_image).val[0];//4 * img_s的平均值
     29     Mat resultImage = Mat::zeros(mul_image.size(), mul_image.type());
     30     float* pDataimg_s  = (float*)(mul_image.data);
     31     float* pDataresult = (float*)(resultImage.data);
     32     const int height = input_image1.rows;
     33     const int width  = input_image1.cols;
     34     //--- 非极大值抑制 + 阈值分割
     35     for (size_t i = 1; i < height-1; i++)
     36     {
     37         for (size_t j = 1; j < width-1; j++)
     38         {
     39             bool b1 = (pDataimg_s[i*height + j] > pDataimg_s[i*height + j - 1]);
     40             bool b2 = (pDataimg_s[i*height + j] > pDataimg_s[i*height + j + 1]);
     41             bool b3 = (pDataimg_s[i*height + j] > pDataimg_s[(i - 1)*height + j]);
     42             bool b4 = (pDataimg_s[i*height + j] > pDataimg_s[(i + 1)*height + j]);
     43             pDataresult[i*height + j] = 255 * ((pDataimg_s[i*height + j] > threshold) && ((b1&&b2) || (b3&&b4)));
     44         }
     45     }
     46     resultImage.convertTo(resultImage, CV_8UC1);
     47     //-----------------------------------------------------------------------------------//
     48     //---------------------------------HSV通道提取---------------------------------------//
     49     //-----------------------------------------------------------------------------------//
     50     Mat input_image2;
     51     input_image.copyTo(input_image2);
     52     Mat img_h, img_s, img_v, img_hsv;
     53     cvtColor(input_image2, img_hsv, CV_BGR2HSV);
     54     vector<Mat> hsv_vec;
     55     split(img_hsv, hsv_vec);
     56     img_h = hsv_vec[0];
     57     img_s = hsv_vec[1];
     58     img_v = hsv_vec[2];
     59     img_h.convertTo(img_h, CV_32F);
     60     img_s.convertTo(img_s, CV_32F);
     61     img_v.convertTo(img_v, CV_32F);
     62     normalize(img_h, img_h, 0, 1, NORM_MINMAX);
     63     normalize(img_s, img_s, 0, 1, NORM_MINMAX);
     64     normalize(img_v, img_v, 0, 1, NORM_MINMAX);
     65     //----下面的操作等同上面的归一化--------//
     66     //double h_max, s_max, v_max;
     67     ////minMaxIdx(img_h, 0, &h_max);
     68     //minMaxLoc(img_h, 0, &h_max);
     69     //minMaxLoc(img_s, 0, &s_max);
     70     //minMaxLoc(img_v, 0, &v_max);
     71     //img_h /= h_max;
     72     //img_s /= s_max;
     73     //img_v /= v_max;
     74     Mat img_vblue = ((img_h > 0.45)&(img_h < 0.75)&(img_s > 0.15)&(img_v > 0.25));//蓝色通道提取
     75     Mat vbule_gradient = Mat::zeros(input_image2.size(), CV_8UC1);
     76     for (size_t i = 1; i < height-1; i++)
     77     {
     78         for (size_t j = 1; j < width-1; j++)
     79         {
     80             /*Rect rec;
     81             rec.x = j - 1;
     82             rec.y = i - 1;
     83             rec.width  = 3;
     84             rec.height = 3;*/
     85             //----梯度和蓝色区域重合的部分,也可以用上面的矩形3X3的判断
     86             vbule_gradient.at<uchar>(i, j) = (resultImage.at<uchar>(i, j) == 255 && img_vblue.at<uchar>(i,j) != 0) ? 255 : 0;
     87             //vbule_gradient.at<uchar>(i, j) = (resultImage.at<uchar>(i, j) == 255 && countNonZero(img_vblue(rec)) >= 1) ? 255 : 0;
     88         }
     89     }
     90     //-----------------------------------------------------------------------------------//
     91     //-----------------------------形态学+轮廓提取车牌-----------------------------------//
     92     //-----------------------------------------------------------------------------------//
     93     Mat morph;
     94     morphologyEx(vbule_gradient, morph, MORPH_CLOSE, Mat::ones(2, 25, CV_8UC1));
     95     vector<vector<Point>> contours;
     96     vector<Vec4i> hierarchy;
     97     findContours(morph, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(-1, -1));
     98     Rect rec_adapt;
     99     for (size_t i = 0; i < contours.size(); i++)
    100     {
    101         //----矩形区域非零像素占总的比例,防止有较大的空白区域干扰检测结果
    102         //----矩形的长宽限制,也可以再增加额外条件:长宽比例等
    103         int true_pix_count = countNonZero(morph(boundingRect(contours[i])));
    104         double true_pix_rate = static_cast<double>(true_pix_count) / static_cast<double>(boundingRect(contours[i]).area());
    105         if (boundingRect(contours[i]).height > 10 && boundingRect(contours[i]).width > 80 && true_pix_rate > 0.7)
    106         {
    107             rec_adapt = boundingRect(contours[i]);
    108             drawContours(morph, contours, static_cast<int>(i), Scalar(255, 255, 255), 2);
    109         }        
    110     }
    111     imshow("Area Brand", input_image(rec_adapt));
    112     waitKey(0);
    113     return 0;
    114 }
    115 #endif

     

    参考:《opencv图像处理编程实例》

  • 相关阅读:
    测试某个方法的执行时间
    DataTable与DataGridView绑定
    《认知与设计——理解UI设计准则》笔记(7) 我们的注意力有限,记忆力也不完美
    常用软件收集
    通过反射得到某个实体的属性值
    获取某个字段的最大值
    C# ServerVariables参数说明
    C# 将网址转换为16进制可用网址,防盗链,%%
    不加修改权限的前提,要分辨出那些图片是删除不用的
    C# Winform 域名得到(查询)(服务器所在) IP  cs
  • 原文地址:https://www.cnblogs.com/wjy-lulu/p/6895742.html
Copyright © 2020-2023  润新知