segmentation of dark lines when background is darker a bit.

7 views (last 30 days)
Helloo, Can someone suggest me how I can do good segmentation of lines, I want to extract those darker lines. I tried normal thresholding but the background is too dark to give me a good result.

Accepted Answer

Image Analyst
Image Analyst on 25 Mar 2016
Edited: Image Analyst on 31 Mar 2016
You can use a modification of an algorithm used to find text on varying background. Basically you scan and do a local Otsu filter. Then you scan and find the local Sobel edges, then take the std dev of that and threshold. Then AND to find only blobs that are locally varying. Then do some cleanup by finding only tall and dark blobs that are large enough. Code is attached. There are a lot of parameters in my well commented code that you can vary to achieve different effects. I've already spent way more time on this than I normally do for people, so I'll leave that to you. Good luck.
  10 Comments
newM
newM on 30 Mar 2016
ok I am sorry about this. I was not aware that it will go public.It is not good for me. so it is kind request please delete the photo. This is true it is not a private consulting service but this the place for academicians to exchange their problem and to solve together not to make trouble for others.
newM
newM on 30 Mar 2016
Image Analyst I am thankful to you for your time and sharing your code. I have problem again if you have time you can look over
if true
% code
***********start % Demo to threshold a document with text where the image is noisy % there is severe non-uniformity of illumination.
function document_threshold()
clc;
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 20;
close all;
% Check that user has the Image Processing Toolbox installed.
hasIPT = license('test', 'image_toolbox');
if ~hasIPT
% User does not have the toolbox installed.
message = sprintf('Sorry, but you do not seem to have the Image Processing Toolbox.\nDo you want to try to continue anyway?');
reply = questdlg(message, 'Toolbox missing', 'Yes', 'No', 'Yes');
if strcmpi(reply, 'No')
% User said No, so exit.
return;
end
end
% Read in gray scale demo image.
folder = dir('C:\Users\');
length(folder);
outputResults='C:\Users';
% Change this if the image is not in the same folder as this m-file.
for k = 1 : length(folder)
baseFileName = folder(k).name;
% Get the full filename, with path prepended.
fullFileName = strcat('C:\Users',folder(k).name);
% Check if file exists.
if ~exist(fullFileName, 'file')
% File doesn't exist -- didn't find it there. Check the search path for it.
fullFileName = baseFileName; % No path this time.
if ~exist(fullFileName, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
grayImage = imread(fullFileName);
% Get the dimensions of the image.
% numberOfColorBands should be = 1.
[rows, columns, numberOfColorBands] = size(grayImage);
if numberOfColorBands > 1
% It's not really gray scale like we expected - it's color.
% Convert it to gray scale by taking only the green channel.
grayImage = grayImage(:, :, 2); % Take green channel.
end
newFigure=figure;
% Display the original gray scale image.
subplot(3, 3, 1);
imshow(grayImage, []);
axis on;
title('Original Grayscale Image', 'FontSize', 8);
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1]);
% Give a name to the title bar.
set(gcf, 'Name', 'Demo to Threshold Document', 'NumberTitle', 'Off')
[rows, columns, numberOfColorChannels] = size(grayImage)
% subplot(3,3,2);
% imshow(grayImage);
% axis on;
% Create the mask
r=[150,181,263,384,443,440,302,183];
c=[273,245,317,361,367,423,401,331];
maskImage = poly2mask(r, c, rows, columns);
subplot(3,3,2);
imshow(maskImage);
ndims(grayImage)
ndims(maskImage)
ndims(uint8(maskImage))
ndims(maskImage)
% Do the masking
maskedImage = grayImage .* uint8(maskImage);
subplot(3,3,3);
imshow(maskedImage);
% Let's compute and display the histogram.
subplot(3, 3, 4);
histogram(grayImage);
grid on;
title('Histogram of Original Image', 'FontSize', 8);
% Do a local Otsu of the gray level image.
fun = @(x) LocalOtsu(x);
A = im2double(grayImage);
localThresh = nlfilter(A, [15, 13], fun);
% Display the image.
subplot(3, 3, 5);
imshow(localThresh, []);
title('Local Otsu', 'FontSize', 8);
% Do a Sobel filter
sobelImage = imgradient(grayImage, 'Sobel');
% Display the image.
subplot(3, 3, 6);
imshow(sobelImage, []);
title('Sobel Image', 'FontSize', 8);
% Display the image's histogram.
subplot(3, 3, 7);
histogram(sobelImage);
grid on;
title('Histogram of Sobel Edge Image', 'FontSize', 8);
% Calculate the local standard deviation
sdImage = stdfilt(sobelImage, ones(9));
% Display the image.
subplot(3, 3, 8);
imshow(sdImage, []);
title('StdDev of Sobel Image', 'FontSize', 8);
% binsToSuppress = [1];
% [lowThreshold, highThreshold, lastThresholdedBand]=threshold(83, 255, sdImage, binsToSuppress);
% Display the image's histogram.
subplot(3, 3, 9);
histogram(sobelImage);
grid on;
title('Histogram of StdDev of Sobel Edge Image', 'FontSize', 8);
% Do a global Otsu of the stddev image.
% Threshold the center pixel only.
binaryImage = sdImage > 6;
% Combine it the the local Otsu image
binaryImage = binaryImage & localThresh;
close(newFigure)
% Display the image.
thridFig=figure;
subplot(3, 3, 1);
imshow(binaryImage, []);
title('Thresholded StdDev Image', 'FontSize', 8);
% Find blobs where the height of the bounding box is some fraction taller than the width.
% Also find the brightness of the blobs so we can remove ones brighter than the mean of the whole image.
labeledImage = bwlabel(binaryImage, 4);
measurements = regionprops(labeledImage, grayImage, 'MeanIntensity', 'BoundingBox', 'Area');
% Concatenate all bounding boxes.
bb = [measurements.BoundingBox];
% Extract heights and widths separately.
heights = bb(4:4:end);
widths = bb(3:4:end);
allAreas = [measurements.Area];
sortedAreas = sort(allAreas, 'descend');
% Determine height to width ratio, and get indexes of what blobs are tall.
tallBlobs = heights > 1.1 * widths; % Logical index
% Find blobs brighter than the mean intensity
meanGrayLevel = mean(grayImage(:));
allBlobIntensities = [measurements.MeanIntensity];
dlmwrite('C:\Users\mean.txt',meanGrayLevel,'-append', 'roffset', 1, 'delimiter','\t','precision',10,'newline', 'pc');
formatSpec = 'Mean %d';
fprintf(formatSpec,meanGrayLevel)
darkBlobs = allBlobIntensities < 1.0 * meanGrayLevel; % Logical index
% Area needs to be more than 20 pixels.
bigEnough = allAreas >= 20;
% Combine to get only tall dark blobs that are big enough.
keepers = tallBlobs & darkBlobs & bigEnough;
keeperIndexes = find(keepers);
% Get a binary Image
binaryImage = ismember(labeledImage, keeperIndexes) > 0;
% We know that there are only 14 lines, so let's just get the largest 14 blobs.
binaryImage = bwareafilt(binaryImage, 14);
%binaryImageLongestLine = bwareaopen(binaryImage, 30);
% Display the image.
subplot(3, 3, 2);
imshow(binaryImage, []);
title('Tall Dark Blobs Only', 'FontSize', 8);
filenameChart = strcat('C:\Users\',folder(k).name);
print('-dbmp256',filenameChart);
% Produce the final image.
finalImage = binaryImage;
set(gca,'visible','off') %hide the current axes
set(get(gca,'children'),'visible','off') %hide the current axes contents
subplot(3, 3, 3);
imshow(grayImage, []);
fontSize = 8;
title('Initial Image', 'FontSize', fontSize);
subplot(3, 3, 4);
imshow(finalImage, []);
title('Final Image', 'FontSize', fontSize);
%save images
%fullFileName = fullfile(outputResults, baseFileName) % No need to worry about slashes now!
%imwrite(finalImage, fullFileName);
close(thirdFig);
end
% Function to take the Otsu threshold of the small patch of gray levels passed in by nlfilter().
function oneThresholdedPixel = LocalOtsu(grayImagePatch)
oneThresholdedPixel = false;
try
[rows, columns] = size(grayImagePatch);
middleRow = ceil(rows/2);
middleColumn = ceil(columns/2);
level = graythresh(grayImagePatch);
% Threshold the center pixel only.
oneThresholdedPixel = ~im2bw(grayImagePatch(middleRow, middleColumn), level);
catch ME
errorMessage = sprintf('Error in function %s() at line %d.\n\nError Message:\n%s', ...
ME.stack(1).name, ME.stack(1).line, ME.message);
fprintf(1, '%s\n', errorMessage);
uiwait(warndlg(errorMessage));
end
return; % from LocalOtsu()
end

Sign in to comment.

More Answers (2)

Guillaume
Guillaume on 23 Mar 2016
You could CLAHE ( adapthisteq in matlab) to enhance the contrast of the image.
im = rgb2gray(imread('test8.png'));
imshow(adapthisteq(im), []);
But there's so much you can do with a poor quality image. Better would be to improve your imaging setup to have better contrasted image (and a more uniform background).
  4 Comments
newM
newM on 25 Mar 2016
True, it is a bmp images and the problem is now we can not take again the photo. I did not ignored his suggestion I did test with his suggestion but because of artifacts not got results. Because of data privacy I can not put whole figure. I try some more test and write you again where I reach. Thank you both.
newM
newM on 1 Apr 2016
can you guide me further Image Analyst
what steps I should tke to get better output?

Sign in to comment.


newM
newM on 31 Mar 2016
Regards to Image Analyst :) Thank you for your kindness & understanding

Categories

Find more on Deep Learning Toolbox in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!