say we have a binary image like the one in below

i would like to extract each black line, even if it's not almost connected

i have marked here in red, example of lines that correspond to those to be extracted

**the purpose here is to extract lines a handwritten text ! **

enter image description here enter image description here enter image description here

any suggestions !! Thanks

  • $\begingroup$ Please post an image without the red lines, so that other people will have a change to play around with it $\endgroup$ Jan 1 '15 at 15:31
  • $\begingroup$ Is the first and second image a processing that you did for the third? $\endgroup$ Jan 1 '15 at 18:58

Here is a possible solution:

  • Use FFT2 to find angle of text and approximate spaces between lines
  • Rotate the image to be at 0 angle
  • Sum the image column-wise
  • Find threshold that splits lines of text from non text lines
  • Show lines on rotated image.

It can be improved by finding a more complex curve (rather than line).

Here are the results:

Original enter image description here

After rotation enter image description here

Sum of rotated image column-wise enter image description here

Final results enter image description here

And the code is:

%% 1) Read image
im = imread('http://i.stack.imgur.com/zbHTp.jpg');
im = im(:,:,2);
im = double(im < 100);
im = padarray(im,[40 0]);

%% 2) Find approximate line spacing
F = fftshift(fft2(im));
% figure;imagesc(log(abs(fftshift(fft2(im)))));
[~,iMax] = max(F(:));
[r1,c1] = ind2sub(size(F),iMax);
F(iMax) = 0;
[~,iMax2] = max(F(:));
[r2,c2] = ind2sub(size(F),iMax2);
lineSpaceY = size(im,1)/ abs(r2-r1);
lineSpaceX = size(im,2)/ abs(c2-c1);
angleDeg = abs(90-rad2deg( atan2(lineSpaceX,lineSpaceY)));
imr = imrotate(im,angleDeg);

%% 3) Take a look at 1D signal
S = mean(imr,2);
isText = S > max(S)/2;
isText = imclose(isText,strel('line',lineSpaceY/10,90));
% figure(); plot(isText,'o-');
rp = regionprops(isText,'Centroid');
centerY = cat(1,rp.Centroid);
centerY = centerY(:,2);

%% 4) Show final results
for i=1:numel(centerY);
    hold on;
    plot( [0,size(im,2)],[centerY(i) centerY(i)],'g','LineWidth',2);

First of all, if the lines aren't connected, apply a morphological opening operation to make them so (see morphologyEx in OpenCV).

Now, assuming you have a connected black region, you could apply iterative thining to obtain the skeleton. Or refer to already available ideas such as this one or this one.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.