MATLAB Answers

0

Detect orientation of screw image

Asked by Ang Xian Jia on 10 Nov 2019 at 9:15
Latest activity Commented on by Ang Xian Jia on 22 Nov 2019 at 1:18
The screw as shown in the image is not completely horizontal. I would like to detect the orientation of screw and form a new image that can make sure that the screw is completely horizontal. Is there a way to do that?
20.bmp

  2 Comments

KSSV
on 10 Nov 2019 at 9:23
Read the pixels...get the coordinates...use polyfit to fit a straight line, get the slope and try to rotate the coordinates to make slope zero.
Ang Xian Jia on 10 Nov 2019 at 9:46
pixelgraph.png
This is the pixels I read from top part of the screw. May I know what you mean by " try to rotate the coordinates to make slope zero" ? Thanks

Sign in to comment.

2 Answers

Answer by Stephan
on 10 Nov 2019 at 11:23
Edited by Stephan
on 10 Nov 2019 at 11:49
 Accepted Answer

Using this script lets you know which angle to rotate. Then use this information to rotate the image and check the orientation again:
%% read image and find points that should lie on a straight line
img = rgb2gray(imread('20.bmp'));
res = detectHarrisFeatures(img,'MinQuality', 0.1, 'ROI', [1 386 762 20]);
% Extract coordinates of the points
x_vals = double(res.Location(:,1));
y_vals = double(res.Location(:,2));
% find slope and offset of the line formed by the points and use arctan to
% estimate the angle the srew is different from horizontal orientation
slope_and_offset = polyfit(x_vals, y_vals,1);
angle = atand(slope_and_offset(1));
fprintf('\nThe screw is oriented %.5f degree to the horizontal.\n', angle)
%% rotate the image
img_rot = imrotate(img,angle);
% search points again on rotated image
res_new = detectHarrisFeatures(img_rot,'MinQuality', 0.1, 'ROI', [1 395 762 10]);
% Extract coordinates of the points
x_vals_rot = double(res_new.Location(:,1));
y_vals_rot = double(res_new.Location(:,2));
% find slope and offset of the line formed by the points and use arctan to
% estimate the angle the srew is different from horizontal orientation
slope_and_offset_rot = polyfit(x_vals_rot, y_vals_rot,1);
angle_rot = atand(slope_and_offset_rot(1));
fprintf('\nThe screw is oriented %.5f degree to the horizontal after rotation.\n\n', angle_rot)
%% plot results
subplot(1,2,1)
hold on
title('Original Image')
imshow(img)
scatter(res.Location(:,1),res.Location(:,2),'or')
hold off
subplot(1,2,2)
hold on
title('Corrected Image')
imshow(img_rot)
scatter(res_new.Location(:,1),res_new.Location(:,2),'ob')
hold off
The keypoint is to define the ROI to the algorithm, so that you only detect points that are valid to reach high presicion.

  4 Comments

Show 1 older comment
Stephan
on 10 Nov 2019 at 15:12
If we apply the same operation on both sides as i did for the lower part, it should be able to estimate the center line, even if the screw would be conic.
Ang Xian Jia on 10 Nov 2019 at 15:30
Hi Sir Stephan, u means that I should take the average of two polyfit line (top and bottom) to form the centerline?
Stephan
on 10 Nov 2019 at 15:39
Yes, this is what i would try to do.

Sign in to comment.


Answer by Image Analyst
on 10 Nov 2019 at 15:46

An alternative way is to use the radon transform. Basically the radon transform makes projections along a list of angles that you specify. Then you can look at the projections image to identify which angle (angles are columns in the image) is the best one (it will be the column where the brightest value is).
See attached demo where I rotate the football demo image.
00_Screenshot.png

  8 Comments

Ang Xian Jia on 21 Nov 2019 at 11:54
Hi image Analyst,
May I know why the screw will not orientated perfect horizontally for this kind of image?
13.bmp
untitled.png
Image Analyst
on 21 Nov 2019 at 12:45
You should be looking for the minimum sum since the object is dark on a bright background. Plus you're going to have to add an offset because the longest dark stretch is along the diagonal, not along the axis of the bolt.
An alternate way is to just take all the points with find() and then fit them to a line with polyfit. Then get the angle from the arctangent of the slope and then call imrotate(). Something like (untested):
[y, x] = find(binaryImage);
coefficients = polyfit(x, y, 1);
angle = arctand(coefficients(1));
rotatedImage = imrotate(grayImage, -angle);
imshow(rotatedImage);
I've used an approach like this for rectangular objects in the past, and it worked well.
Ang Xian Jia on 22 Nov 2019 at 1:18
Understood. Thank you very much, Image Analyst.

Sign in to comment.