2014-12-03 103 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