detect HSV color for skin color and extract the color in that region

asked 2017-02-16 00:56:59 -0600

Clementf2b gravatar image

updated 2020-11-05 15:05:47 -0600

The following is the code that I run to find the face region

private Mat mRgbMat;
private Mat mHsvMat;
private Mat mMaskMat;
private int channelCount = 3;
private Mat mDilatedMat;
private List<MatOfPoint> contours = new ArrayList<MatOfPoint>();

private Mat hierarchy;
private int iLineThickness = 5;
private Scalar colorGreen = new Scalar(0, 255, 0);
private static double mMinContourArea = 0.3;
private List<MatOfPoint> mMaxContours = new ArrayList<MatOfPoint>();

private void detectRegion() {

    //get the image from gallery and change it into bitmap
    Bitmap bmpTemp = originalImg.copy(Bitmap.Config.ARGB_8888, true);
    Utils.bitmapToMat(bmpTemp, mRgbMat);
    Imgproc.cvtColor(mRgbMat, mHsvMat, Imgproc.COLOR_RGB2HSV, channelCount);

    Scalar lowerThreshold = new Scalar(0, 0.23 * 255, 50); // Blue color – lower hsv values
    Scalar upperThreshold = new Scalar(50, 0.68 * 255, 255); // Blue color – higher hsv values
    Core.inRange(mHsvMat, lowerThreshold, upperThreshold, mMaskMat);
    Imgproc.dilate(mMaskMat, mDilatedMat, new Mat());

    Imgproc.findContours(mMaskMat, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

    // Find max contour area
    double maxArea = 0;
    Iterator<MatOfPoint> each = contours.iterator();
    while (each.hasNext()) {
        MatOfPoint wrapper = each.next();
        double area = Imgproc.contourArea(wrapper);
        if (area > maxArea)
            maxArea = area;
    }

    // Filter contours by area and resize to fit the original image size
    mMaxContours.clear();
    each = contours.iterator();
    while (each.hasNext()) {
        MatOfPoint contour = each.next();
        if (Imgproc.contourArea(contour) > mMinContourArea*maxArea) {
            mMaxContours.add(contour);
        }
    }

    Imgproc.drawContours(mRgbMat, mMaxContours,0, colorGreen, iLineThickness);
    Log.d(TAG + " contours" ,  contours.size() + "" );

    // convert to bitmap:
    Bitmap bm = Bitmap.createBitmap(mRgbMat.cols(), mRgbMat.rows(), Bitmap.Config.ARGB_8888);
    Utils.matToBitmap(mRgbMat, bm);

    // find the imageview and draw it!
    imageView.setImageBitmap(bm);
}

Result of the above code:

please add https:// because I cannot post link. Thank you s11.postimg.org/myaf9fb4z/photo_2017_02_16_14_43_34.jpg

Although I can get a good result using the above function, I may not get the result that I want if there are some extra elements that contains a close value of the color like the following image.

please add https:// because I cannot post link. Thank you s27.postimg.org/gy04nnwzn/photo_2017_02_16_14_49_57.jpg

How do I change my code to fit this situation? Also I need to change the HSV value in this region. How can I get the HSV value in that region? Please give me some helps. Thank you very much.

edit retag flag offensive close merge delete

Comments

How do I change my code to fit this situation? You do not, there are limits to HSV based color segmentation for skin color, and your are running into them. You can set your ranges for HSV stronger, but that will fail in some cases also.

StevenPuttemans gravatar imageStevenPuttemans ( 2017-02-16 07:52:18 -0600 )edit

@StevenPuttemans Thank you for your reply. You mean that I should set the range closer? Yes. If people contain brown hair, it would affect my result. Do you know how to extract the HSV color from that region?

Clementf2b gravatar imageClementf2b ( 2017-02-16 08:08:49 -0600 )edit

@Clementf2b Did you manage to make this work the way you wanted?

PedroSilva gravatar imagePedroSilva ( 2017-08-08 04:48:14 -0600 )edit