Edge and corner detection using Hough Transform

Hello, I am trying to write a code that will ultimately detect and plot the corners of a PCB as well as outline the two sides and top edge shown in the camera view. I am trying to do this using a Houghs Transform and line identification. I want to outline the three edges shown in the camera view ( two sides and top edge) and plot the intersections of the top line with the two side lines, marking the top two corners of my PCB. I Have a code that does a simple line detection based off MATHWORKs documentation. I will also share the edge detected picture as well as the lines overlayed on the original camera view. Can anyone explain why only the right edge is being detected, and steps i can take to ensure the other that the other two edges (top and left side) are to be detected and outlined as well?
:
clc; clear all; close all
%% Initialize Cameras
camList = webcamlist; % camera list, figure which is top view
cam = webcam(3);
cam.Resolution='1280x960';
%% set parameters
filter=105; %Intensity of pixel to base filter on; originally at 100
line_num=3;
fill_gap=200;
parameters=[filter,line_num,fill_gap]; % detection parameters
%% Take image
I2=snapshot(cam);
imshow(I2)
%% Turn image to grayscale
I0=rgb2gray(I2);
imshow(I0)
%% Index pixels that are lighter than filter value
index=find(I0<parameters(1));
%% Make Matrix of same size as original picture w/ all black
Ix=zeros(size(I0));
%% Paste pixels that passed filter onto the all black matrix
Ix(index)=I0(index);
imshow(Ix)
%% Detect Edges of newly created, whited out image
I3 = edge(Ix,'Roberts');
imshow(I3)
%% Houghs Transform
[H, theta, rho] = hough(I3)
P = houghpeaks(H,parameters(2),'threshold',ceil(0.7*max(H(:))));
%% plot peaks
imshow(H,[],'XData',theta,'YData',rho,'InitialMagnification','fit');
xlabel('\theta'), ylabel('\rho');
axis on, axis normal, hold on;
plot(theta(P(:,2)),rho(P(:,1)),'s','color','white');
%%
lines = houghlines(I3, theta, rho, P,'FillGap',parameters(3)); %info about the lines extracted
%%
figure, imshow(I2), hold on
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');
% Plot beginnings and ends of lines
plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');
end

1 Comment

Also, here is an example image from the camera so that you can reproduce the exact results:

Sign in to comment.

 Accepted Answer

Because you are detecting edges/corners of a simple convex polygon, I would recommend downloading pgonCorners,
load Image
[r,g,b]=imsplit(Image);
BW=g>120 &b>90 ;
BW=bwareafilt(imclose(BW,ones(5)),1);
p=polyshape(fliplr(pgonCorners(BW,4)));
imshow(Image);
hold on
plot(p,'FaceColor','none','EdgeColor','m','LineWidth',5)
hold off

3 Comments

That works very well, could the pgonCorners funcgtion be modified so that i can identify each gold rectangular pad at the top of the PCB?
I doubt it, but you could use pgonCorners to find the corners of the thick-bordered rectangle at the bottom of the image from the BW image developed below. This will give you enough landmarks to unravel the geometry of the entire PCB, using fitgeotrans or fitgeotform2d.
load Image
[r,g,b]=imsplit(Image);
BW=g>120 &b>90 ;
BW=bwareafilt(imclose(BW,ones(5)),1);
box=imclose(r>220 & b>220 & g>220 & BW, ones(7));
z=box(end,:);
box(end,:)=1;
box=bwareafilt(imfill(box,'holes'),1);
box(end,:)=z;
imshow(box)
Thats the route i was originally going to go, thanks a lot. you helped a ton, sorry for the delay on accepting

Sign in to comment.

More Answers (1)

The whole approach is wrong. You should just do shape detection. Just
  1. threshold
  2. find centroid
  3. find boundary coordinates
  4. find distance of centroid to all boundary coordinates
  5. Use findpeaks to find peaks of the distances plot.
