MATLAB: How to find the internal and external diameter of a oil seal that I’ve taken from the camera

image processingImage Processing Toolboximage segmentationmeasure external diametermeasure internal diameter

I've tried to get the internal and external diameters of a oil seal using following code.
% Read your image and binarize it
I = imread('E:\MINI PROJECT\images\WP_20180114_11_52_47_Selfie.jpg');
Igray = rgb2gray(I);
BW = imbinarize(Igray);
% Measure the outer radius
BWout = ~BW;
BWout = imfill(BWout,'holes');
statOuter = regionprops(BWout,{'EquivDiameter','Centroid'});
outerRadius = statOuter.EquivDiameter/2;
% Measure the inner radius
BWin = imclearborder(BW);
BWin = imopen(BWin, strel('disk',5)); % Remove noise
statInner = regionprops(BWin,{'EquivDiameter','Centroid'})
innerRadius = statInner.EquivDiameter/2;
% Show the result
figure
imshow(I)
hold on
viscircles(statOuter.Centroid, outerRadius,'Color','r')
viscircles(statInner.Centroid, innerRadius,'Color','r')
It gives answers only for some pictures but it didn't give an answer for following image
It gives this error
Error using /
Too many input arguments.

Best Answer

The problem is that your image capture conditions are so horrendous as to virtually preclude accurate measurements. Here are some tips:
  1. Use a gray scale camera.
  2. Use a uniform white background, not one all wavy and wrinkled.
  3. Use uniform illumination, not one with bright and dark spots and gradients.
  4. Use a light box that is white all around the interior to help get uniform illumination and eliminate shadows. Plans for cheap ones made from a cardboard box and white paint can be found on the internet.
  5. You may need to use a telecentric lens if the object is not really flat.
  6. Make sure the camera is directly overhead the center of the ring.
  7. Take a shot of the background and divide your image by it to get rid of lens shading.
  8. Put a standard in your image, like a white ceramic tile so you can multiply by a factor if the tile intensity does not match what it's supposed to be. For example if, in your "reference" image the tile is 220 gray levels, and for some test image it's 200, then you need to multiply your image by 220/200 to bring the intensity up to what it's supposed to be.
  9. Use a camera with fixed, manual settings, not automatic settings that can change for any snapshot.
Due to your lousy initial image, the binarization process didn't find the proper threshold.
I've fixed your code to make it work with this image:
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 20;
%===============================================================================
% Get the name of the image the user wants to use.
baseFileName = 'WP_20180114_11_52_47_Selfie.jpg';
folder = pwd
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% The file doesn't exist -- didn't find it there in that folder.
% Check the entire search path (other folders) for the file by stripping off the folder.
fullFileNameOnSearchPath = baseFileName; % No path this time.
if ~exist(fullFileNameOnSearchPath, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
%=======================================================================================
% Read in demo image.
rgbImage = imread(fullFileName);
% Get the dimensions of the image.
[rows, columns, numberOfColorChannels] = size(rgbImage)
% Display image.
subplot(2, 3, 1);
imshow(rgbImage, []);
axis on;
caption = sprintf('Original Color Image\n%s', baseFileName);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Set up figure properties:
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0.05 1 0.95]);
% Get rid of tool bar and pulldown menus that are along top of figure.
% set(gcf, 'Toolbar', 'none', 'Menu', 'none');
% Give a name to the title bar.
set(gcf, 'Name', 'Demo by ImageAnalyst', 'NumberTitle', 'Off')
drawnow;
% Convert to gray scale, but only if it's color, otherwise you'll get an error.
if numberOfColorChannels >= 3
grayImage = rgb2gray(rgbImage);
else
grayImage = rgbImage;
end
% Show histogram
subplot(2, 3, 2);
imhist(grayImage);
grid on;
drawnow;
title('Histogram of Gray Scale Image', 'FontSize', fontSize, 'Interpreter', 'None');
% Binarize by thresholding.
% BW = imbinarize(grayImage);
thresholdGrayLevel = 90;
% Put a red line on the histogram there
hold on;
line([thresholdGrayLevel, thresholdGrayLevel], ylim, 'Color', 'r', 'LineWidth', 2);
BW = grayImage < thresholdGrayLevel;
% Display the image.


subplot(2, 3, 3);
imshow(BW, []);
axis on;
title('BinaryImage', 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
% Take the largest blob only, to get rid of noise.

BW = bwareafilt(BW, 1);
% Fill holes to get final outer binary image.
BWout = imfill(BW, 'holes');
% Display the image.
subplot(2, 3, 4);
imshow(BWout, []);
axis on;
title('Outer BinaryImage', 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
% Get measurements for outer ring.
statOuter = regionprops(BWout,{'EquivDiameter','Centroid'});
outerRadius = statOuter.EquivDiameter/2
% Find the inner radius
BWin = imclearborder(~BW);
% Take the largest blob only, to get rid of noise.
BWin = bwareafilt(BWin, 1);
% BWin = imopen(BWin, strel('disk', 5)); % Remove noise
% Display the image.
subplot(2, 3, 5);
imshow(BWin, []);
axis on;
title('Inner BinaryImage', 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
% Measure the inner radius
statInner = regionprops(BWin, 'EquivDiameter', 'Centroid')
innerRadius = statInner.EquivDiameter/2;
% Show the result
subplot(2, 3, 6);
imshow(rgbImage);
hold on
viscircles(statOuter.Centroid, outerRadius, 'Color', 'r')
viscircles(statInner.Centroid, innerRadius, 'Color', 'r')
message = sprintf('The inner radius = %.2f pixels.\nThe outer radius = %.2f pixels.', innerRadius, outerRadius);
title(message, 'FontSize', fontSize, 'Interpreter', 'None');
uiwait(helpdlg(message));