更新1
我知道inRange
函数的作用。但是我不想应用蒙版并用肤色显示新图像。我想要做的是知道图像是否包含肤色并覆盖更大的区域。
我想做什么
我想在边界内检测到手指时拍摄照片。它的尺寸是已知的。
苦苦挣扎
我做了什么
我正在使用JNI Layer来执行操作。我可以使用this tutorial从图像数据中获取Mat
,但不知道如何操纵poutPixels
。格式为NV21
,我不知道如何对其进行操作。
我需要裁剪图像,然后检测图像中是否存在皮肤。我已经成功地将图像裁剪到所需的尺寸,但没有任何线索可以向前移动以检测皮肤。我希望此方法返回true
或false
。
以下是代码:
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
功能的内容,但我不知道如何检查是否有皮肤。
问题
NV21
。它是8UC1
还是8UC3
?感谢任何帮助。
答案 0 :(得分:1)
我通过提取肤色范围并使所有像素等于zero
来解决我的问题。以下是步骤。
首先将图片转换为HSV
。
Mat mHsv = new Mat(rows, cols, CvType.CV_8UC3);
Imgproc.cvtColor(mRgba, mHsv, Imgproc.COLOR_RGB2HSV);
肤色范围可能会有所不同,但这个适合我。
Mat output = new Mat();
Core.inRange(mHsv, new Scalar(0, 0.18*255, 0), new Scalar(25, 0.68*255, 255), output);
现在提取此通道,同时使皮肤像素等于zero
Mat mExtracted = new Mat();
Core.extractChannel(output, mExtracted, 0);
现在你有mExtracted
矩阵,其中肤色像素为0
,其余为255
(或肤色,我不确定)。
由于0
现在实际上是肤色区域,您可以做的是定义一个适合您需要的阈值。根据我的需要,我希望皮肤覆盖超过一半的面积,所以我做了相应的逻辑。
int n = Core.countNonZero(mExtracted);
int check = (mExtracted.rows() * mExtracted.cols())/2;
if(n >= check && isFocused) {
//Take picture
}