文章目录
前言
今天看了一篇技术文档感觉挺有意思,是关于在低对比度图像中检测脏污区域(这里的脏污指的是比其他区域暗的部分,人眼都不一定能看出来)。
1. 低对比度图像脏污区域检测
先上图:
第一张图如果不是标注结果,我都没有发现脏污区域在哪里,第二张图还清晰一些,基本可以看出来图像靠近左边缘的位置有偏暗的区域,这就是我们所说的脏污区域了,也是我们要检测的区域。
标注结果图(引用https://jishuin.proginn.com/p/763bfbd62291):
2. 实现方法介绍
这里介绍两种实现方法,
第一种是用C++实现参考博文的方法,即利用梯度方法来检测,具体步骤如下:
- 对图像进行高斯模糊去噪,梯度计算对噪声很敏感;
- 调用Sobel函数计算图像在x,y方向梯度;
- 调用convertScaleAbs函数将x,y梯度图像像素值限制在0-255;
- 调用addWeight函数将x,y梯度图像融合;
- 调用threshold函数对融合图像进行二值化;
- 使用先腐蚀、后膨胀的形态学处理方法对二值图像进行非脏污区域过滤;
- 调用findContours方法查找脏污区域轮廓。
第二种方法是本人根据提高图像对比度思路实现的,具体步骤如下:
8. 对图像进行高斯模糊去噪;
9. 使用局部直方图均衡化方法来提高图像对比度;
10. 使用OTSU二值化阈值方法来粗略分割脏污区域;
11. 对二值图像使用腐蚀的形态学操作过滤掉部分非脏污区域;
12. 调用findContours方法查找脏污区域轮廓。
3. C++源码实现
#include <iostream>
#include <opencv2\imgcodecs.hpp>
#include <opencv2\core.hpp>
#include <opencv2\imgproc.hpp>
#include <opencv2\highgui.hpp>
#include <vector>
int main()
{
using namespace cv;
std::string strImgFile = "C:\\Temp\\common\\Workspace\\Opencv\\images\\led1.jpg";
Mat mSrc = imread(strImgFile);
CV_Assert(mSrc.empty() == false);
Mat mSrc2 = mSrc.clone();
CV_Assert(mSrc2.empty() == false);
Mat mGray