You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
Can any one correct this code to remove hair pixels??
5 views (last 30 days)
Show older comments
Hi!! Can any on help to remove pixels hair from a dermoscopic image with DullRazor method. DullRazor performs the following steps: -It identifies the dark hair locations by a generalized grayscale morphological closing operation, -It verifies the shape of the hair pixels as thin and long structure, and replace the verified pixels by a bilinear interpolation, and -It smooths the replaced hair pixels with an adaptive median filter. I tried this but it's not correct:
image = im2double(imread('image1.bmp'));
figure, imshow(image);
grayscale = rgb2gray(image);
%get hairs using bottomhat filter
se = strel('disk',5);
hairs = imbothat(grayscale,se);
figure, imshow(hairs);
Answers (1)
Image Analyst
on 8 Sep 2012
You need to find the hairs first. Binarize (threshold) and then use regionprops to identify long thin objects. Then use roifill() to replace those objects with the surrounding neighborhood background. I'm not sure what the median filter would gain you - I don't think it's necessary.
15 Comments
Pamela
on 8 Sep 2012
Thanks I tried to correct the code using your advice
image = im2double(imread('image.bmp'));
figure(1), imshow(image);
grayscale = rgb2gray(image);
se = strel('disk',5);
hairs = imbothat(grayscale,se);
figure(2), imshow(hairs);
mask = bwlabel(hairs);
figure(3), imshow(mask);
stats = regionprops(mask, 'MajorAxisLength', 'MinorAxisLength');
major = stats.MajorAxisLength
minor = stats.MinorAxisLength
image2 = roifill(image,mask);
figure(5), imshow(image2);
But i can't understand how can i use the variable major and minor?? i have also an error widh roifill
??? Error using ==> iptcheckinput
Function ROIFILL expected its first input, I, to be two-dimensional.
Image Analyst
on 8 Sep 2012
You need to do it on a grayscale image, or each channel of the color image one at a time.
Pamela
on 8 Sep 2012
Edited: Image Analyst
on 8 Sep 2012
How can i use the variable major and minor because the result is insufficient.
image = im2double(imread('image.bmp'));
figure(1), imshow(image);
grayscale = rgb2gray(image);
se = strel('disk',5);
hairs = imbothat(grayscale,se);
figure(2), imshow(hairs);
mask = bwlabel(hairs);
figure(3), imshow(mask);
stats = regionprops(mask, 'MajorAxisLength', 'MinorAxisLength');
major = stats.MajorAxisLength
minor = stats.MinorAxisLength
image2 = roifill(grayscale,mask);
figure(5), imshow(image2);
Image Analyst
on 8 Sep 2012
You can't, because you don't have separated hairs. They're all overlapping and crossing. You can try the code below. It's not perfect but ti gives you someplace to start.
% Demo to eliminate hairs.
% By ImageAnalyst
clc; % Clear the command window.
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 = 14;
% Read in a standard MATLAB gray scale demo image.
folder = 'C:\Users\Mark\Documents\Temporary';
baseFileName = 'DullRazor.jpg';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
if ~exist(fullFileName, 'file')
% Didn't find it there. Check the search path for it.
fullFileName = baseFileName; % No path this time.
if ~exist(fullFileName, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
rgbImage = imread(fullFileName);
% Get the dimensions of the image. numberOfColorBands should be = 3.
[rows columns numberOfColorBands] = size(rgbImage);
% Display the original color image.
subplot(2, 2, 1);
imshow(rgbImage, []);
% See if we can get rid of the hairs in the RGB image.
% rgbImage = imerode(rgbImage, true(5));
title('Original Color Image', 'FontSize', fontSize);
% Enlarge figure to full screen.
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
% Extract the individual red, green, and blue color channels.
redChannel = rgbImage(:, :, 1);
greenChannel = rgbImage(:, :, 2);
blueChannel = rgbImage(:, :, 3);
% Display the original color image.
subplot(2, 2, 2);
imshow(redChannel, []);
title('Red Channel', 'FontSize', fontSize);
subplot(2, 2, 3);
imshow(greenChannel, []);
title('Green Channel', 'FontSize', fontSize);
subplot(2, 2, 4);
imshow(blueChannel, []);
title('Blue Channel', 'FontSize', fontSize);
figure;
% Let's compute and display the histogram.
[pixelCount grayLevels] = imhist(redChannel);
subplot(2, 2, 1);
bar(pixelCount);
grid on;
title('Histogram of red Channel', 'FontSize', fontSize);
xlim([0 grayLevels(end)]); % Scale x axis manually.
% Threshold the image
binaryImage = redChannel < 120;
binaryImage = imdilate(binaryImage, true(5));
% Display it.
subplot(2, 2, 2);
imshow(binaryImage, []);
title('Binary Image', 'FontSize', fontSize);
% Fill in the mask
redChannel = roifill(redChannel, binaryImage);
greenChannel = roifill(greenChannel, binaryImage);
blueChannel = roifill(blueChannel, binaryImage);
noHairImage = cat(3, redChannel, greenChannel, blueChannel);
% Display it.
subplot(2, 2, 3);
imshow(noHairImage, []);
title('No Hair Image', 'FontSize', fontSize);
Image Analyst
on 8 Sep 2012
Well you can do a median filter and subtract it from your original images to get the hairs, or do a bottom hat filter (a morphological way of doing a similar thing). But you don't have isolated straight short hair segments so the part of DullRazor that assumes that won't work. It just won't. You don't have the kind of image it was meant for. What I would suggest for a work around is to calculate the Euclidean Distance transform with bwdist() and then threshold that to find values less than the radius of the thickest hair, say 2 or 3 pixels. Then use that as a mask. This will avoid using most of the big dark areas as part of the mask, like that big dark pigmented area in your photo - it will use only narrow areas like hairs and only the outer 2 or 3 pixels of the big dark blobs.
hamed abdulaziz
on 17 Sep 2013
Hi Image Analyst,
please Could write your last suggestion for Pamela to remove hair pixels in MATLAB code. thanks in advance
Hamed
Image Analyst
on 26 Sep 2013
medianFiltered = medfilt2(grayImage, [9,9]);
subtraction = double(grayImage) - double(medianFiltered);
hamed abdulaziz
on 26 Sep 2013
Image Analyst, Thank you very much, I wrote this code but I did not get good result please could guide me where I am new in MATLAB
hamed abdulaziz
on 26 Sep 2013
% Dull Razor algorithm
% 1-It identifies the dark hair locations by a generalized grayscale morphological closing operation,
% % 2-It verifies the shape of the hair pixels as thin and long structure, and replace the verified pixels by a bilinear interpolation, and
% % 3-It smooths the replaced hair pixels with an adaptive median filter. I tried this code but it's not correct:
%load image
image = im2double(imread('hair.bmp'));
grayscale = rgb2gray(image);
%get hairs using close operation
se = strel('disk',5);
hairs = imclose(grayscale ,se);
lab_mask = bwlabel(hairs);
stats = regionprops(lab_mask, 'MajorAxisLength', 'MinorAxisLength');
%identifies long, thin objects
Aaxis = [stats.MajorAxisLength];
Iaxis = [stats.MinorAxisLength];
idx = find((Aaxis ./ Iaxis) > 4); % Selects regions that meet logic check
out_mask = ismember(lab_mask, idx);
figure, imshow(out_mask);
replacedImage = roifill(grayscale, hairs);
figure, imshow(replacedImage);
Image Analyst
on 26 Sep 2013
bwlabel works on binary images so you need to do a threshold after the closing.
hairs = hairs < 130; % or whatever. Then do bwlabel.
hamed abdulaziz
on 26 Sep 2013
I inserted your suggestion in the code(is it correct?) but I got complete blurred image %load image image = im2double(imread('hair.bmp')); grayscale = rgb2gray(image); %get hairs using close operation se = strel('disk',5); hairs = imclose(grayscale ,se); hairs = hairs < 130; % or whatever. Then do bwlabel. lab_mask = bwlabel(hairs); stats = regionprops(lab_mask, 'MajorAxisLength', 'MinorAxisLength'); %identifies long, thin objects Aaxis = [stats.MajorAxisLength]; Iaxis = [stats.MinorAxisLength]; idx = find((Aaxis ./ Iaxis) > 4); % Selects regions that meet logic check out_mask = ismember(lab_mask, idx); figure, imshow(out_mask); replacedImage = roifill(grayscale, hairs); figure, imshow(replacedImage)
See Also
Tags
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)