检测皮肤并捕获图像

时间:2017-11-28 11:32:33

标签: android c opencv image-processing java-native-interface

更新1

我知道inRange函数的作用。但是我不想应用蒙版并用肤色显示新图像。我想要做的是知道图像是否包含肤色并覆盖更大的区域。

我想做什么

我想在边界内检测到手指时拍摄照片。它的尺寸是已知的。

苦苦挣扎

  1. 以本机代码处理图像数据。
  2. 在实时相机中检测皮肤,因此无论何时聚焦该特定区域并检测到皮肤,都应该拍摄。
  3. 我做了什么

    我正在使用JNI Layer来执行操作。我可以使用this tutorial从图像数据中获取Mat,但不知道如何操纵poutPixels。格式为NV21,我不知道如何对其进行操作。

    我需要裁剪图像,然后检测图像中是否存在皮肤。我已经成功地将图像裁剪到所需的尺寸,但没有任何线索可以向前移动以检测皮肤。我希望此方法返回truefalse

    以下是代码:

    jbyte * pNV21FrameData = env->GetByteArrayElements(NV21FrameData, 0);
    jint * poutPixels = env->GetIntArrayElements(outPixels, 0);
    
    Mat mNV(height, width, CV_8UC3, (unsigned char*)pNV21FrameData);
    Mat finalImage(height, width, CV_8UC3, (unsigned char*) poutPixels);
    
    jfloat wScale = (float) width/screenWidth;
    jfloat hScale = (float) height/screenHeight;
    
    float temp = rectX * wScale;
    int x = (int) temp;
    temp = rectY * hScale;
    int y = (int) temp;
    
    int cW = (int) (width * wScale);
    int cH =  (int) (height * hScale);
    
    cH = cH/2;
    
    
    Rect regionToCrop(x, y, cW, cH);
    mNV = mNV(regionToCrop);
    finalImage = finalImage(regionToCrop);
    
    //detect skin and return true or false
    

    我已阅读有关inRange功能的内容,但我不知道如何检查是否有皮肤。

    问题

    1. 我是在正确的道路上继续前进吗?
    2. 我得到的图片格式为NV21。它是8UC1还是8UC3
    3. 如何从这里开始检测皮肤?
    4. 感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

我通过提取肤色范围并使所有像素等于zero来解决我的问题。以下是步骤。

  1. 将图像转换为HSV
  2. 首先将图片转换为HSV

    Mat mHsv = new Mat(rows, cols, CvType.CV_8UC3);
    Imgproc.cvtColor(mRgba, mHsv, Imgproc.COLOR_RGB2HSV);
    
    1. 获取肤色范围
    2. 肤色范围可能会有所不同,但这个适合我。

      Mat output = new Mat();
      Core.inRange(mHsv, new Scalar(0, 0.18*255, 0), new Scalar(25, 0.68*255, 255), output);
      
      1. 提取此皮肤范围通道
      2. 现在提取此通道,同时使皮肤像素等于zero

        Mat mExtracted = new Mat();
        Core.extractChannel(output, mExtracted, 0);
        

        现在你有mExtracted矩阵,其中肤色像素为0,其余为255(或肤色,我不确定)。

        1. 获取零点数
        2. 由于0现在实际上是肤色区域,您可以做的是定义一个适合您需要的阈值。根据我的需要,我希望皮肤覆盖超过一半的面积,所以我做了相应的逻辑。

          int n = Core.countNonZero(mExtracted);
          int check = (mExtracted.rows() * mExtracted.cols())/2;
          
          if(n >= check && isFocused) {
              //Take picture
          }