Skin Detection: A Step-by-Step Example using Python and OpenCV

So last night I went out for a few drinks with my colleague, James, a fellow computer vision researcher who I have known for years.

You see, James likes to party. He’s a “go hard” type of guy. He wanted to hit every single bar on Washington St. (there’s a lot of them)…and then hit ’em again on the way back.

It’s safe to say that by the end of the night that James was blotto. Wasted. Lights out.

Anyway, it was getting late. 1:47am, to be exact. I’m tired. I just want to go to bed. We’re at the last bar. I’m signing my name on the tab and heading for the door, looking forward to getting some sleep.

And James, in his clearly drunken and intoxicated state, walks (or rather, stumbles like a newborn foal) up to this blonde who looks and dresses like she’s straight out of South Beach and says: “You know…if you take your shirt off I have a Python script that can detect how much skin you’re showing. Wanna see?”

Now tell me, what do you think happens next?

That’s right. James gets a top shelf Manhattan thrown in his face by the South Beach girl. Honestly, he’s just lucky that he didn’t catch a well deserved fist to the nose.

Shocked, and fairly appalled, I led the drunken James back to my apartment to sleep it off. Not to mention have a conversation with him regarding how to treat women the next morning.

So here’s the deal…

In this blog post I’m going to show you how to detect skin in images using computer vision.

But use these superpowers for good, okay? Don’t be like James. Play it cool.

Read on and find out how simple it really is to detect skin in images using Python and OpenCV.

Looking for the source code to this post?
Jump right to the downloads section.

OpenCV and Python versions:
This example will run on Python 2.7/Python 3.4+ and OpenCV 2.4.X/OpenCV 3.0+.

Detecting Skin in Images & Video Using Python and OpenCV

You know the drill. Open up your favorite editor, create a new file, name it , and let’s get to work:

On Lines 2-5 we import the packages that we’ll need. We’ll use NumPy for some numerical processing, argparse  to parse our command line arguments, and cv2  for our OpenCV bindings.

We’ll also use a package called imutils  which contains a bunch of “convenience” image processing functions for resizing, rotating, etc. You can read more about the imutils  package in my Basics of Image Manipulations post.

From there, Lines 8-11 parse our command line arguments. We have only a single (optional) switch, --video , which allows you to detect skin in a pre-supplied video. However, you could just as easily omit this switch from the command and use your webcam to detect skin in images. If you don’t have a webcam attached to your system, then you’ll have to supply a video.

From there, we define the lower and upper boundaries for pixel intensities to be considered skin on Lines 15 and 16. It’s important to note that these boundaries are for the HSV color space, NOT the RGB color space.

If you haven’t had a chance to take a look at my post on Color Detection Using Python and OpenCV, then now would be a good time to do so — we’ll be building off the fundamentals presented in the color detection post and extending our method to detect skin in images.

Alright, now let’s write some code to grab a reference to the webcam or video:

On Line 20 we make a check to see if the --video  switch was supplied. If it was not, then we grab reference to the webcam by passing a value of 0  to the cv2.VideoCapture  function.

However, if the --video  switch was supplied, then we’ll pass the path to the video to cv2.VideoCapture  on Lines 24 and 25.

Let’s start reading frames from our video:

We start looping over the frames in the video on Line 28 and grab the next frame on Line 30 using the  method.

The  function returns a tuple, consisting of grabbed  and frame . The grabbed  variable is simply a boolean flag, indicating if the frame was successfully read or not. The frame  is the frame itself.

From there, we make a check on Line 34 to see if the frame  was not read. If it was not, and we are reading a video from file, we assume we have reached the end of the video and we can safely break from the loop. Otherwise, we keep on looping.

In order to speed up the skin detection process, we use our imutils.resize  convenience function to resize our frame to have a width of 400 pixels on Line 40.

The actual skin detection takes place on Line 41 and 42. First, we convert the image from the RGB color space to the HSV color space. Then, we apply the cv2.inRange  function, supplying our HSV frame, and our lower and upper boundaries as arguments, respectively.

