horizontal-vertical only lines

2019-07-09 04:38发布

问题:

I'm new in matlab. I have a block of image as illustrated below:

Whites show pixel that their values are equal to 1 and Blacks show pixel that their values are equal to 0,

I want to get vertical only lines. This means horizontal lines should be removed as illustrated below:

Also I want to get horizontal only lines. This means vertical lines should be removed as illustrated below:

How can I do it in Matlab? I prefer morphological operations for this.

回答1:

Assuming your image is BW below:

% detecting all connected regions:
B = bwboundaries(BW,4);

This results in a cell array B that contains all the "patches" that are made by connecting neighboring cells with value 1 that are connected from one of 4 sides, i.e. not in diagonal.

B = 
    [11x2 double]
    [ 2x2 double]
    [ 3x2 double]
    [ 3x2 double]
    [ 2x2 double]
    [ 3x2 double]
    [ 2x2 double]
    [ 2x2 double]
    [ 3x2 double]
    [ 3x2 double]
    [ 2x2 double]
    [11x2 double]

For example:

>> B{6}
ans =
     3     7
     3     8
     3     7

Each row is one cell coordinates. The first column is its' row, the second its' column, and the first and last cells are always the same.

Now we need to loop through the cells in B, and find which of them are lines, either horizontal or vertical, and save them to new matrices.

% matrices for horizontal and vertical lines:
BWh = zeros(size(BW)); % horizontal lines
BWv = zeros(size(BW)); % vertical lines
for k = 1:numel(B)
    % if the coordinates changes ONLY vertically:
    % a vertical line is where all the coulmn indecies are the same
    % and there are different row indices
    if all(B{k}(1,2)==B{k}(:,2)) && B{k}(1,1)~=B{k}(2,1) 
        BWv(sub2ind(size(BW),B{k}(:,1),B{k}(:,2))) = 1;
    end
    % if the coordinates changes ONLY horizontaly:
    % a vertical line is where all the row indecies are the same
    % and there are different column indices
    if all(B{k}(1,1)==B{k}(:,1)) && B{k}(1,2)~=B{k}(2,2)
        BWh(sub2ind(size(BW),B{k}(:,1),B{k}(:,2))) = 1;
    end
end
subplot 131
imagesc(BWh)
title('Horizontal lines')
subplot 132
imagesc(BWv)
title('Vertical lines')

The "Diagonal edges" are what left after we exclude the lines, so we can just look for what we didn't find so far:

subplot 133
imagesc(BW & ~BWv & ~BWh)
title('Diagonal edges')
colormap 'gray'

This method will ignore anything that is not a one-cell thick line, so for instance, the square in the middle in the image below will be shown only in the Diagonal edges pattern:



回答2:

Interesting question, because there's so many ways to do that. In essence you need to take out consecutive pixels of a spesific dimension. One way I see to solve this is to convolve with a [1 1] or [1 1]' vector and then take out all the elements where you get the values 2.

bw(conv2(bw,[1 1],'same')==2)=0;

this will still leave single pixels that you can take out easily using

bw = bwareaopen(bw,2) ;

this is just the main idea, you probably need to be more careful around the edges, or pad with zeros to avoid edge artifacts that conv2 can make)...

Another idea, use the Hough transform to detect lines and keep only those with theta=0 or 90 deg...