# How to find intersection coordinates of node points in truss image?

10 views (last 30 days)

Show older comments

ayemoe aung
on 29 Sep 2017

Commented: Cedric Wannaz
on 10 Oct 2017

##### 1 Comment

### Accepted Answer

Cedric Wannaz
on 29 Sep 2017

Edited: Cedric Wannaz
on 2 Oct 2017

If you are always dealing with regular trusses, your best option may be to detect vertical and horizontal edges by summation over dimensions 1 and 2:

img = im2bw(imread('TrussExt1.png')) ;

subplot(1,2,1) ; plot(sum(img,1)) ; grid('on') ; title('Sum over rows') ;

subplot(1,2,2) ; plot(sum(img,2)) ; grid('on') ; title('Sum over columns') ;

Getting the relevant nodes coordinates hence just means getting these mins:

>> c = find(sum(img, 1) < size(img, 1)/2)

c =

21 22 23 183 184 185 346 347 348 508 509 510 671 672 673

we see that, as the horizontal and vertical lines are 3 pixels wide, we get three close numbers per min, and we can take the "middle ones" as follows:

>> c(2:3:end)

ans =

22 184 347 509 672

Putting all that together we get:

img = im2bw(imread('TrussExt1.png')) ;

c = find(sum(img, 1) < size(img, 1)/2) ;

c = c(2:3:end) ;

r = find(sum(img, 2) < size(img, 2)/2) ;

r = r(2:3:end) ;

[R, C] = meshgrid(r, c) ;

imshow(img) ;

hold('on') ;

plot( C(:), R(:), 'rx', 'MarkerSize', 10, 'LineWidth', 3 ) ;

If you are not always dealing with regular trusses, your best option may be to detect the diagonal cross nodes and to build a grid based on them, using the position of the outer boundaries found by taking the first and last mins using the approach developed above.

Here is an example, where we spot the nodes that you don't want to get:

img = im2bw(imread('TrussExt2.png')) ;

ker = [0,0,0,1,1,1,1,1,1,1,0,0,0; ...

1,1,0,0,0,1,1,1,0,0,0,0,1; ...

1,1,1,0,0,0,1,0,0,0,1,1,1; ...

1,1,1,1,0,0,0,0,0,1,1,1,1; ...

1,1,1,1,0,0,0,0,0,1,1,1,1; ...

1,1,1,0,0,0,0,0,0,0,1,1,1; ...

1,1,0,0,0,1,1,1,0,0,0,1,1; ...

0,0,0,0,1,1,1,1,1,0,0,0,0] ;

ker = 10 * (1 - 2*ker) ; % {0,1} -> {10,-10}.

ker = rot90(ker, 2) ;

cv = conv2( 1-img, ker, 'same' ) ;

[r,c] = find(cv > 0.7*max(cv(:))) ;

figure() ;

imshow(img) ;

hold('on') ;

plot(c, r, 'ro', 'MarkerSize', 10, 'LineWidth', 3) ;

Applied to TrussExt2.png attached to my answer, we get:

which shows that it is working pretty well. Depending the quality of the image, we may have to filter/cluster the output of FIND, but in this case we don't. I'll stop here but with a little extra work, you can find the nodes of the "multi-scale" rectangular grid that corresponds to these "cells centers".

Another approach could consist in performing more shape-specific convolutions, in order to target the 6 or 7 possible geometries of interest. As the width of the non-diag. lines is 3 pixels, it could be done as follows:

img = im2bw(imread( 'truss.JPG')) ;

imshow(img) ;

hold('on') ;

np = 3 ; B = ones(np) ;

kernels = {[-B,-B,-B;-B, B, B;-B, B, B], ... % sym. lower right

[-B,-B,-B; B, B, B; B, B, B], ... % sym. lower middle

[-B,-B,-B; B, B,-B; B, B,-B]} ; % sym. lower left

kernels = [kernels, cellfun(@flipud, kernels, 'UniformOutput', false)] ;

nKer = numel(kernels) ;

colors = jet(nKer) ;

for kId = 1 : nKer

cv = conv2(1-2*img, kernels{kId}, 'same') ;

[r, c] = find(cv == max(cv(:))) ;

plot(c, r, 'x', 'Color', colors(kId,:), 'MarkerSize', 20, 'LineWidth', 3) ;

end

If you have many nodes of each type/shape though, you may need to set a tolerance ( cv >= tol*max(cv(:)) ) and aggregate close points (which brings us back to clustering).

Or, if you know the number of relevant points in advance, you can reduce you problem to a peak identification problem or a clustering problem:

img = im2bw(imread('truss.JPG')) ;

n = 3 ; B = ones( n ) ; ker = [B, 10*B, B; 10*B, 10*B, 10*B; B, 10*B, B]/(3*n)^2 ;

cv = conv2(1-img, ker, 'same') ;

surf(cv)

where you see that all straight lines and diagonal crosses are below the level of the 6 relevant nodes. I defined the weights of the blocks in the kernel for that purpose. The condition is that elements of the "high" blocks are greater than twice the value of elements of the "low" blocks, and elements of the "low" blocks must be positive (I picked 10 and 1 as weights of B to be on the safe side).

##### 9 Comments

### More Answers (1)

Image Analyst
on 29 Sep 2017

Edited: Image Analyst
on 29 Sep 2017

##### 0 Comments

### See Also

### Categories

### Products

### Community Treasure Hunt

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

Start Hunting!