The output of the cv2.inRange  function is our mask This mask is a single channel image, has the same width and height as the frame, and is of the 8-bit unsigned integer data type.

Pixels that are white (255) in the mask represent areas of the frame that are skin. Pixels that are black (0) in the mask represent areas that are not skin.

However, we may detect many small false-positive skin regions in the image. To remove these small regions, take a look at Lines 46-48. First, we create an elliptical structuring kernel. Then, we use this kernel to perform two iterations of erosions and dilations, respectively. These erosions and dilations will help remove the small false-positive skin regions in the image.

From there, we smooth the mask slightly using a Gaussian blur on Line 52. This smoothing step, while not critical to the skin detection process, produces a much cleaner mask.

We then apply the skin mask to our frame on Line 53.

Line 56 shows us a side-by-side view of the original frame along with the frame with skin detected in it.

We wait for a keypress on Line 59, and if it’s the q  key, then we break from the loop.

Finally, Lines 63 and 64 release the reference to our webcam/video and close any open windows.

Running our Skin Detector

To run our skin detector, open up a terminal and navigate to where our source code is stored.

If you are using the example video provided with the code downloads for this post (or an example video of your own), then issue the following command:

Otherwise, if you want to use your own webcam, execute this command:

If all goes well, you should see my detected skin, as shown by the following figure:

Figure 1: Detecting the skin of my face using Python and OpenCV.

Figure 1: Detecting the skin of my face using Python and OpenCV.

And here is another example image from the video supplied with the code download:

Figure 2: Detecting both the skin of my and and the skin of my face using Python and OpenCV.

Figure 2: Detecting both the skin of my and and the skin of my face using Python and OpenCV.

Pretty cool, right?

Using this basic approach we were able to build a fairly rudimentary skin detection algorithm — that’s still able to obtain decent results!


There are some pretty obvious limitations and drawbacks to this approach.

The main drawback is that we are framing skin detection as a “color detection” problem. This assumes that we can easily specify the HSV values for ranges of pixel intensities that are considered skin.

However, under different lighting conditions, this approach might not perform as well — and we would likely have to continue to tweak the HSV value ranges.

The HSV value ranges we supplied worked fairly well for this example post…but what about for other ethnicities?

For example, I’m a white male. And surely the same HSV values used to detect my skin could not be used to detect someone from Asia or Africa. This implies that we have some a priori knowledge regarding the skin tone of who we want to detect.

Of course, more robust approaches can be applied. A (highly simplified) example would be to perform face detection to an image, determine the color of the skin on their face, and then use that model to detect the rest of the skin on their body.

Not a bad approach, but as you can imagine, it’s definitely a little more complicated.

In the meantime, as long as you can specify the HSV values of the skin tone you want to detect, framing skin detection as a color detection problem should work quite well for you.


In this blog post I showed you how to detect skin in images using Python and OpenCV.

To accomplish our skin detection, we framed skin detection as an extension to color detection.

We were able to supply upper and lower ranges of pixel intensities in the HSV color space to detect skin in images.

While this is not a perfect or robust approach, the simplicity of our skin detection algorithm makes it a very good starting point to build more robust solutions.

But remember our promise, okay?

Don’t be like James. Use our skin detection superpowers for good, not evil.


If you would like to download the code and images used in this post, please enter your email address in the form below. Not only will you get a .zip of the code, I’ll also send you a FREE 17-page Resource Guide on Computer Vision, OpenCV, and Deep Learning. Inside you'll find my hand-picked tutorials, books, courses, and libraries to help you master CV and DL! Sound good? If so, enter your email address and I’ll send you the code immediately!

, , , ,

