I have problem with low contrast image segmentation. Task is to find surface defects. They are visible (defects are always dark areas) but the contrast of image is very low. Below two samples.
I have tried enhance contrast and then tresholding:
Mat tmp1 = imread("C:\\framesRoi\\311.bmp",0);
stretchContrast(tmp1);
threshold(tmp1,tmp1,75,255,THRESH_BINARY);
where stretch contrast 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);
}
}
But this approach failed. There are many false detections and not all defects are detected:
Here is zip with test frames: https://dl.dropboxusercontent.com/u/47015140/testFrames.rar
Essentially, what this means is that if less than 35% of the range of brightness occupies the full range of the data type, then the image is considered low contrast. To make this a concrete example, consider that an image in OpenCV is represented by an unsigned 8-bit integer that has a range of values [0, 255].
Edge-based segmentation is one of the most popular implementations of segmentation in image processing. It focuses on identifying the edges of different objects in an image.
It can be explained as follows: given a color image I, let us consider the of pixels, where , , and is the th color component in the used color space. The segmentation is defined as an array , , assigning a label to each pixel of the image, indicating if it belongs to the background or the foreground.
Try clustering the image by gray level using a clustering method such as kmeans. Below I've used kmeans directly on the images without any gray level transformations (using 3 clusters gave me better results). You should be able to improve results by clustering a preprocessed image using methods outlined in the comments.
Shape of the clusters may slightly vary due to the randomness of kmeans.
Now if you take connected components of the clustered image and calculate the average gray level of those regions, the defects should have a lower average than the other regions.
I did clustering part in 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))
As people said in your comment, you can change the brightness in a negative way and push up the contrast.
Moreover, the sharpen filter is also very useful for your case. You can do this in OpenCV.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With