Boundary Finding Examples Colorado School of Mines Department of Electrical Engineering and Computer Science Example 1 – Iterative polygonal fit • Linear approximation: approximate a segment by a line between its endpoints; split at point with largest error, repeat until approximation is good 2 Colorado School of Mines Department of Electrical Engineering and Computer Science clear all close all I = imread('cameraman.tif'); E = edge(I, 'canny'); imshow(E, 'InitialMagnification', 300); hold on % Turn hold on so we can "plot" on top of image % Click on the first point along the contour. fprintf('Pick first point on a contour\n'); while true p1 = round(ginput(1)); % Get x,y coords if ~E(p1(2),p1(1)) fprintf('Try again\n'); else break; end end plot(p1(1),p1(2), 'g*'); Matlab program for polygonal fit (1 of 4) % Trace the boundary, starting from that point. Use 'W' as initial step % direction. Matlab's "bwtraceboundary" seems to have problems occasionally % when the neighbor to the west is occupied. So if it is, let's move p1 to % that point. while E(p1(2),p1(1)-1) % Check if neighbor to the left is occupied p1(1) = p1(1)-1; end pts = bwtraceboundary(E, [p1(2),p1(1)], 'W', 8, Inf, 'clockwise'); N = size(pts, 1); % Number of points 3 Colorado School of Mines Department of Electrical Engineering and Computer Science % Click on the 2nd point along the contour. fprintf('Pick 2nd point on the contour\n'); while true p2 = round(ginput(1)); % Get x,y coords if ~E(p2(2),p2(1)) fprintf('Try again\n'); else break; end end plot(p2(1),p2(2), 'g*'); Matlab program for polygonal fit (2 of 4) % Get the indices of the 1st point in our list. indices1 = find( (pts(:,1)==p1(2)) & (pts(:,2)==p1(1)) ); % Get the indices of the 2nd point in our list. indices2 = find( (pts(:,1)==p2(2)) & (pts(:,2)==p2(1)) ); assert(~isempty(indices2), 'Can''t find point2 along the contour'); % Find the pair of indices that are closest to each other. for i=1:length(indices1) for j=1:length(indices2) d(i,j) = abs(indices2(j) - indices1(i)); end end [i,j] = find(d == min(d(:))); if indices1(i)<indices2(j) i1 = indices1(i); i2 = indices2(j); else i1 = indices2(j); i2 = indices1(i); end Colorado School of Mines Department of Electrical Engineering and Computer Science 4 % Get points from p1 to p2. pts = pts(i1:i2, :); plot(pts(:,2), pts(:,1), 'g*'); % Fit line segments to the points in the contour. % "lineSegs" consists of % [x0, y0, x1, y1] lineSegs = fitLineSegments(pts, [], 2.0); Each row of Matlab program for polygonal fit (3 of 4) % Draw final line segments figure, imshow(I, 'InitialMagnification', 300); for iSeg=1:size(lineSegs,1) p0 = lineSegs(iSeg,1:2); p1 = lineSegs(iSeg,3:4); line([p0(1) p1(1)], [p0(2) p1(2)], 'Color', 'r', 'LineWidth', 3.0); end 5 Colorado School of Mines Department of Electrical Engineering and Computer Science function lineSegs = fitLineSegments(pts, lineSegs, THRESH) % Input array pts is size (N,2), where each row is the coordinates of a % point on the contour, (r,c). N = size(pts,1); % Number of points along contour p1 = pts(1,:); % First point on contour p3 = pts(end,:); % Last point on contour % Draw line from p1 to p3 line([p1(2) p3(2)], [p1(1) p3(1)], 'Color', 'r', 'LineWidth', 3.0); pause Matlab program for polygonal fit (4 of 4) % Find the point p2 that is the furthest from the line from p1 to p3. v = [p3(2)-p1(2); -(p3(1)-p1(1))]; % A vector perpendicular to that line v = v/norm(v); % Get vectors from the first endpoint to all other points. r = pts - repmat(p1,N,1); % The distance from each point to the line is just abs(dot(v,r)) d = abs( v(1)*r(:,1) + v(2)*r(:,2) ); [dmax,i2] = max(d); % Point p2 is the furthest from the line % If dmax is less than the threshold, then we are done. if dmax < THRESH lineSegs = [lineSegs; p1(2) p1(1) p3(2) p3(1)]; else % Recursively fit line segments to each piece. lineSegs = [lineSegs; fitLineSegments(pts(1:i2,:), [], THRESH); fitLineSegments(pts(i2:end,:), [], THRESH)]; end 6 return Colorado School of Mines Department of Electrical Engineering and Computer Science Example 2 – find a square target • Find the square in the image • Squares are frequently used as “fiducial” targets “ARToolkit”, www.hitl.washington.edu/artoolkit Example video http://www.youtube.com/watch?v=5M-oAmBDcZk Colorado School of Mines Department of Electrical Engineering and Computer Science 7 A simple method • Get the boundary of a connected component • Find the point that is furthest from the centroid – assume that is a corner • Then find the point furthest from that detected corner – assume that is the opposite corner • Then find the points that are furthest from the line connecting the two opposite corners Colorado School of Mines • Assume that the square is not too large and not too small Department of Electrical Engineering and Computer Science 8 • Threshold image • Find connected components clear all close all I = imread('square.jpg'); % open file I = rgb2gray(I); imshow(I,[]); BW = im2bw(I, graythresh(I)); BW = ~BW; % invert the image so we look for a white square figure, imshow(BW); % Find connected components [L,nBlobs] = bwlabel(BW); blobs = regionprops(L); Colorado School of Mines Department of Electrical Engineering and Computer Science 9 % Look at the blobs and find the first one that looks like a square. fFoundSquare = false; % This will be set to true if a square is found for i=1:nBlobs if blobs(i).Area > 40000 || blobs(i).Area < 2000 continue; • For each blob, end % Find a point on the boundary of this blob [rows,cols] = find(L==i); [r0,i0] = min(rows); c0 = cols(i0); • get its boundary Find point furthest from centroid % Get coordinates (row,col) along boundary pts = bwtraceboundary(BW, [r0 c0], 'N'); N = size(pts,1); c = mean(pts); % Number of points along the boundary % Get centroid % Find the point furthest from centroid dp = pts - repmat(c,N,1); d = dp(:,1).^2 + dp(:,2).^2; [~,i1] = max(d); % Assume that this is a corner p1 = pts(i1,:); Colorado School of Mines Department of Electrical Engineering and Computer Science 10 • • Find point furthest from first corner Find the points that are furthest from the line connecting the two opposite corners % Get vectors from the first corner to all other points r = pts - repmat(p1,N,1); % Find the point furthest from first corner d = r(:,1).^2 + r(:,2).^2; [~,i3] = max(d); % Assume that this is the opposite corner p3 = pts(i3,:); % Find the points that are the furthest from the line from i1 to i3. v = [p3(2)-p1(2); -(p3(1)-p1(1))]; % A vector perpendicular to that line % The signed distance from each point p to the line is just dot(v,r) d = v(1)*r(:,1) + v(2)*r(:,2); [~,i2] = max(d); % Point 2 is to the right of 1->3 p2 = pts(i2,:); [~,i4] = min(d); % Point 3 is to the left of 1->3 p4 = pts(i4,:); % So the order of point is 1,2,3,4 in counterclockwise order Colorado School of Mines Department of Electrical Engineering and Computer Science 11 • • As partial verification, check side lengths Break out of loop if a square is found % Verify that this is a square - there are many ways to do this. % We will just check to see if the sides are all about the same length. s12 = norm(p1-p2); s23 = norm(p2-p3); s34 = norm(p3-p4); s41 = norm(p4-p1); smax = max([s12,s23,s34,s41]); sthresh = 0.7; % minimum ratio of lengths if (s12/smax > sthresh) && (s23/smax > sthresh) && ... (s34/smax > sthresh) && (s41/smax > sthresh) fFoundSquare = true; break; end end hold on plot(pts(:,2), pts(:,1), 'g*'); hold off Colorado School of Mines Department of Electrical Engineering and Computer Science 12 • Choose the first point to be the one closest to the top left • Draw a colored marker on each corner c = [p1; p2; p3; p4]; % Arbitrarily choose the first point to be the point closest to the top left d = c(:,1).^2 + c(:,2).^2; [~,i0] = min(d); for i=1:4 i1 = i0+(i-1); if i1>4 i1=i1-4; end corners(i,:) = c(i1, :); end figure(1) mycolors = ['r', 'g', 'b', 'y']; hold on for i=1:4 plot(corners(i,2), corners(i,1), 's', 'Color', mycolors(i)); end Colorado School of Mines Department of Electrical Engineering and Computer Science 13 Example 3 – Hough peaks • The left image below is a noisy 200x200 image of two squares, rotated at 45 degrees. An edge detection operation is performed to yield the binary edge image on the right. 14 Colorado School of Mines Department of Electrical Engineering and Computer Science Example 3 – Hough peaks (continued) • Recall the normal representation of a line: x cos θ + y sin θ = ρ θ x ρ y • Where are the peaks in the Hough transform; i.e., what are the values of (ρ,θ) at the peaks? • Describe the relative height of the peaks to each other. 15 Colorado School of Mines Department of Electrical Engineering and Computer Science Example 3 - Solution • The geometry is as shown below. – The lines at +45° have ρ equal to 50√2, 100√2, or 150√2. – The lines at -45° have ρ equal to 50√2, 0, or -50√2. (Or equivalently, you could have one line at θ = -45°, ρ = 50√2, another at θ = -45°, ρ = 0, and the third at θ = 135°, ρ = 50√2.) • The peaks at (+45°, 100√2), (-45°, 0) are twice as big as the others. ρ +45° -45° x x ρ y y 16 Colorado School of Mines Department of Electrical Engineering and Computer Science Example 4 – Generalized Hough • We’ll first create an “R-table” from the template object • Then try to find instances of the object in the test image Template object Test image Image: “part.jpg” Image: “parts.jpg” 17 Colorado School of Mines Department of Electrical Engineering and Computer Science % Create an R-table from the template image T. % Assume that the object of interest is centered in the image. clear all, close all; T = imread('part.jpg'); DY = conv2(T,fspecial('prewitt')); DX = conv2(T,(-1.*(fspecial('prewitt')'))); GMAG = sqrt(DX.^2 + DY.^2); [iHeight,iWidth] = size(GMAG); ixCen = round(iWidth/2); iyCen = round(iHeight/2); iThetaMax = 64; % Center of object % Angles are quantized into this many bins Rcount = zeros(1,iThetaMax); gthresh = 37; % This is the count of vectors for each angle % A threshold for gradient magnitude for ix=1:iWidth for iy=1:iHeight if GMAG(iy,ix) > gthresh theta = atan2(DY(iy,ix),DX(iy,ix)); iTheta = round((180/pi)*theta*iThetaMax/360)+1; if (iTheta <= 0) iTheta = iTheta + iThetaMax; end % Calculate vector to object center from this edge point rx = ixCen - ix; ry = iyCen - iy; % Store in R-table n = Rcount(iTheta) + 1; Rx(iTheta,n) = rx; Ry(iTheta,n) = ry; Rcount(iTheta) = n; % # vectors stored end 18 end end Colorado School of Mines Department of Electrical Engineering and Computer Science % Perform the Generalized Hough Transform to find instances of an object in image I. % Assume that the R-table has already been created. I = imread('parts.jpg'); DY = conv2(I,fspecial('prewitt')); DX = conv2(I,(-1.*(fspecial('prewitt')'))); GMAG = sqrt(DX.^2 + DY.^2); [iHeight,iWidth] = size(GMAG); H = zeros(iHeight,iWidth); % zero the accumulator array iThetaMax = length(Rcount); % Number of discrete angles in the R-table gthresh = 37; % A threshold for gradient magnitude for ix=1:iWidth for iy=1:iHeight if GMAG(iy,ix) > gthresh theta = atan2(DY(iy,ix),DX(iy,ix)); iTheta = round((180/pi)*theta*iThetaMax/360)+1; if (iTheta <= 0) iTheta = iTheta + iThetaMax; end % Access R-table to get all the vectors stored at this angle for i=1:Rcount(iTheta) rx = Rx(iTheta,i); ry = Ry(iTheta,i); x0 = rx + ix; y0 = ry + iy; % Estimated location of object origin if (x0 > 0 && x0 <= iWidth) if (y0 > 0 && y0 <= iHeight) H(y0,x0) = H(y0,x0) + 1; end end % increment accumulator array end end end end imshow(H,[]) Display the accumulator array Colorado School of%Mines Department of Electrical Engineering and Computer Science 19