95 Responses to Skin Detection: A Step-by-Step Example using Python and OpenCV

  1. Wajih Ullah Baig August 29, 2014 at 7:16 am #

    Bought your book yesterday.
    It is one wonderful effort. Top of my list of OpenCV books!

    • Adrian Rosebrock August 30, 2014 at 6:57 am #

      Awesome! I’m happy that you are enjoying it!

  2. Orion Gump September 4, 2014 at 2:47 am #

    Hi, I tried to compile the file but it was reported that

    Traceback (most recent call last):
    File “”, line 2, in
    from pyimagesearch import imutils
    ImportError: No module named pyimagesearch

    May I know where I can download the pyimagesearch lib?

    • Adrian Rosebrock September 4, 2014 at 7:56 am #

      Hi Orion, did you download the source code from the bottom of the page? Be sure to click the “Download the Code!” button at the bottom of this page and the ‘pyimagesearch’ module will be in the .zip file. Alternatively, shoot me an email and I’ll be happy to pass it along to you.

      • gol July 14, 2015 at 9:48 pm #

        I downloaded .zip file. but i cant import pyimagesearch.facedetector. I am using windows 8. python27. thanx

        • Adrian Rosebrock July 15, 2015 at 6:43 am #

          Hey Gol, I’m not sure I understand your question — there is no facedetector module inside the skin detection .zip. If you are using code from the Case Studies book, then you’ll need to copy the facedetector into the pyimagesearch directory of the skin detection example.

  3. Suraj December 31, 2014 at 10:15 am #

    As you told here that this works only for certain skin tones ,Are we supposed to write various test cases for different skin tones are is there any package available for it ??

    • Adrian Rosebrock December 31, 2014 at 11:27 am #

      Hi Suraj, yes, that is correct. You will have to write your own test cases. Definitely consider using the HSV or L*a*b* color space for this.

  4. SaadEddin January 19, 2015 at 12:03 pm #

    I did a couple of your tutorials the last few days… So I Bought your book today, I am looking forward to starting my journey.

    I do have some experience with OpenCV, numpy, scipy, scikit image and scikit learn. I used them in a couple of projects and homeworks so I learned using some tutorials from here and there, so the learning process wasn’t structures.

    So I decided to start with your book as I prefer a structured learning process. Especially at the beginning, as it will consolidate the skills much better I hope.


    • Adrian Rosebrock January 19, 2015 at 2:06 pm #

      Hi Saad. Awesome, thanks for picking up a copy of Practical Python and OpenCV! I’m sure you’ll learn a ton from the book!

  5. Boris Tsipenyuk March 10, 2015 at 1:44 pm #

    this was a great proof of concept, what I found hilarious in my limited testing is that generally it detected skin (and hair) at least for blondes 🙂 so the bald sample set may be flawed a bit 🙂

  6. Joe Landau June 8, 2015 at 6:38 pm #

    Using a Raspberry Pi with the Pi’s camera, line 21 does not work for me. It is said on the net that you need to install a V4L2 driver. (

    Also, the comment on lines 18 and 19 mystifies me.

    • Adrian Rosebrock June 8, 2015 at 7:21 pm #

      Anytime you see a call to cv2.VideoCapture and you want to use the code with the Raspberry Pi, you’ll need to convert it to use the picamera module, like in this post or use the V4L2 driver. I really recommend converting the code. It’s much easier than getting the driver working.

      As for the comment, that’s simply a typo. If a video is not supplied, then we will grab the webcam reference.

  7. Patrick Nowicki July 19, 2015 at 1:36 pm #

    I managed to get the Raspberry Pi camera working on my Pi 2 for this example, but the frame rate is only about 5 frames/sec on my output and the video is delayed about 1-2 seconds. Is this expected because of the processing power of the Pi? Just curious if there is anyway to make it smoother/faster.

    • Adrian Rosebrock July 19, 2015 at 1:52 pm #

      Very nice, congrats on getting your Pi 2 working for this email! 5 FPS sounds a tad low for this example though, even given the limited processing power of the Pi. I would suggest trying to resize the image even further, perhaps having a maximum width of 200-300 pixels.

      • Patrick Nowicki July 19, 2015 at 1:56 pm #

        Thanks for the super quick reply! A resize to 200 did make a huge difference. Thanks for the tip!

        • Christian Abbott March 30, 2016 at 12:10 pm #

          For anybody else running this on a Pi: Erosion and Dilation are, by far, the two biggest bottlenecks for your execution speed here. As an alternative, try performing Opening instead:

          skinMask = cv2.morphologyEx(skinMask, cv2.MORPH_OPEN, kernel) as opposed to your two calls to Dilate() and Erode().

          • Adrian Rosebrock March 30, 2016 at 12:41 pm #

            Hey Christian — do you have any timings to confirm this?

          • Christian Abbott March 30, 2016 at 4:39 pm #


            Here’s the output for 30 frames of execution, Erode & Dilate vs. Opening:

            With erode & dilate:
            With opening:

            Pardon the awful cProfile formatting. Individual trial info is at the bottom.

          • Adrian Rosebrock March 30, 2016 at 5:12 pm #

            Awesome, thanks for sharing! I’ll also keep this in mind for future posts as well.

  8. cm November 29, 2015 at 2:09 am #

    Hi Adrian,

    I have “import error” problem on pi for importing “pyimagesearch”.
    Here is the message:
    ImportError: No module named 'pyimagesearch'

    I know that my system lacks of this package, however I don’t know how to
    install it on the pi system.
    Could you teach me how to do this?


    – CM

    • Adrian Rosebrock November 29, 2015 at 7:06 am #

      The pyimagesearch package is included in the source code download of this post. Just download the .zip file, unzip it, and run the Python script. There is nothing to install.

      • Sharon December 24, 2018 at 4:48 am #

        Hi Adrian,
        are there plans to make pyimagesearch a python package as you did imutils?

        • Adrian Rosebrock December 27, 2018 at 10:41 am #

          No, the reason being is that what the “pyimagesearch” module contains is 100% dependent on the blog post itself. I use the “pyimagesearch” module to reach readers how to properly organize their Python packages. Each post could have a different “pyimagesearch” package.

  9. thom December 5, 2015 at 4:15 am #

    Hi when i use skin detection from your video ewerything works.
    But when i try from my camera (cv)pi@raspberrypi:~ $ python
    i got this eror

    I downloaded from botom code.

    • Adrian Rosebrock December 5, 2015 at 6:20 am #

      Based on your terminal, I assume you are using the Raspberry Pi. Are you using a USB webcam or the Pi camera module? I’m assuming the Pi camera module. In that case, you’ll need to update the code to access the Raspberry Pi camera rather than use the cv2.VideoCapture function.

  10. Gabriel February 16, 2016 at 6:58 am #

    Hello, great tutorials! Quick question about the color: In the code you include the line:

    # define the upper and lower boundaries of the HSV pixel
    # intensities to be considered ‘skin’
    upper = np.array([20, 255, 255], dtype = “uint8”)

    If the values [20, 255, 255] are HSV, this is the same than [20, 100, 100], right? (in HSV you can’t go beyond 100%).

    • Adrian Rosebrock February 16, 2016 at 3:37 pm #

      Under the pure definition of the HSV color space, yes, that’s correct. However, OpenCV’s cv2.cvtColor function allows the Hue to be in the range [0, 180] and both the saturation to be in the range [0, 255].

  11. Niki February 19, 2016 at 3:07 am #

    Hi Adrian,

    Thank you for this wonderful blog. I only started looking at the a few posts, but so far I’ve learned a lot more than the last 2 weeks that I was randomly looking at different sources.

    I have a question regarding this post. I have a video of hand washing and I want to detect the act of hand washing. One step is to detect the hands. Unfortunately, when I try your code on my videos, it cannot detect the hands at all. Instead in some of the videos, parts of the wall, that have a light pink color, are detected, and in some other videos nothing is detected at all.

    My question is does this code work well when there is fast movement of hands like in the case of hand washing?

    Another thing that I should mention is that the sink area has also a light color; can this cause a problem as well?

    Do you think this algorithm still works for me by performing some changes or I should try something else?

    Your help is greatly appreciated!

    • Adrian Rosebrock February 19, 2016 at 1:51 pm #

      This method of skin detection relies on color thresholding, which can work well in some situations — and fail in others. It mainly depends on lighting conditions and the color of your own skin. You might need to tweak the values to cv2.inRange to obtain a better segmentation of the skin.

      That said, I don’t think this method is best for your particular application. Presuming your camera is fixed and non-moving, you can likely use simple motion detection to detect the hands as they go under the water stream.

  12. Tim Clemans February 29, 2016 at 12:30 am #

    I’m struggling to learn how to specify lower and upper boundaries. How can I generate the lower and upper boundaries? Is there a free computer program that will generate a rang for me?

    • Adrian Rosebrock February 29, 2016 at 3:28 pm #

      Please see this blog post where I mention the range-detector script that can be used to help define the upper and lower boundaries in a given color space.

  13. Oscar March 2, 2016 at 8:23 am #

    Hi Adrian,
    first of all, thanks for the tutorial.
    I am using the Raspberry Pi and the Pi camera module. in other reply, you said it´s necessary to update the code to access the Raspberry Pi camera rather than use the cv2.VideoCapture function, but what code I have to add or change in

    Thanks in advance.

    • Adrian Rosebrock March 3, 2016 at 7:11 am #

      You’ll need to change the camera initialization and a function call that actually reads a frame from the video stream. I suggest using the VideoStream class which can access both a builtin/USB webcam and the Raspberry Pi camera module with minimal changes.

  14. Vinith March 29, 2016 at 10:21 am #


    I keep getting the error numpy module not found and cv2 module too. I downloaded both files online but problem still persists.

    • Adrian Rosebrock March 29, 2016 at 3:39 pm #

      Have you installed OpenCV? Did you install using a tutorial on PyImageSearch? If so, you’re probably forgetting to use the workon cv command prior to executing your Python script.

  15. Alf April 28, 2016 at 4:08 am #

    Dear Mr. Rosebrock,
    Such a Great Job!
    But is it possible to achieve similar result by usage of Bayesian pixel-based skin segmentation?
    How could I do this?


    • Adrian Rosebrock April 28, 2016 at 2:26 pm #

      There are many different ways to perform segmentation, and yes, Bayesian methods can be applied for this. However, I do not have any tutorials on this particular method — I can’t promise I’ll cover it in the future, but I can certainly look into it.

      • Alf April 28, 2016 at 11:56 pm #

        Thank you for quick response!

  16. Deger July 25, 2016 at 6:43 am #

    Hello Adrian,
    Thanks for the tutorial. I have 2 questions for you.
    1- Are you using Hubspot? Because you have amazing and excellent marketing jobs.
    2- I have sent you an e-mail about buying your book but maybe for a specific tutorial (object recognition and feature detection)

    I am looking forward to hear from you.
    Thank you.

    • Adrian Rosebrock July 27, 2016 at 2:33 pm #

      Hey Deger — I’m actually not using HubSpot. Do you think I should be? I’ve also responded to your email, be sure to give my response a look.

  17. DantePy August 22, 2016 at 8:20 am #

    Hi Adrian,
    I’m pretty new in cv, anyway I’m very excited of such field, thanks a lot for your wonderful blog.
    I have a question about the code showed above, I know that dilate is the complementary operation of erode, so what is the meaning of those two lines of code? Why they don’t elude each other?

    • Adrian Rosebrock August 22, 2016 at 1:26 pm #

      Performing an erosion will remove small speckles of noise from your binary map. But then you apply a dilation to grow back the regions of actual objects you’re interested in. In essence, an erosion followed by a dilation will remove noise from your images.

  18. muhammad iqbal October 1, 2016 at 7:23 am #

    Is there any other way to detect other than color problem.

    • Adrian Rosebrock October 2, 2016 at 9:03 am #

      Certainly, there are many methods that can be used to detect hands in images. Some methods rely on machine learning and treat the problem as an object detection task (like Haar cascades, HOG + Linear SVM detectors, or CNN localizers). Other methods use hardware to facilitate hand detection such as stereo vision and 3D cameras — it really just depends on the actual problem and the setup.

  19. Shilpa November 29, 2016 at 1:14 am #

    Hi Adrian,

    Can You please let me know how can one find the nails from human finger.Any help wold be appreciated.

    • Adrian Rosebrock November 29, 2016 at 7:57 am #

      I don’t have any experience with fingernail detection but I wouldn’t rely on color thresholding due to varying skin tones. Have you considered training a custom object detector? With a fixed camera this should be fairly straightforward.

  20. Parth Shah November 30, 2016 at 11:36 pm #

    Hi Adrian,

    I was wondering is this face detection possible with help of neural-networks do you any books ot tutorials for that like your Practical Python and OpenCV ?
    If there are any would really appreciate if you could mail me some links or blogs for some reference..

    Thank you!

    • Adrian Rosebrock December 1, 2016 at 7:26 am #

      You can certainly build a face detector using neural networks; however, most current methods that you see in OpenCV or other computer vision libraries rely on either Haar cascades (covered in Practical Python and OpenCV) or HOG + Linear SVM detectors (covered in the PyImageSearch Gurus course).

      I’ll be announcing a new book soon which will cover neural networks and deep learning so be sure to be on the lookout for it!

      • Parth Shah December 1, 2016 at 10:20 am #

        Thank you for replying on short notice!
        But is there any other reference you have anything that can get me a jump-start for Neural Networks, with a level of your explanation xD ?
        Also, I tried using your range-detector script mentioned in this blog, I was using webcam, 2 windows pop for output one is original and other is thres..
        But thres is always blank can you tell me exactly how to use it..
        I am kinda new to all this but suprisingly ComputerVision is quite interesting!
        Thank you

        • Adrian Rosebrock December 5, 2016 at 1:50 pm #

          The PyImageSearch Gurus course covers NNs, CNNs, and Deep Learning with my level of explanation. I’m also currently writing a book on deep learning + image classification.

  21. myheadhurts February 24, 2017 at 4:09 pm #

    Hi Adrian- when I downloaded, it landed in downloads. I unzipped it there, but I’m pretty sure I needed to extract it to some other spot, because the program can’t find the ‘pyimagesearch’ module. Could not locate this problem in the other replies, so I’m bugging you for some direction. Where do I extract to?


    • Adrian Rosebrock February 27, 2017 at 11:21 am #

      Change directory into the skindetection directory and then execute the Python script from there. You need to be in the same directory as the pyimagesearch module for it to import.

  22. vivek May 28, 2017 at 2:26 pm #

    hello sir
    how do you define the range for lower and upper boundaries for pixel intensities to be considered skin on?

    • Adrian Rosebrock May 31, 2017 at 1:29 pm #

      You can do it one of two ways:

      1. Read various publications on skin detection and see which ranges/methods the authors recommend.
      2. Use scripts such as range-detector to manually determine the color thresholds.

  23. alice November 7, 2017 at 5:25 am #

    Hey Adiran,
    wonderful work thank very much fo ur blogs wihch help me a lot to understand how to use opencv and python
    but I just have a question about this line of the programm
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11, 11))
    why did u use 11 ? and for the iteration (the line after ) why did u use 2
    ps : ( i m new on CV and PYTHON )

    • Adrian Rosebrock November 9, 2017 at 7:02 am #

      The line you are referring to defines a circular kernel of size 11×11 pixels. This kernel is used to erode (remove) connected foreground pixels (to disconnect connected components) and then dilate (re-grow) the regions. If you’re new to OpenCV and image processing I would highly encourage you to read through Practical Python and OpenCV and/or the PyImageSearch Gurus course where I discuss these algorithms and techniques in more detail.

      • alicia December 5, 2017 at 6:33 am #

        Hello ! need help really sorry im trying to record a video on raspberry and it s just giving the first image of the video durinf 20 secondes Can u help me ?

        • Adrian Rosebrock December 5, 2017 at 7:23 am #

          It’s hard to say what the specific problem is here, but I would suggest making sure you can read the frames from your camera sensor before writing them to disk. You might also have a stray cv2.waitKey call in your code. Again, it’s hard to diagnose without more detail.

          • alice December 12, 2017 at 3:45 pm #

            Thank you it s okay , please Ineed to get the value of the green and red canal of the skin (PIXEL )d by image did u do it or know how to start to ?

  24. Syed Abdullah Hashmi November 13, 2017 at 10:23 am #

    Its working amazingly thank you sir..

  25. Manh Nguyen December 3, 2017 at 9:06 am #

    HI Adrian,
    Great post! This post is help me a lot. I have a question, hope you can reply me. Why do you change from RGB to HSV, I think you have some reasons for this work. Thank you!

    • Adrian Rosebrock December 5, 2017 at 7:46 am #

      I convert to HSV from RGB because HSV is more similar to how humans perceive color. It’s also easier to define more robust color ranges in HSV than RGB. If you’re interested in learning more about color spaces and how to use them, take a look at the PyImageSearch Gurus course.

  26. Raj December 16, 2017 at 10:46 pm #

    HI Adrian,

    I am Raj,

    “import error” problem on pi for importing “pyimagesearch”.
    Here is the message:
    ImportError: No module named ‘pyimagesearch’

    • Adrian Rosebrock December 19, 2017 at 4:30 pm #

      Please make sure you use the “Downloads” section of this blog post to download the source code. Inside you will find the “pyimagesearch” module.

  27. lissou December 18, 2017 at 5:05 pm #

    Working well ! oh thanks very much great job
    Instead Please I need to get the value of the green and red chanel of the skin by the video but don’t have any ideo to do it well ?
    I ve understand that you made a conversion gro RGB to HSB why ? and to get the pixel I have to do the opposite to get the red and green channel of the skin ?

    • Adrian Rosebrock December 26, 2017 at 4:08 pm #

      Refining color ranges tends to be easier and more intuitive in the HSV color space rather than RGB. For defining your own color ranges, take a look at the range-detector script in the imutils library.

  28. licia January 27, 2018 at 7:12 am #

    Great job ! it s workiing well but when I put the path to work on my video file it doesn’t work need HELP please

    • Adrian Rosebrock January 30, 2018 at 10:36 am #

      Hey licia — it sounds like either (1) your path to your input video is invalid, (2) you don’t have the proper video codec installed on your system, or (3) you compiled OpenCV without video support. Double-check your input video path as that is normally the error. Otherwise you should try following one of my OpenCV install tutorials which will compile + install OpenCV with video support.

      • licia February 1, 2018 at 10:33 am #

        Hello yes I think I was typing a wrong path it’s working well sorry how can I get the video when the skin is detected to split the video and do image processing how to get the video not the original the other ? thanks thanks

        • Adrian Rosebrock February 3, 2018 at 10:51 am #

          Hm, I’m not sure what you mean. Could you try to explain that again?

          • licia February 4, 2018 at 5:52 am #

            Okay, the program is working well and the two videos are generated , I want now to save the video (when the skin is detected) in a file for exemple skin.avi and I can t I tried with

            out = write (skin)
            but no success

          • Adrian Rosebrock February 6, 2018 at 10:15 am #

            Take a look at this post on saving key clips to file.

  29. Hossein March 24, 2018 at 8:29 am #

    How can I combine this code with face detection (object detection)
    For example just execute this code on my face , not my hands

    • Adrian Rosebrock March 27, 2018 at 6:31 am #

      You would:

      1. Detect the face in the image (see this post to get you started)
      2. Extract the face ROI bounding box
      3. Apply skin detection to the face ROI

  30. Rohit May 26, 2018 at 2:56 am #

    how to pass the path of a video in this code?

    • Adrian Rosebrock May 28, 2018 at 9:51 am #

      You can do so via command line arguments. If you are new to command line arguments be sure to read this blog post.

  31. Saikiran Siriki July 17, 2018 at 2:08 pm #

    Hi, thanks for the awesome tutorial. I’m working on a project where I’m generating facemask from your dlib 68 landmarks tutorial. However I would like to change the skintone of the obtained image(just the face within the 68 landmarks), how would I go about approaching the problem.

  32. Ankit agrawal August 13, 2018 at 11:15 am #


    I am going through your tutorials in OpenCV ’Skin Detection’.I am a beginner.
    I am getting this error again and again:

    Traceback (most recent call last):

    (h, w) = image.shape[:2]
    AttributeError: ‘NoneType’ object has no attribute ‘shape’

    Can you please guide me to solve this.

  33. Ashish August 18, 2018 at 12:00 am #


    cv2.videocapture().read() returning a false value.
    I have used a .mp4 video.

    Is there any other way to read video files.


    • Adrian Rosebrock August 22, 2018 at 10:15 am #

      It sounds like your machine does not have the proper video codecs installed. Make sure you follow one of my OpenCV tutorials and from there you should be able to open the MP4 file.

  34. Akhil August 20, 2018 at 10:57 am #

    Sir, you are doing a great job. You are helping the generation. this quality is very rare and many don’t do it for free as you are doing.

    • Adrian Rosebrock August 22, 2018 at 9:52 am #

      Thank you Akhil, that is very kind 🙂 I really appreciate that.

  35. benji kohen September 1, 2018 at 11:42 am #

    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11, 11))
    why did u use 11?

    • Adrian Rosebrock September 5, 2018 at 9:08 am #

      The kernel is used to perform a series of erosions and dilations, removing small regions of noise.

  36. vijay singh September 6, 2018 at 2:07 am #

    Great post Adrian. It would be helpful for me in security intrusion detection. I will try to use it for my object.

    perform face detection to an image, determine the color of the skin on their face, and then use that model to detect the rest of the skin on their body.

    As it is based on color. I am afraid it can have false detection if the background of the image is same.

  37. Kumar Ujjawal September 11, 2018 at 12:16 am #

    Hi, I’m getting a blank image instead of skin.

    • Adrian Rosebrock September 11, 2018 at 8:04 am #

      Blank as in a “black” output image? If so, that means you need to tune your threshold parameters.

  38. Bishoy Youhana October 9, 2018 at 3:53 pm #

    how do I go about implementing this for individual photos?

    • Adrian Rosebrock October 12, 2018 at 9:26 am #

      You can use the “cv2.imread” function to load an input image. From there you can apply the same thresholding techniques to the image.

  39. Bhagya Amarasinghe November 10, 2019 at 1:12 am #

    Hi, is there a way to cut the first half of the generated mask? I want to obtain the neck separately.

    • Adrian Rosebrock November 14, 2019 at 9:31 am #

      You can use NumPy array slicing to extract arbitrary regions of the image/frame.


  1. How to Build a Kick-Ass Mobile Document Scanner in Just 5 Minutes - PyImageSearch - September 1, 2014

    […] Remember my friend James from my post on skin detection? […]

