• OpenCV 实现低对比度图像脏污区域检测


    1. 低对比度图像脏污区域检测

    先上图:

    第一张图如果不是标注结果,我都没有发现脏污区域在哪里,第二张图还清晰一些,基本可以看出来图像靠近左边缘的位置有偏暗的区域,这就是我们所说的脏污区域了,也是我们要检测的区域。

    标注结果图:

     

     

    2. 实现方法介绍

    这里介绍两种实现方法,
    第一种是用C++实现参考博文的方法,即利用梯度方法来检测,具体步骤如下:

    • 对图像进行高斯模糊去噪,梯度计算对噪声很敏感;
    • 调用Sobel函数计算图像在x,y方向梯度;
    • 调用convertScaleAbs函数将x,y梯度图像像素值限制在0-255;
    • 调用addWeight函数将x,y梯度图像融合;
    • 调用threshold函数对融合图像进行二值化;
    • 使用先腐蚀、后膨胀的形态学处理方法对二值图像进行非脏污区域过滤;
    • 调用findContours方法查找脏污区域轮廓。

    第二种方法是本人根据提高图像对比度思路实现的,具体步骤如下:
    8. 对图像进行高斯模糊去噪;
    9. 使用局部直方图均衡化方法来提高图像对比度;
    10. 使用OTSU二值化阈值方法来粗略分割脏污区域;
    11. 对二值图像使用腐蚀的形态学操作过滤掉部分非脏污区域;
    12. 调用findContours方法查找脏污区域轮廓。

    3. C++源码实现

      1 #include <iostream>
      2 #include <opencv2\imgcodecs.hpp>
      3 #include <opencv2\core.hpp>
      4 #include <opencv2\imgproc.hpp>
      5 #include <opencv2\highgui.hpp>
      6 #include <vector>
      7  
      8 int main()
      9 {
     10     using namespace cv;
     11  
     12     std::string strImgFile = "C:\\Temp\\common\\Workspace\\Opencv\\images\\led1.jpg";
     13     Mat mSrc = imread(strImgFile);
     14  
     15     CV_Assert(mSrc.empty() == false);
     16  
     17     Mat mSrc2 = mSrc.clone();
     18  
     19     CV_Assert(mSrc2.empty() == false);
     20  
     21     Mat mGray;
     22     cvtColor(mSrc, mGray, COLOR_BGR2GRAY);
     23  
     24     GaussianBlur(mGray, mGray, Size(5, 5), 1.0);
     25     Mat mGray2 = mGray.clone();
     26  
     27     CV_Assert(mGray.empty() == false);
     28     imshow("gray", mGray.clone());
     29  
     30     //方法1:利用梯度变化检测缺陷
     31     Mat mSobelX, mSobelY;
     32     Sobel(mGray, mSobelX, CV_16S, 1, 0, 7);
     33     Sobel(mGray, mSobelY, CV_16S, 0, 1, 7);
     34     convertScaleAbs(mSobelX, mSobelX);
     35     convertScaleAbs(mSobelY, mSobelY);
     36  
     37     Mat mEdge;
     38     addWeighted(mSobelX, 1, mSobelY, 1, 0, mEdge);
     39     imshow("edge", mEdge);
     40  
     41     Mat mThresh;
     42     threshold(mEdge, mThresh, 0, 255, THRESH_BINARY | THRESH_OTSU);
     43     imshow("thresh", mThresh);
     44  
     45     Mat kernel1 = getStructuringElement(MORPH_RECT, Size(11, 11));
     46     CV_Assert(kernel1.empty() == false);
     47  
     48     Mat mMorph;
     49     morphologyEx(mThresh, mMorph, MORPH_ERODE, kernel1);
     50     imshow("erode", mMorph);
     51  
     52     Mat kernel2 = getStructuringElement(MORPH_RECT, Size(5, 5));
     53     morphologyEx(mMorph, mMorph, MORPH_DILATE, kernel2);
     54     imshow("dilate", mMorph);
     55  
     56     std::vector<std::vector<Point>> contours;
     57     findContours(mMorph, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
     58  
     59     for (int i = 0; i < contours.size(); i++)
     60     {
     61         float area = contourArea(contours[i]);
     62         if (area > 200)
     63         {
     64             drawContours(mSrc, contours, i, Scalar(0, 0, 255));
     65         }
     66     }
     67  
     68     imshow("result1", mSrc.clone());
     69  
     70     //方法2: 利用局部直方图均衡化方法检测缺陷
     71     Ptr<CLAHE> ptrCLAHE = createCLAHE(20, Size(30, 30));
     72     ptrCLAHE->apply(mGray2, mGray2);
     73     imshow("equalizeHist", mGray2);
     74  
     75     Mat mThresh2;
     76     threshold(mGray2, mThresh2, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
     77     CV_Assert(mThresh2.empty() == false);
     78     imshow("thresh", mThresh2);
     79  
     80     Mat kernel2_1 = getStructuringElement(MORPH_RECT, Size(9, 9));
     81     Mat mMorph2;
     82     morphologyEx(mThresh2, mMorph2, MORPH_ERODE, kernel2_1);
     83  
     84     CV_Assert(mMorph2.empty() == false);
     85  
     86     imshow("morph2", mMorph2);
     87  
     88     std::vector<std::vector<Point>> contours2;
     89     findContours(mMorph2, contours2, RETR_EXTERNAL, CHAIN_APPROX_NONE);
     90  
     91     for (int i = 0; i < contours2.size(); i++)
     92     {
     93         float area = contourArea(contours2[i]);
     94         if (area > 200)
     95         {
     96             drawContours(mSrc2, contours2, i, Scalar(0, 0, 255));
     97         }
     98     }
     99  
    100     imshow("result2", mSrc2);
    101  
    102     waitKey(0);
    103     destroyAllWindows();
    104  
    105     system("pause");
    106     return 0;
    107 }

    4.结果

    梯度方法检测结果:

     局部直方图均衡化方法检测结果:

    总结

    相对于梯度方法,局部直方图均衡化方法需要特别注意局部窗口大小参数以及阈限值参数的选择,本人也是尝试了多次才达到比较好的效果。再一次体会到传统图像处理的痛处,没有通用的参数适用于所有的应用实例,不同的场景要配置不同的参数才能达到想要的结果。

     

  • 相关阅读:
    使用C++ 实现的 websocket 客户端 (基于easywsclient)
    ant打包报错 JRE version less than 1.8 is not suppored
    离线安装SVN 4.2.3
    maven项目使用oracle11g
    springboot 新工程报错 Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
    IP与域名绑定
    web项目如果省略端口
    Linux源码安装Python3.7服务
    Linux yum软件包安装、管理与使用
    RPM软件包管理与使用
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/15672107.html
Copyright © 2020-2023  润新知