更新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?
>如何从这里开始检测皮肤?
任何帮助表示赞赏.
解决方法:
我通过提取肤色范围并使所有像素等于零来解决我的问题.以下是步骤.
>将图像转换为HSV
首先将图像转换为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);
>提取此皮肤范围通道
现在提取此通道,同时使皮肤像素等于零
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
}