Before you leave a comment...

Hey, Adrian here, author of the PyImageSearch blog. I'd love to hear from you, but before you submit a comment, please follow these guidelines:

  1. If you have a question, read the comments first. You should also search this page (i.e., ctrl + f) for keywords related to your question. It's likely that I have already addressed your question in the comments.
  2. If you are copying and pasting code/terminal output, please don't. Reviewing another programmers’ code is a very time consuming and tedious task, and due to the volume of emails and contact requests I receive, I simply cannot do it.
  3. Be respectful of the space. I put a lot of my own personal time into creating these free weekly tutorials. On average, each tutorial takes me 15-20 hours to put together. I love offering these guides to you and I take pride in the content I create. Therefore, I will not approve comments that include large code blocks/terminal output as it destroys the formatting of the page. Kindly be respectful of this space.
  4. Be patient. I receive 200+ comments and emails per day. Due to spam, and my desire to personally answer as many questions as I can, I hand moderate all new comments (typically once per week). I try to answer as many questions as I can, but I'm only one person. Please don't be offended if I cannot get to your question
  5. Do you need priority support? Consider purchasing one of my books and courses. I place customer questions and emails in a separate, special priority queue and answer them first. If you are a customer of mine you will receive a guaranteed response from me. If there's any time left over, I focus on the community at large and attempt to answer as many of those questions as I possibly can.

Thank you for keeping these guidelines in mind before submitting your comment.

Leave a Reply