radius of rod along its length in an image
10 views (last 30 days)
Show older comments
I have an image (attached) containing a rough rod. I am trying to find the values of radius along the rod's length. The true radius at the edge of the rod is known to me. What would be a good/ elegant way of doing this using matlab image processing tools?
3 Comments
Image Analyst
on 17 Feb 2022
Just threshold to get the rod, then sum the binary image vertically. The sum is the diameter so divide it by 2.
mask = imbinarize(grayImage); % Assuming the mask looks good.....I have not tried it.
horizontalProfile = sum(mask, 1);
radii = horizontalProfile / 2;
Accepted Answer
DGM
on 17 Feb 2022
Edited: DGM
on 17 Feb 2022
I ended up having to do a little manual touchup on the image (attached). It's still not a very good result, and the perspective probably makes the results meaningless, but it should serve as an example.
A = imread('wavyrod.jpg');
A = rgb2gray(A);
% crop it down to save time
A = imcrop(A,[0.5 962.5 4032 572]);
% try to flatten the image and smooth out any noise
Af = imflatfield(A,200);
Af = medfilt2(Af,[10 10]);
%imshow(Af)
% threshold the image and try to clean it up
m = Af>50;
m = bwareafilt(m,1);
m = imfill(m,'holes');
m = imopen(m,strel('disk',30,0));
figure
%imshow(m)
% omit the very end, since it's not a full diameter due to the viewing angle
startx = 3908;
m = m(:,1:startx);
% object width in pixels
profile = sum(m,1);
% assuming end diameter is known, that could be used for scaling
enddia = 25; % mm
scale_estimate1 = enddia/mean(profile(end-10:end)) % from the diameter
% or the ruler could be used for scaling
% this is the distance beween the the lower 2 and 23 cm tickmarks on the ruler
% i just measured this manually
rulerspan = [3440 40]; % pixels [x y]
spanlen = 210; % mm
scale_estimate2 = spanlen/norm(rulerspan) % from the ruler
% we now have two estimates of the scaling factor
% for this example, i'm going to assume the second has preferable accuracy
% note that this is reversed, aligning the visible end of the rod with zero
profilemm = profile * enddia/mean(profile(end-10:end));
% create scaled xdata for the profile
xposmm = linspace(scale_estimate2*numel(profilemm),0,numel(profilemm));
plot(xposmm,profilemm)
% now let's say we want to interpolate this xdata every 1mm
% start by getting new xdata
xposmm_new = 0:1:floor(xposmm(1));
% one approach would be to fit a spline to both interpolate and denoise
pp = fit(xposmm',profilemm','smoothingspline','smoothingparam',0.5);
profilemm_new = pp(xposmm_new);
figure
plot(xposmm_new,profilemm_new) % the new data at every mm
Obviously, the radius would be half that.
I don't feel confident to trust the ruler for scaling, since its length varies by about 12% across the image. In a better setup, using the ruler may be more effective.
6 Comments
DGM
on 28 Feb 2022
For the given image (or a similar setup), I would expect that you're right. The accuracy in getting the exact edge isolated varies due to the reflectivity of the object and the texture of the background. Some edges look exactly like the background since they're a reflection of it.
As I think I mentioned, I've resorted to backlighting parts on a light table to get good edge contrast, but I haven't done it with shiny round parts. Reflections might still be an obstacle, and I know my current digital camera does not like to behave with the flicker from the light table, so that might be another source of frustration.
I guess the brute simple way to do it would be to just smoke the part with lampblack and photograph it against a plain white background. That would be a bit of a mess, but it would be way easier.
More Answers (1)
yanqi liu
on 17 Feb 2022
yes,sir,may be ocr the number and use the scale information to get result,now we can see the ocr process.
im = imread('https://ww2.mathworks.cn/matlabcentral/answers/uploaded_files/896745/image.jpg');
bw = im2bw(im);
bwt = ~rot90(bw,2);
c = ocr(bwt,'CharacterSet','0123456789');
bts = [];
wts = [];
for i = 1 : length(c.Words)
if length(c.Words{i}) ~= 2 || c.WordBoundingBoxes(i,4) > size(bw,2)/40
continue;
end
bts(end+1,:) = c.WordBoundingBoxes(i,:);
wts{end+1} = c.Words{i};
end
[~,ind] = max(bts(:,1));
rect = bts(ind,:);
word = wts{ind};
figure; imshow(rot90(im,2),[]); hold on;
hold on; rectangle('position', rect, 'EdgeColor', 'r', 'LineWidth', 2)
text(rect(1),rect(2)-rect(4)/2,word,'Color','r','FontSize',20);
See Also
Categories
Find more on Lighting, Transparency, and Shading in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!