MATLAB: Pixel to Area conversion accruacy issue with Matlab and im2bw function

digital image processingimage analysisimage processingImage Processing ToolboxMATLABpixel area

I am reformatting and reposting this question to hopefully make it easier for more people to help.
I am writing a short Matlab script to use im2bw to calculate the area of objects in the image. I am trying to validate that the areas are being calculated correctly, but on the reference image I am using the last square's area is 2% off and I cannot figure out why.
myFolder = 'Your Directory';
% Get a list of all files in the folder with the desired file name pattern.
filePattern = fullfile(myFolder, '*.png'); % Change to whatever pattern you need.
theFiles = dir(filePattern);
for k = 1 : length(theFiles)
baseFileName = theFiles(k).name;
fullFileName = fullfile(theFiles(k).folder, baseFileName);
J = imread(fullFileName);
%J = imcrop(I,[500,200,4400,3500]);
BW = im2bw(J,0.3);
BW2 = imcomplement(BW);
BW3 = imfill(BW2,4,'holes');
%figure(1)
%imshowpair(I,BW3,'montage')
stats = regionprops(BW3,'area','PixelList','majoraxislength','minoraxislength');
area = zeros(size(stats));
for i = 1:size(stats,1)
area(i) = stats(i).Area;
end
scale = 1e-6;
%scale = 3.134755344e-8;
cutoff = 0;
area = area*scale;
stats(area<cutoff)=[];
area(area<cutoff)=[];
writematrix(area,'Your Directory','WriteMode','append')
end
figure(1)
imshowpair(J,BW3,'montage')
The image is 1000×1000 with 20×20, 100×100, 100×200, and 200×200 squares that I use as a reference.
I assumed the reference image in reality was 1mx1m and scaled accordingly, but the 200×200 square seems to not come out exactly right. The result is 0.0392 when it should be 0.04.
Additionally I have some issues overall with the accuracy of the im2bw function when trying to calculate area using other images, where I get 10-20% error. Any insights into this issue would be awesome as well.

Best Answer

  • As you can see from this corrected code:
    clc; % Clear the command window.
    fprintf('Beginning to run %s.m ...\n', mfilename);
    close all; % Close all figures (except those of imtool.)
    imtool close all; % Close all imtool figures.
    clear; % Erase all existing variables.
    workspace; % Make sure the workspace panel is showing.
    fontSize = 22;
    myFolder = pwd; % 'Your Directory';
    % Get a list of all files in the folder with the desired file name pattern.
    filePattern = fullfile(myFolder, 'ar*.png'); % Change to whatever pattern you need.
    theFiles = dir(filePattern)
    for k = 1 : length(theFiles)
    baseFileName = theFiles(k).name;
    fullFileName = fullfile(theFiles(k).folder, baseFileName);
    rgbImage = imread(fullFileName);
    %J = imcrop(I,[500,200,4400,3500]);
    BW = im2bw(rgbImage,0.3);
    BW2 = imcomplement(BW);
    BW3 = imfill(BW2,4,'holes');
    stats = regionprops(BW3,'area','PixelList','BoundingBox');
    areaInPixels = [stats.Area]
    bb = vertcat(stats.BoundingBox);
    allWidthsInPixels = bb(:, 3)
    allHeightInPixels = bb(:, 4)
    scale = 1e-6;
    areaInMm = areaInPixels * scale
    % %scale = 3.134755344e-8;
    % cutoff = 0;
    % stats(areaInMm<cutoff)=[];
    % areaInMm(areaInMm<cutoff)=[];
    %
    % writematrix(areaInMm,'Your Directory','WriteMode','append')
    end
    % figure(1)
    % imshowpair(rgbImage,BW3,'montage')
    fprintf('Done running %s.m ...\n', mfilename);
    The areas, widths, and heights are
    areaInPixels =
    400 10000 20000 39204
    allWidthsInPixels =
    20
    100
    200
    198
    allHeightInPixels =
    20
    100
    100
    198
    areaInMm =
    0.0004 0.01 0.02 0.039204
    so your last rectangle is not 200x200, it's 198x198.
    It is probably because your large rectangle is ringed with a value of 127, unlike the other rectangles, and that 127 is below the threshold so it's not considered part of the blob. Why does only that one blob have a one pixel wide layer of 127 surrounding it?
    Try a manual threshold instead.
    BW = rgbImage(:, :, 1) < 255;
    imshow(BW);
    % BW2 = imcomplement(BW);
    % BW3 = imfill(BW2,4,'holes');
    BW3 = imfill(BW,4,'holes');
    That will work.