文章目錄
- 前言
- 1. 低對比度影像臟污區域檢測
- 2. 實作方法介紹
- 3. C++原始碼實作
- 4.結果
- 總結
- 參考
前言
今天看了一篇技術檔案感覺挺有意思,是關于在低對比度影像中檢測臟污區域(這里的臟污指的是比其他區域暗的部分,人眼都不一定能看出來),
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;
cvtColor(mSrc, mGray, COLOR_BGR2GRAY);
GaussianBlur(mGray, mGray, Size(5, 5), 1.0);
Mat mGray2 = mGray.clone();
CV_Assert(mGray.empty() == false);
imshow("gray", mGray.clone());
//方法1:利用梯度變化檢測缺陷
Mat mSobelX, mSobelY;
Sobel(mGray, mSobelX, CV_16S, 1, 0, 7);
Sobel(mGray, mSobelY, CV_16S, 0, 1, 7);
convertScaleAbs(mSobelX, mSobelX);
convertScaleAbs(mSobelY, mSobelY);
Mat mEdge;
addWeighted(mSobelX, 1, mSobelY, 1, 0, mEdge);
imshow("edge", mEdge);
Mat mThresh;
threshold(mEdge, mThresh, 0, 255, THRESH_BINARY | THRESH_OTSU);
imshow("thresh", mThresh);
Mat kernel1 = getStructuringElement(MORPH_RECT, Size(11, 11));
CV_Assert(kernel1.empty() == false);
Mat mMorph;
morphologyEx(mThresh, mMorph, MORPH_ERODE, kernel1);
imshow("erode", mMorph);
Mat kernel2 = getStructuringElement(MORPH_RECT, Size(5, 5));
morphologyEx(mMorph, mMorph, MORPH_DILATE, kernel2);
imshow("dilate", mMorph);
std::vector<std::vector<Point>> contours;
findContours(mMorph, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
for (int i = 0; i < contours.size(); i++)
{
float area = contourArea(contours[i]);
if (area > 200)
{
drawContours(mSrc, contours, i, Scalar(0, 0, 255));
}
}
imshow("result1", mSrc.clone());
//方法2: 利用區域直方圖均衡化方法檢測缺陷
Ptr<CLAHE> ptrCLAHE = createCLAHE(20, Size(30, 30));
ptrCLAHE->apply(mGray2, mGray2);
imshow("equalizeHist", mGray2);
Mat mThresh2;
threshold(mGray2, mThresh2, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
CV_Assert(mThresh2.empty() == false);
imshow("thresh", mThresh2);
Mat kernel2_1 = getStructuringElement(MORPH_RECT, Size(9, 9));
Mat mMorph2;
morphologyEx(mThresh2, mMorph2, MORPH_ERODE, kernel2_1);
CV_Assert(mMorph2.empty() == false);
imshow("morph2", mMorph2);
std::vector<std::vector<Point>> contours2;
findContours(mMorph2, contours2, RETR_EXTERNAL, CHAIN_APPROX_NONE);
for (int i = 0; i < contours2.size(); i++)
{
float area = contourArea(contours2[i]);
if (area > 200)
{
drawContours(mSrc2, contours2, i, Scalar(0, 0, 255));
}
}
imshow("result2", mSrc2);
waitKey(0);
destroyAllWindows();
system("pause");
return 0;
}
4.結果
梯度方法檢測結果:


區域直方圖均衡化方法檢測結果:


總結
相對于梯度方法,區域直方圖均衡化方法需要特別注意區域視窗大小引數以及閾限值引數的選擇,本人也是嘗試了多次才達到比較好的效果,再一次體會到傳統影像處理的痛處,沒有通用的引數適用于所有的應用實體,不同的場景要配置不同的引數才能達到想要的結果,
參考
https://jishuin.proginn.com/p/763bfbd62291
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/303134.html
標籤:其他
上一篇:關于影像原理的淺分析