In short:
mask = grayImage > threshold % Or use Color Thresholder
mask = brareafilt(imfill(mask, 'holes'), 1); % Take largest blob.
props = regionprops(mask, 'Centroid'); % Find centroid.
boundary = bwboundaries(mask);
boundary = boundary{1};
xb = boundary(:, 1);
yb = boundary(:, 2);
distances = sqrt((xb - props.Centroid(1)).^2 + (yb - props.Centroid(2)) .^ 2);
plot(distances, 'b-');
grid on
[peakValues, peakIndexes] = findpeaks(distances);
and so on. I'm sure you can finish it. Let me know if you can't, and why you want the coordinates of the edges (what will that enable you to do?).
The peaks are the corners of the board. See attached demos.

8 Comments

I need to mark the center (or as close to) the 8 gold pads on the top of the PCB, im reworking a past dissertation for a different PCB as the image processing and gold pad marking is based off of the boards geometry. These coordinates are then used to move an extruder to line up with the PCB for wiring. Thank you for your response, Im going to need a little bit of time to go through those demos and figure out if this is the way i should go.
@Sam Blake aha! Now we're getting somewhere. What we have is:
So you really want to know the centroid of the gold pads and you thought getting the edges was a step towards that. So do you want to know
  1. the centroid of the gold pads in pixel coordinates?
  2. Or the shortest distance of the pad to the closest edge of the PCB?
In case 1 you can use some algorithm to segment the gold pads and then use regionprops. In case 2, you'll have to do case 1 and then call bwboundaries on the entire PCB and then use sqrt() and min() to find the boundary point closest to each centroid, and then multiply by a scaling factor if you need the distance in real world units such as millimeters.
I need the coordinates of the centroids of the gold pads in milimeters so that i can line up a microelectrode extruder to each gold pad using motors. I believe i would need a mix of both cases as i would need the distances from the edges to the gold pads, as well as distance between each gold pad and the coordinates for each gold pad. Ultimately, this will be an automated process in which the camera locates the location of a gold pad -> moves motors to line up an extruder -> extrude electrode onto gold pad -> locate next gold pad and repeat. Sorry, I should have given the full scope of the project in the original post. Again, I appreciate your response and it will take me a little bit to make sense of all of this as i am new to image processing.
Also, I am curious about the 'brareafilt' function you use in your first answer, I cant seem to find that in any documentation anywhere, Perhaps you meant bwareafilt?
Sorry for the delay I was busy. I still think your whole approach is wrong, especially so after reading your comment to me. But we really need to know if your extruder/robot is using the same coordinate system as your camera and image. If it is, you don't need the edges of the PCB or the corners of it. You just need to find the solder pads, which none of this does. However if the extruder robot operates on it's own coordinate system, we're going to have to convert the pixel coordinates of the pads into extruder coordinates. And we'd need to know if the robot has a fixed coordinate system with repect to the lab countertop, mounting jig or whatever, or if it adjusts it's coordinate system to the location of the PCB. Like the PCB might be anywhere but the upper left corner is always (0,0) millimeters as far as the robot is concerned.
No need to apologize. So my extruded is horizontally fixed on a rotary stage, it only rotates about the z axis if x and y is looking straight down on the table. The PCB is attached to a fixed template that can move in the z and x direction, which we’ll say is alongside the rotary stage and perpendicular to the extruder. The coordinates for the stage movement is based off of the motion controller specific software but it will be in mm or steps, which I’ve already made conversions for. As I said before this is already completed work for the most part as it’s based off of a published dissertation and a previously working machine, I’m just re-working it with a different motion controller and PCB. Im going to link my final product from my image processing that I got today. I appreciate your insights as I’m going to be looking through the demo codes and trying to make more Sense of them in the future. Looking through your profile, I’m sure if this was your project you’d finish it in a half hour instead of a few weeks like me.

Sign in to comment.

Asked:

on 27 Jul 2023

Moved:

on 1 Aug 2023

Community Treasure Hunt

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

Start Hunting!