MATLAB Answers

Binarization to Crop Image

35 views (last 30 days)
Brian Peoples
Brian Peoples on 6 Jul 2020 at 14:11
Commented: Image Analyst on 8 Jul 2020 at 14:27
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
h = msgbox('select region of interest');
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
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!


Sign in to comment.

Accepted Answer

Image Analyst
Image Analyst on 6 Jul 2020 at 23:17
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.)
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);
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');
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');
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');
% 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;


Brian Peoples
Brian Peoples on 7 Jul 2020 at 15:32
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 at 16:19
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 at 18:24
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.


Image Analyst
Image Analyst on 7 Jul 2020 at 20:30
A little time in optimizing and standardizing your image capture conditions will make the image analysis algorithm tremendously easier. For example there are lots of cheap light boxes on for image capture, like the
They range from $40 to a few hundred dollars. They are for the casual, non-scientific, non-professional user, despite what they say. And as a professional, I ought to know. I call these "Ebay quality" or "Etsy quality" since that is really the market they sell to - the casual user who likes to take pictures of things to sell them online.
Of course you can get much better if you want to have your machine shop build something for you from aluminum rails, high quality camera mounts such as these RAM Mounts, lamps from AdvancedIllumination or SmartVisionLights, professional machine vision industrial or scientific cameras, and other professional components.
Good luck.
Brian Peoples
Brian Peoples on 8 Jul 2020 at 14:19
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 at 14:27
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.

Translated by