While exploring image processing, I recently embarked on a project to implement skin color detection and segmentation using MATLAB. This project is helpful and touches on several important applications like face recognition, gesture analysis, and human-computer interaction. In this post, I will walk you through my experience, the techniques I explored, and how I structured the code. I’ll also share insights into the key decisions I made during the project.
Table of Contents
Why Skin Color Detection?
Skin color detection plays a pivotal role in numerous image processing applications, such as facial recognition and hand gesture recognition. By isolating skin regions in an image, we can perform focused analysis on the regions of interest. My goal was to detect skin regions in an image by segmenting them based on their color properties. By using MATLAB’s powerful image processing toolbox, things get pretty straight forward.
Loading and Preprocessing the Image
The first task was to load the image and resize it for easier handling. I used an image of a hand that I found in a dataset. To ensure that the image was manageable for the MATLAB operations, I resized it to 256×256 pixels. Here is how I did it in MATLAB.
im_orig = imread('Dataset/hand3.jpeg');
img_resized = imresize(im_orig, [256, 256]);
Code language: Matlab (matlab)
Here I used the imread
function to read the image from my Dataset folder. I just picked any random image. Then, resized it with the help of imresized
function. This preprocessing step sets the stage for more complex operations by reducing the computational load while maintaining adequate detail in the image.
Color Space Transformation
Skin color is more easily distinguishable in certain color spaces compared to the traditional RGB space. Therefore, I converted the image to two popular color spaces: YCbCr and HSV.
In the YCbCr color space, I took advantage of the chroma channels (Cb and Cr) to distinguish skin pixels. The hue and saturation components of the HSV color space were also very effective at capturing the subtleties of skin tone.
% Convert to YCbCr
YCBCR = rgb2ycbcr(img_resized);
% Convert to HSV
HSV = rgb2hsv(img_resized);
Code language: Matlab (matlab)
After converting the image to these color spaces, I explored how each component (like Hue in HSV) contributed to identifying skin regions. Here is how I displayed them in MATLAB.
%% Color Space Transformation - HSV
HSV = rgb2hsv(img_resized);
H = HSV(:,:,1); S = HSV(:,:,2); V = HSV(:,:,3);
figure('Name','HSV Color Space Components','NumberTitle','off');
subplot(2,2,1), imshow(H), title('Hue Component');
subplot(2,2,2), imshow(S), title('Saturation Component');
subplot(2,2,3), imshow(V), title('Value Component');
subplot(2,2,4), imshow(img_resized), title('Resized Image');
Code language: Matlab (matlab)
And Here is how it results.
Skin Segmentation in HSV
The HSV color space, in particular, allowed me to create a skin mask using a simple thresholding technique. I defined ranges for the hue and saturation values that are typically associated with skin color. Pixels that fell within this range were classified as skin, while the rest were considered background.
skin_mask_hsv = (HSV(:,:,1) > 0.0 & HSV(:,:,1) < 0.1) & (HSV(:,:,2) > 0.2 & HSV(:,:,2) < 0.6);
Code language: Matlab (matlab)
This binary mask was crucial for further processing, as it separated skin pixels from the non-skin regions. The resulting skin mask was, however, a bit noisy, requiring further refinement through morphological operations.
Morphological Operations and Hole Filling
To improve the quality of the skin mask, I applied morphological operations—specifically, the closing operation, which helps remove small holes and connect disjointed regions of the mask. I then filled in any remaining gaps using MATLAB’s imfill()
function.
skin_mask_hsv = imclose(skin_mask_hsv, strel('disk', 5));
segmented_skin_hsv = imfill(skin_mask_hsv, 'holes');
Code language: Matlab (matlab)
This cleaned-up mask was much more precise, clearly delineating the skin regions from the background. I found this step to be essential for producing smooth, connected skin regions, especially when working with complex images.
After applying the imfill
operation here is how it looks.
Extracting Skin Regions
With a refined skin mask in hand, the next step was to extract the skin regions from the original image. I used the binary mask to segment out the skin-colored areas, creating a final image that highlighted only the skin regions.
segmented_skin_hsv = img_resized .* uint8(repmat(skin_mask_hsv, [1 1 3]));
Code language: Matlab (matlab)
The result was an image where only the hand (the skin region) was visible, and the background was blacked out. This was a rewarding moment in the project, as I could see the tangible result of all the processing steps.
Comparing Results with YCbCr
While the HSV color space yielded satisfactory results, I wanted to see how the YCbCr color space compared. By applying similar thresholding techniques to the chroma components (Cb and Cr), I created another skin mask and segmented the image in the YCbCr color space.
skin_mask_ycbcr = (YCBCR(:,:,2) > 77 & YCBCR(:,:,2) < 127) & (YCBCR(:,:,3) > 133 & YCBCR(:,:,3) < 173);
segmented_skin_ycbcr = img_resized .* uint8(repmat(skin_mask_ycbcr, [1 1 3]));
Code language: Matlab (matlab)
The results were slightly better to those obtained in the HSV color space, but I noticed slight differences in the detection accuracy depending on the lighting conditions and skin tone variations in the image.
Visualizing the Results
Finally, I visualized the segmented skin regions from both the HSV and YCbCr color spaces side by side. This comparison helped me understand the strengths and weaknesses of each color space for skin detection.
figure('Name','Skin Segmentation Comparison','NumberTitle','off');
subplot(1,2,1), imshow(segmented_skin_hsv), title('Skin Segmentation (HSV)');
subplot(1,2,2), imshow(segmented_skin_ycbcr), title('Skin Segmentation (YCbCr)');
Code language: Matlab (matlab)
The HSV color space appeared more robust in varying lighting conditions, while the YCbCr space was slightly more sensitive to skin color variations. However, both methods were effective in accurately segmenting skin regions.
Conclusion:
Working on this skin color detection and segmentation project in MATLAB was a valuable learning experience. It deepened my understanding of how different color spaces can be utilized for image segmentation, and how to refine results using morphological operations. The comparison between HSV and YCbCr gave me practical insights into the performance of each approach under different conditions.