You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
Camera-to-coin distance finder and comparing their values
5 views (last 30 days)
Show older comments
Hey,
I'm just wondering that is there any chance to do that analysis which to my problem it is Image Segmentation Tutorial analysis of finding its circular are I mean diameter of any circle of the same object in different pictures?, like same coin but its getting away from the camera and in order to detect that distance I just want it to detect the radius change and make a scale for it. Is there any chance that I can do this with a similar code like yours?, Please look at my two examples; I want to calculate their area or radius and compare them with each other so that I can detect the change and find the distance irl with a scale. It would mean a lot if you just answer me back.
Best Regards,
Batuhan
Accepted Answer
Image Analyst
on 10 Dec 2022
Just measure the width of a known thing, like the square or circle, in each image. You can then make up a look up table of working distance (scene-to-lens distance) vs. size in pixels. From that you can fit a function to get you the mm per pixel for any distance. Then when you plug in the known distance, you can measure the size in pixels and report the size in mm.
What was the working distance for each of the two images?
22 Comments
Batuhan Istanbullu
on 10 Dec 2022
Plus when I do the measurement I mean finding the area of that circle, I want to find its location like this too. Is that doable?
Image Analyst
on 10 Dec 2022
Wow, that's pretty close. But yes, it's do able. Since your image is red you can probably find it well like this
[r, g, b] = imsplit(rgbImage);
% Threshold blue channel, or use the Color Thresholder app if your fingers are going to be in there.
mask = b < 200;
% If you know there is only one blob, take the largest one.
mask = bwareafilt(mask, 1);
% Get area
props = regionprops(mask, 'Area');
area = props.Area
Do that for every image. So if there are 20 images, you'll have 20 areas and 20 distances in mm -- that's two 20-element vectors, or one 20 row 2-D matrix.
Batuhan Istanbullu
on 11 Dec 2022
I'm trying to implement your code but I can't, I changed the name rgbImage with my picture's name like 'IMG_4461.jpg' but it gives me this error:
Error using imsplit
Expected input number 1, I, to be one of these types:
double, single, uint8, uint16, uint32, uint64, int8, int16, int32, int64, logical
Error in imsplit (line 54)
validateattributes(I,{'numeric','logical'},{'3d','nonsparse','real','nonempty'},'imsplit','I',1);
Error in batu (line 2)
[r, g, b] = imsplit('IMG_4461.jpg');
Batuhan Istanbullu
on 11 Dec 2022
Okay I solved the error and found this as area =
7845080
and here is my code
rgb = imread('IMG_4461.jpg');
imshow(rgb);
% imtool (rgb) ;
d = drawline;
pos = d.Position;
diffPos = diff(pos);
diameter = hypot(diffPos(1),diffPos(2));
gray_image = rgb2gray(rgb);
imshow(gray_image)
[r, g, b] = imsplit(rgb);
% Threshold blue channel, or use the Color Thresholder app if your fingers are going to be in there.
mask = b < 200;
% If you know there is only one blob, take the largest one.
mask = bwareafilt(mask, 1);
% Get area
props = regionprops(mask, 'Area');
area = props.Area
and here is the image , Idk where I'm doing wrong but I'm trying to take measure of the largest red one.
Image Analyst
on 11 Dec 2022
The problem is you're not really thinking about what the algorithm needs to do and you're just randomly tossing in useless operations, like drawing a line and converting to gray scale. Also, you're not displaying the intermediate images so you don't really know what you did last and what you need to do next.
Here, try this:
rgb = imread('IMG_4461.jpg');
% Display image.
subplot(2, 2, 1);
imshow(rgb);
impixelinfo;
title('Original RGB Image')
[r, g, b] = imsplit(rgb);
% Display image.
subplot(2, 2, 2);
imshow(b);
impixelinfo;
title('Blue Channel')
% Threshold blue channel, or use the Color Thresholder app if your fingers are going to be in there.
mask = b < 140;
% Display image.
subplot(2, 2, 3);
imshow(mask);
impixelinfo;
title('Initial Mask Image')
% Get rid of dark surround.
mask = imclearborder(mask);
% If you know there is only one blob, take the largest one.
mask = bwareafilt(mask, 1);
% Display image.
subplot(2, 2, 4);
imshow(mask);
impixelinfo;
title('Final Mask Image')
% Get area
props = regionprops(mask, 'Area', 'EquivDiameter');
area = props.Area
diameter = props.EquivDiameter
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1227377/image.png)
area =
235361
diameter =
547.422078919377
If you want you could also ask for Centroid and then use viscircles to put the circle at the detected location in the overlay above the image.
Now I don't know what this distance (paper-to-lens distance) this was (Looks like more than 50 mm) but then you'd have to do this for several distances to be able to create a formula that gave the lateral spatial resolution factor (in mm per pixel).
Batuhan Istanbullu
on 11 Dec 2022
Well, sir you have no idea what you have just did. Thank you so much! Also do you mind If I ask something else too?, if you don't mind; the below code gives me the exact positions of the red images that I wanted to take into account, Please look at the images that I've just uploaded. I did found the exact positions of the things but I wanted to find their areas. Can I get them from workspace?
I = imread('IMG_4461.jpg');
J = imrotate(I,180);
imshow(J);
% imtool (rgb) ;
d = drawline;
pos = d.Position;
diffPos = diff(pos);
diameter = hypot(diffPos(1),diffPos(2));
gray_image = rgb2gray(J);
imshow(gray_image)
imshow(J);
% Now to track red objects in real time
% we have to subtract the red component
% from the grayscale image to extract the red components in the image.
diff_im = imsubtract(J(:,:,1), rgb2gray(J));
%Use a median filter to filter out noise
diff_im = medfilt2(diff_im, [3 3]);
% Convert the resulting grayscale image into a binary image.
diff_im = im2bw(diff_im,0.18);
% Remove all those pixels less than 11000px
diff_im = bwareaopen(diff_im,11000);
% Label all the connected components in the image.
bw = bwlabel(diff_im, 8);
% Here we do the image blob analysis.
% We get a set of properties for each labeled region.
stats = regionprops(bw, 'BoundingBox', 'Centroid');
% Display the image
imshow(J)
hold on
%This is a loop to bound the red objects in a rectangular box.
for object = 1:length(stats)
bb = stats(object).BoundingBox;
bc = stats(object).Centroid;
rectangle('Position',bb,'EdgeColor','r','LineWidth',2)
plot(bc(1),bc(2), '-m+')
a=text(bc(1)+15,bc(2), strcat('X: ', num2str(round(bc(1))), ' Y: ', num2str(round(bc(2)))));
set(a, 'FontName', 'Arial', 'FontWeight', 'bold', 'FontSize', 12, 'Color', 'yellow');
end
hold off
Batuhan Istanbullu
on 11 Dec 2022
and in your code, which area or diameter is taking into account the final mask one?, if so what is their units? mm or pixels?
Image Analyst
on 11 Dec 2022
Seems like you ignored everything I did and threw in useless stuff again. OK, whatever. That's not how I'd do it but you can do whatever you want.
I don't understand the grammar of "which area or diameter is taking into account the final mask one". What I am doing is taking the largest blob only and getting the area of that and the "Equivalent Circular Diameter", in other words the diameter of a circle that has the same area as the blob. It's appropriate for roughly circular things, not for squares and rectangles though. The area and diameter have units of pixels because we have not specified the field of view or real world size of the blobs. That is what you were going to do. You were going to put the camera at one distance, measure the diameter, then move the camera to a different distance and measure the diameter again, then at a different distance, and a different one, until you have maybe 5 or 10 lens-to-scene distances. So then you'd have a "pixelsPerMm" spatial calibration factor for every distance. Then you can fit those to a polynomial and be able to get the pixelsPerMm for any distance.
Batuhan Istanbullu
on 11 Dec 2022
no no I didn't ignore anything, I'm just continuing with your way sir. I didn't see your solution thats why. Now I get it. Thank you for all your help !
Batuhan Istanbullu
on 11 Dec 2022
'which area or diameter is taking into account the final mask one' means that, look at the image please; How can I find that area of the blacked one? Cause my object doesnt need to be circular.
Image Analyst
on 11 Dec 2022
Did my way have this:
d = drawline;
pos = d.Position;
diffPos = diff(pos);
diameter = hypot(diffPos(1),diffPos(2));
gray_image = rgb2gray(J);
No. I specifically took that out.
Your last image looks absolutely nothing like the shapes drawn on paper. That image would take an entirely new algorithm.
Batuhan Istanbullu
on 11 Dec 2022
Oh I see, that last image is what I'm trying to do. I'm trying to move my finger by 5 cm at every time and calculate that red the area of that red square every time and compare it.
Batuhan Istanbullu
on 11 Dec 2022
That's why first I wanted to filter out the red shapes in earlier image to see that whether I can find their area while knowing their positioning in that image
Batuhan Istanbullu
on 11 Dec 2022
Can't I just calculate the boundingbox area? or areas of what I bound
Image Analyst
on 11 Dec 2022
If you want you can.
props = regionprops(mask, 'BoundingBox', 'Area');
allAreas = [props.Area]
bb = vertcat(props.BoundingBox);
widths = bb(:, 3);
heights = bb(:, 4);
bbAreas = heights .* widths
Image Analyst
on 11 Dec 2022
Edited: Image Analyst
on 11 Dec 2022
Yes, so? It also works if there is only one blob in your mask.
OK let me be super explicit. Give me 5 photos:
- One taken at 50 mm camera to lens distance.
- One taken at 100 mm camera to lens distance.
- One taken at 150 mm camera to lens distance.
- One taken at 200 mm camera to lens distance.
- One taken at 250 mm camera to lens distance.
Attach them with the paperclip icon.
Batuhan Istanbullu
on 5 Feb 2023
Dear Image Analyst,
I have been using the same code that you have shared with me but for whatever reason I can't find the largest blob in the picture. Can you help me where I'm doing wrong?
rgb = imread('A3.jpeg');
J = imrotate(rgb,180);
subplot(2, 2, 1);
imshow(J);
impixelinfo;
title('Original RGB Image')
[r, g, b] = imsplit(J);
subplot(2, 2, 2);
imshow(r);
impixelinfo;
title('Blue Channel')
mask =r <110 ;
subplot(2, 2, 3);
imshow(mask);
impixelinfo;
title('Initial Mask Image')
mask = imclearborder(mask);
mask = bwareafilt(mask, 1);
subplot(2, 2, 4);
imshow(mask);
impixelinfo;
title('Final Mask Image')
% Get area
props = regionprops(mask, 'Area', 'EquivDiameter', 'BoundingBox', 'Centroid');
area = props.Area;
diameter = props.EquivDiameter;
hold on
for object = 1:length(props)
bb = props(object).BoundingBox;
bc = props(object).Centroid;
rectangle('Position',bb,'EdgeColor','r','LineWidth',2)
plot(bc(1),bc(2), '-m+')
a=text(bc(1)+15,bc(2), strcat('X: ', num2str(round(bc(1))), ' Y: ', num2str(round(bc(2)))));
set(a, 'FontName', 'Arial', 'FontWeight', 'bold', 'FontSize', 12, 'Color', 'yellow');
end
Image Analyst
on 5 Feb 2023
This should do it:
mask = bwareafilt(mask, 1);
subplot(2, 2, 4);
imshow(mask);
If all you see is black, then there is nothing in the original mask image -- no blobs at all.
More Answers (0)
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)