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

10 views (last 30 days)
Hello, I would like to know the way to find coordinate points (x,y) of nodes in truss image. I give an example of image. In that image, I will get only six edge points and I will exclude two crossed points in the middle. How can I find the coordinate points in that figure?

Accepted Answer

Cedric Wannaz
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

Sign in to comment.

More Answers (1)

Image Analyst
Image Analyst on 29 Sep 2017
Edited: Image Analyst on 29 Sep 2017
Call bwmorph(BW, 'skel', inf) followed by bwmorph(bw, 'branchpoints') followed by find(). See attached demo.

Community Treasure Hunt

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

Start Hunting!