Binarization to Crop Image

7 views (last 30 days)
Brian Peoples
Brian Peoples on 6 Jul 2020
Commented: Image Analyst on 8 Jul 2020
In my code I use binarization to crop my region of interest from a photograph to observe lightness values as shown bellow:
This is my code:
I0 = imread(f{3}); %f{3} is some random photo in this case
I1 = I0(:,:,3); % select 3d channel
I2 = im2bw(I1,graythresh(I1)-0.1); % binarization
figure(n);
imshow(I2)
h = msgbox('select region of interest');
uiwait(h)
p = ginput(1); % pick point
I3 = bwselect(~I2,p(1),p(2)); % select region of interest
I4 = cat(3,I3,I3,I3);
I5 = uint8(I4).*I0; % crop rgb image
imshow(I5);
My question is as follows:
I made some modifications to my image and now it is:
My current code (even when I try and tweak the threshold) won't strictly pick up the piece of hair! I really ned help just getting the hair to pick up in the crop!

Accepted Answer

Image Analyst
Image Analyst on 6 Jul 2020
I would try to have the blue tape completely surround the hair and then do color segmentation on the blue tape. Then pick the blobs that are not blue tape and get their centroids. The blob with the centroid closest to the middle of the image is the hair mask.
% Demo to mask of hair switch.
% By Image Analyst.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clearvars;
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 16;
fprintf('Beginning to run %s.m ...\n', mfilename);
%-----------------------------------------------------------------------------------------------------------------------------------
% Read in image.
folder = pwd;
baseFileName = 'image.jpeg';
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
rgbImage = imread(fullFileName);
[rows, columns, numberOfColorChannels] = size(rgbImage);
% Display the RGB image full size.
subplot(2, 2, 1);
imshow(rgbImage, []);
axis('on', 'image');
caption = sprintf('Original Image : "%s"', baseFileName);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Set up figure properties:
% Enlarge figure to full screen.
hFig1 = gcf;
hFig1.Units = 'Normalized';
hFig1.WindowState = 'maximized';
% 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.
hFig1.Name = 'Demo by Image Analyst';
% Do color segmentation to get the blue tape.
[BW,maskedRGBImage] = createMask(rgbImage);
mask = ~BW;
% Get rid of blobs smaller than 10,000 pixels.
mask = bwareaopen(mask, 10000);
% Display the binary image.
subplot(2, 2, 2);
imshow(mask, []);
axis('on', 'image');
caption = sprintf(' Mask Image');
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Get the area and centroid.
labeledImage = bwlabel(mask);
props = regionprops(labeledImage, 'Area', 'Centroid');
allAreas = [props.Area]
xy = vertcat(props.Centroid);
% Find out which one is closest to the middle.
x = xy(:, 1);
middlex = columns/2
distanceFromMiddle = abs(x - middlex)
[minDistance, indexOfMiddle] = min(distanceFromMiddle)
% Keep the middle blob.
hairMask = ismember(labeledImage, indexOfMiddle);
hairMask = imfill(hairMask, 'holes');
% Display the RGB image full size.
subplot(2, 2, 3);
imshow(hairMask, []);
axis('on', 'image');
caption = sprintf('Hair Mask');
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
%=====================================================================================================
% function [BW,maskedRGBImage] = createMask(RGB)
%createMask Threshold RGB image using auto-generated code from colorThresholder app.
% [BW,MASKEDRGBIMAGE] = createMask(RGB) thresholds image RGB using
% auto-generated code from the colorThresholder app. The colorspace and
% range for each channel of the colorspace were set within the app. The
% segmentation mask is returned in BW, and a composite of the mask and
% original RGB images is returned in maskedRGBImage.
% Auto-generated by colorThresholder app on 06-Jul-2020
%------------------------------------------------------
% Convert RGB image to chosen color space
I = rgb2hsv(RGB);
% Define thresholds for channel 1 based on histogram settings
channel1Min = 0.410;
channel1Max = 0.670;
% Define thresholds for channel 2 based on histogram settings
channel2Min = 0.000;
channel2Max = 1.000;
% Define thresholds for channel 3 based on histogram settings
channel3Min = 0.000;
channel3Max = 1.000;
% Create mask based on chosen histogram thresholds
sliderBW = (I(:,:,1) >= channel1Min ) & (I(:,:,1) <= channel1Max) & ...
(I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ...
(I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max);
BW = sliderBW;
% Initialize output masked image based on input image.
maskedRGBImage = RGB;
% Set background pixels where BW is false to zero.
maskedRGBImage(repmat(~BW,[1 1 3])) = 0;
end
  2 Comments
Brian Peoples
Brian Peoples on 7 Jul 2020
So I intend on using this for both blonde/black hair to notice differences in their lightness & RGB values. I have another picture:
This same cropping method won't work on this hair... I was wondering if you knew how I could go about this? Possibly just change the whole background to blue? Even then I can't get the middle segment of the hair in the crop is my guess just because the lightness values are too high there
Image Analyst
Image Analyst on 7 Jul 2020
What are you trying to measure? The shine on the hair? Can you fix your camera and field of view so that the hair switch is always in the same rows and columns of the image? I'd also make your tabletop all blue. And make the tape more matte and less shiny because there is white in both the hair and tape. It would also be helpful if you can make the hair totally surrounded by blue tape.
One way to do it is to train with with a linear discriminant, like the attached demo. Have 3 classes (desk, blue, hair), or two (blue and non-blue) if you can make the desktop blue. Then draw out each class roughly. Then it will take those regions and train a classifier that's not bad. Then you can clean it up with morphological things like removing noise specks or things touching the border or based on position, or whatever. Here's one classifier:

Sign in to comment.

More Answers (1)

Brian Peoples
Brian Peoples on 7 Jul 2020
Yes, lightness and RGB values. I can try changing the tabletop to blue and making sure the tape is more matte to block the excess reflectance. If this does not work, I might have to make a camera setup where each image captures holds the switch in the same location. Thank you so much! I will accept your answer tomorrow after I make the adjustments. I really do appreciate your indepth assistance. In the meantime, I can look at the classifier you've provided.
  3 Comments
Brian Peoples
Brian Peoples on 8 Jul 2020
Thank you so much and I did build a lightbox myself with a difffused light source and camera mount. If you look at the question I had just posted I think you might be able to help. It's here:
I changed the threshold slightly and got it to work for both black and blonde hair which is nice. Later I will probably change the background to be fully blue, but now I'm more concerned with cutting off the blurred section of the hair switch after the initial crop.
Any ideas?
Image Analyst
Image Analyst on 8 Jul 2020
I'd just wrap a piece of paper with text on it over the barrel and see what rows and columns the image gets too blurry for you. Then just analyze the image, or crop it, within those boundaries.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!