Here's what I reached so far..Please let me know if there are any suggestions or anything wrong up to this point
% Read image, store it in variable I, and convert it to grayscale
I = imread('1.jpg');
gray = rgb2gray(I);
% Use imtool(gray) to get 5 Regions Of Interest (ROIs) on the drill bit
% edges, denoting the initials and serial numbers 'D1-5' to assign them to
% the drill bit threshold calculations
croppedimg_D1 = imcrop(gray,[2075.03375681172 77.5023160620334 22.4739441746469 15.0290152994543]);
% Obtain the gray threshold using Otsu's graythresh method for each ROI,
% named TD1-5 for each point respectively
TD1 = graythresh(croppedimg_D1);
croppedimg_D2 = imcrop(gray,[1854.03375681172 83.5023160620333 22.4739441746469 15.0290152994543]);
TD2 = graythresh(croppedimg_D2);
croppedimg_D3 = imcrop(gray,[1335.03375681172 102.502316062033 22.4739441746469 15.0290152994543]);
TD3 = graythresh(croppedimg_D3);
croppedimg_D4 = imcrop(gray,[106.033756811718 202.502316062033 22.4739441746469 15.0290152994543]);
TD4 = graythresh(croppedimg_D4);
croppedimg_D5 = imcrop(gray,[129.033756811718 244.502316062033 22.4739441746469 15.0290152994543]);
TD5 = graythresh(croppedimg_D5);
% Obtain the average threshold for the drill bit by summing up ROI
% thresholds and dividing them by their count
avg_T_Drill = (TD1+TD2+TD3+TD4+TD5)/5;
% Use imtool(gray) to get 5 Regions Of Interest (ROIs) on the card
% edges, denoting the initials and serial numbers 'C1-5' to assign them to
% the card threshold calculations
croppedimg_C1 = imcrop(gray,[1733.22437414373 472.442302998379 18.4452136468276 12.3348797142872]);
% Obtain the gray threshold using Otsu's graythresh method for each ROI,
% named TC1-5 for each point respectively
TC1 = graythresh(croppedimg_C1);
croppedimg_C2 = imcrop(gray,[1205.22437414373 480.442302998379 18.4452136468276 12.3348797142872]);
TC2 = graythresh(croppedimg_C2);
croppedimg_C3 = imcrop(gray,[687.724374143729 876.442302998379 18.4452136468276 12.3348797142872]);
TC3 = graythresh(croppedimg_C3);
croppedimg_C4 = imcrop(gray,[707.224374143729 1696.94230299838 18.4452136468276 12.3348797142872]);
TC4 = graythresh(croppedimg_C4);
croppedimg_C5 = imcrop(gray,[1688.22437414373 1722.44230299838 18.4452136468276 12.3348797142872]);
TC5 = graythresh(croppedimg_C5);
% Obtain the average threshold for the card by summing up ROI
% thresholds and dividing them by their count
avg_T_Card = (TC1+TC2+TC3+TC4+TC5)/5;
% read in tiff image and convert it to double format (I'm originally working with a TIF image)
my_image = im2double(I);
my_image = my_image(:,:,1);
% allocate space for thresholded image
image_thresholded = zeros(size(my_image));
% loop over all rows and columns
for ii = 1:size(my_image,1)
for jj = 1:size(my_image,2)
% get pixel value
pixel = my_image(ii,jj);
% check pixel value and assign new value
if pixel < avg_T_Drill
new_pixel = 0;
elseif pixel > avg_T_Card
new_pixel = 256;
else
new_pixel = pixel;
end
% save new pixel value in thresholded image
image_thresholded(ii,jj) = new_pixel;
end
end
BinaryImg = im2double(image_thresholded);
% Create empty mask.
BW = false(size(BinaryImg,1),size(BinaryImg,2));
% Flood fill
row = 231;
column = 1206;
tolerance = 5.000000e-02;
addedRegion = grayconnected(BinaryImg, row, column, tolerance);
BW = BW | addedRegion;
% Flood fill
row = 888;
column = 1596;
tolerance = 5.000000e-02;
addedRegion = grayconnected(BinaryImg, row, column, tolerance);
BW = BW | addedRegion;
% Fill holes
BW = imfill(BW, 'holes');
% Erode mask with disk
radius = 2;
decomposition = 0;
se = strel('disk', radius, decomposition);
BW = imerode(BW, se);
% Dilate mask with disk
radius = 3;
decomposition = 0;
se = strel('disk', radius, decomposition);
BW = imdilate(BW, se);
% Create masked image.
maskedImage = BinaryImg;
maskedImage(~BW) = 0;
% Obtain a sample column using imtool(maskedImage)
SampleCol = maskedImage(1:end, 2585);
% Find indices with white pixels
nonZeros = find(SampleCol == 256);
% Find unwanted noise indices between the drill edges
noiseIndex = find(76 < nonZeros & nonZeros < 200);
% Remove noise indices from the nonZeros vector to show only first and last white pixels of the drill and card
nonZeros(noiseIndex) = [];
% Calculate the drill diameter in pixels by subtracting the index values corresponding to the drill edges
Drill_Diameter_px = nonZeros(2) - nonZeros(1);
% Calculate the card height in pixels by subtracting the index values corresponding to the card edges
Card_Height_px = nonZeros(4) - nonZeros(3);
% Real card height is hardcoded here
Card_Real_Height = 53.98;
% Calculate Spatial Calibration factor by dividing real height in mm by height in pixels
SCF = Card_Real_Height/Card_Height_px;
% Solve for real drill diameter using the previously calculated SCF and the obtained drill diameter in pixels
Drill_Real_Diameter = SCF * Drill_Diameter_px;
% Plot results
figure, imshow(I)
hold on
plot([2585,2585],[nonZeros(3),nonZeros(4)],'--k','LineWidth',1)
caption = sprintf('Card Height = %.2f mm', Card_Real_Height);
text(2050, 600, caption, 'FontSize', 11);
plot([2585,2585],[nonZeros(1),nonZeros(2)],'-k','LineWidth',1)
caption = sprintf('Drill Diameter = %.1f mm', Drill_Real_Diameter);
text(2050, 200, caption, 'FontSize', 11,'Color','black');
