android – 检测皮肤和捕获图像

更新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
}
点赞