2014-12-03 104 views
12

我有低對比度圖像分割的問題。 任務是查找表面缺陷。它們是可見的(缺陷總是黑暗的區域),但圖像的對比度非常低。 下面兩個樣本。低對比度圖像分割

1 2

我試圖提高對比度,然後tresholding:

Mat tmp1 = imread("C:\\framesRoi\\311.bmp",0); 
stretchContrast(tmp1); 
threshold(tmp1,tmp1,75,255,THRESH_BINARY); 

其中拉伸對比IMPL:

int minValue = 255, maxValue = 0; 
const int l = sourceImg.cols * sourceImg.rows * sourceImg.channels(); 
if(sourceImg.isContinuous()) 
{ 
    uchar* ptr = sourceImg.ptr<uchar>(0); 
    for(int i = 0; i < l; ++i) 
    { 
     if(ptr[i] < minValue) 
     { 
      minValue = ptr[i]; 
     } 
     if(ptr[i] > maxValue) 
     { 
      maxValue = ptr[i]; 
     } 
    } 
} 
cout<<"min: "<<minValue<<";"<<"max value: "<<maxValue<<endl; 

const int magicThreshold = 10; 
if(sourceImg.isContinuous()) 
{ 
    uchar* ptr = sourceImg.ptr<uchar>(0); 
    for(int i = 0; i < l; ++i) 
    { 
     ptr[i] = 255 * (ptr[i]-minValue)/(maxValue - minValue); 
    } 
} 

但這種方法失敗了。有許多錯誤的檢測,而不是檢測所有的缺陷: 3

這裏是拉鍊與測試幀:https://dl.dropboxusercontent.com/u/47015140/testFrames.rar

+1

當你根據圖像內容的對比度拉伸,你輸了就要挑一個有用的閾值範圍內。 – 2014-12-03 21:34:09

+0

@MarkRansom:我應該怎麼做? – krzych 2014-12-03 21:38:41

+2

如果您知道缺陷總是會變暗,您可以在不改變對比度的情況下調整亮度,使明亮區域保持一致。你可以用最大值來做到這一點,儘管使用第90百分位左右,而不會受到噪音的影響。 – 2014-12-03 21:48:25

回答

8

嘗試使用諸如kmeans之類的聚類方法通過灰度級對圖像進行聚類。下面我直接在圖像上使用kmeans而沒有任何灰度級轉換(使用3個聚類給了我更好的結果)。您應該能夠通過使用評論中概述的方法對預處理的圖像進行聚類來改進結果。

enter image description here enter image description here

簇的形狀可能會略有不同,由於k均值的隨機性。

現在,如果將聚類圖像的連通分量計算出來並計算這些區域的平均灰度級,則缺陷的平均值應低於其他區域。

我在Matlab中做了部分聚類。

im = imread('r2SOV.png');%Uy1Fq r2SOV 
gr = im; 
size = size(gr); 

% perform closing using a 5x5 circular structuring element 
sel = strel('disk', 2, 4); 
mcl = imclose(gr, sel); 
% cluster gray levels using kmeans: using 3 clusters 
x = double(mcl(:)); 
idx = kmeans(x, 3); 
cl = reshape(idx, size); 

figure, imshow(label2rgb(cl)) 
+0

最好的答案洙遠。我會等到賞金到期並接受最佳答案。 – krzych 2014-12-06 12:45:05

4

隨着人們在您的評論說,你可以改變亮度以消極的方式,並推升對比。

此外,sharpen filter對您的情況也非常有用。你可以在OpenCV中做this

4

我認爲你應該嘗試adaptiveThreshold功能與一個大窗口。

#include "opencv2/opencv.hpp" 
using namespace cv; 
int main(int argc,char** argv) 
{ 

    Mat im = imread("c:/data/img1.png",0); 
    cv::namedWindow("ctrl"); 
    int win=62; 
    int th=2100; 
    cv::createTrackbar("win", "ctrl", &win, 500); 
    cv::createTrackbar("th", "ctrl", &th, 10000); 
    while(true) 
    { 
     Mat thresh; 
     medianBlur(im,thresh,15);//helps smooth out smaller noises, which you could also remove by size instead of this way 
     adaptiveThreshold(thresh,thresh,255,ADAPTIVE_THRESH_MEAN_C,THRESH_BINARY,win*2+1,( th/1000.)); 
     imshow("thresh",thresh); 
     if(waitKey(1)==27) 
      exit(0); 
    } 
} 

這裏所有結果(http://www.datafilehost.com/d/99e3d86c)你可能也想看看ImageJ的,它實現了一堆的自動閾值算法。我認爲你需要的是將本地圖像信息考慮在內的東西。

enter image description here enter image description here