1

When using a binary image with several lines I know that this code displays the longest line:

lineStats = regionprops(imsk, {'Area','PixelIdxList'});
[length, index] = max([lineStats.Area]);
longestLine = zeros(size(imsk));
longestLine(lineStats(index).PixelIdxList)=1;
figure
imshow(longestLine)

Is there a way to display the second longest line? I need to display a line that is a little shorter than the longest line in order to connect them.

EDIT: Is there a way to display both lines on the binary image figure?

Thank you.

Genevieve
  • 975
  • 2
  • 21
  • 35
  • Regarding your edit. Yes, simply use `index` and `index2` from Trogdor's code and repeating the `longestLine(...) = 1;` calculation twice - once for each variable. – rayryeng Aug 30 '16 at 14:04

3 Answers3

5

I would set the longest line to zero and use max again, after I copy the original vector.

lineStats = regionprops(imsk, {'Area','PixelIdxList'});
[length, index] = max([lineStats.Area]);
lineAreas = [lineStats.Area]; %copy all lineStats.Area values into a new vector
lineAreas(index) = NaN; %remove the longest line by setting it to not-a-number
[length2, index2] = max(lineAreas);

EDIT: Response to new question

sort may be a more straight forward approach for multiples, but you can still use max.

lineAreas = [lineStats.Area]; %copy all lineStats.Area values into a new vector
% add a for loop that iteratively stores the desired indices
nLines = 3; 
index = zeros(1,nLines);
for iLines = 1:nLines
    [length, index(iLines)] = max(lineAreas);
    lineAreas(index) = NaN; %remove the longest line by setting it to not-a-number
end
longestLine = zeros(size(imsk));
% I cannot be certain this will work since your example is not reproducible
longestLine([lineStats(index).PixelIdxList]) = 1;
figure
imshow(longestLine)
Trogdor
  • 1,346
  • 9
  • 16
  • 1
    More efficient than sorting. You have my vote. +1. – rayryeng Aug 30 '16 at 13:44
  • 1
    But less general, what if you want the 5th longest line? Or if you want the 2nd, 4th and 6th shortest lines? –  Aug 30 '16 at 14:05
  • @SembeiNorimaki The question is not generalized. The OP specifically wants the second longest line. If the question was asking for the n'th longest line, that's a different story. – rayryeng Aug 30 '16 at 14:32
2

Instead of using max use sort in descending order and take the second element. Like max, sort also provides the indexes of the returned values, so the two functions are pretty compatible.

eStats = regionprops(imsk, {'Area','PixelIdxList'});
[length, index] = sort([lineStats.Area], 'descend');
longestLine = zeros(size(imsk));
longestLine(lineStats(index(2)).PixelIdxList)=1; % here take the second largest
figure
imshow(longestLine)
  • Instead of `index(2)` you can use `index([2,3])` to display the 2nd and 3rd longest lines. Just provide a vector with the lines that you want to display. –  Aug 30 '16 at 14:24
2

As an alternative with focus on performance and ease of use, here's one approach using bwlabel instead of regionprops -

[L, num] = bwlabel(imsk, 8);
count_pixels_per_obj = sum(bsxfun(@eq,L(:),1:num));
[~,sidx] = sort(count_pixels_per_obj,'descend');

N = 3; % Shows N biggest objects/lines
figure,imshow(ismember(L,sidx(1:N))),title([num2str(N) ' biggest blobs']) 

On the performance aspect, here's one post that does some benchmarking on snowflakes and coins images from MATLAB's image gallery.

Sample run -

imsk = im2bw(imread('coins.png')); %%// Coins photo from MATLAB Library

N = 2:

enter image description here

N = 3:

enter image description here

Community
  • 1
  • 1
Divakar
  • 218,885
  • 19
  • 262
  • 358