You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio+OpenCV:手部检测项目中从YCrCb图像获取皮肤HSV值

手部检测项目:Android Studio + OpenCV 提取皮肤区域HSV值方案

嘿,我来帮你一步步搞定这个需求——从YCrCb色彩空间定位皮肤,再提取对应的HSV值,还要计算皮肤区域的HSV统计信息,对吧?下面是具体的实现步骤和代码示例,都是Android平台上用OpenCV的实操内容:

1. 先确认OpenCV在Android Studio的配置(快速回顾)

如果还没配置,其实很简单:

  • 下载OpenCV Android SDK,解压后把sdk/java目录导入到你的Android项目作为模块
  • 在app模块的build.gradle里添加对这个OpenCV模块的依赖
  • 在你的Activity里初始化OpenCV(建议在onCreate前完成):
static {
    if (!OpenCVLoader.initDebug()) {
        // 这里可以加个Toast或者日志提示初始化失败
    }
}

2. 核心流程:从YCrCb提取皮肤掩码 → 转换到HSV → 计算HSV值

步骤拆解与代码实现

下面的代码可以放在相机帧处理回调(比如CameraBridgeViewBase.CvCameraViewListener2的onCameraFrame方法)里,或者处理本地图片的函数中:

import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
import java.util.Collections;

public Mat processHandFrame(Mat inputFrame) {
    // 1. 把输入帧(默认BGR格式)转成YCrCb色彩空间
    Mat ycrcbMat = new Mat();
    Imgproc.cvtColor(inputFrame, ycrcbMat, Imgproc.COLOR_BGR2YCrCb);

    // 2. 定义YCrCb的皮肤阈值——这个范围是行业内常用的皮肤检测区间,你可以根据测试场景微调
    Scalar lowerSkinThreshold = new Scalar(0, 133, 77);
    Scalar upperSkinThreshold = new Scalar(255, 173, 127);
    Mat skinMask = new Mat();
    // 生成皮肤掩码:符合阈值的像素为255(白色),其余为0(黑色)
    Core.inRange(ycrcbMat, lowerSkinThreshold, upperSkinThreshold, skinMask);

    // 可选优化:对掩码做形态学操作,去除小噪声点,让皮肤区域更平滑
    Mat morphKernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(5, 5));
    Imgproc.dilate(skinMask, skinMask, morphKernel);
    Imgproc.erode(skinMask, skinMask, morphKernel);

    // 3. 把原BGR帧转成HSV色彩空间
    Mat hsvMat = new Mat();
    Imgproc.cvtColor(inputFrame, hsvMat, Imgproc.COLOR_BGR2HSV);

    // 4. 用皮肤掩码提取仅包含皮肤区域的HSV图像
    Mat skinHSVRegion = new Mat();
    hsvMat.copyTo(skinHSVRegion, skinMask);

    // 5. 计算皮肤区域的HSV统计值
    // 方式1:计算HSV三个通道的均值(最常用的代表值)
    Scalar meanHSV = Core.mean(skinHSVRegion, skinMask);
    Log.d("SkinHSV", "平均H值: " + meanHSV.val[0] + ", 平均S值: " + meanHSV.val[1] + ", 平均V值: " + meanHSV.val[2]);

    // 方式2:计算HSV各通道的最小/最大值(获取范围)
    Core.MinMaxLocResult hRange = Core.minMaxLoc(skinHSVRegion.submat(0, skinHSVRegion.rows(), 0, 1));
    Core.MinMaxLocResult sRange = Core.minMaxLoc(skinHSVRegion.submat(0, skinHSVRegion.rows(), 1, 2));
    Core.MinMaxLocResult vRange = Core.minMaxLoc(skinHSVRegion.submat(0, skinHSVRegion.rows(), 2, 3));
    Log.d("SkinHSVRanges", "H范围: " + hRange.minVal + " ~ " + hRange.maxVal);
    Log.d("SkinHSVRanges", "S范围: " + sRange.minVal + " ~ " + sRange.maxVal);
    Log.d("SkinHSVRanges", "V范围: " + vRange.minVal + " ~ " + vRange.maxVal);

    // 方式3:生成HSV直方图(查看颜色分布)
    MatOfInt channels = new MatOfInt(0, 1, 2); // 对应H、S、V三个通道
    MatOfInt histSize = new MatOfInt(180, 256, 256); // H的范围是0-179,S/V是0-255
    MatOfFloat ranges = new MatOfFloat(0, 180, 0, 256, 0, 256);
    Mat hsvHist = new Mat();
    Imgproc.calcHist(Collections.singletonList(skinHSVRegion), channels, skinMask, hsvHist, histSize, ranges);
    // 这里可以把直方图数据导出做进一步分析,比如找峰值颜色

    // 别忘了释放Mat资源,避免内存泄漏
    ycrcbMat.release();
    skinMask.release();
    hsvMat.release();
    skinHSVRegion.release();
    channels.release();
    histSize.release();
    ranges.release();
    hsvHist.release();

    return inputFrame; // 返回原帧或者处理后的掩码帧都可以,看你的需求
}

关键细节说明

  • YCrCb皮肤阈值选择:Cr通道对应红色分量,Cb对应蓝色分量,皮肤的Cr值通常在133-173之间,Cb在77-127之间,这个范围对黄种人、白种人都有不错的检测效果,如果你是针对特定肤色人群,可以用样本图片调整阈值。
  • 色彩空间转换注意:OpenCV在Android中获取的相机帧是BGR格式,所以转换时要用COLOR_BGR2YCrCb和COLOR_BGR2HSV,别误用RGB相关的转换常量。
  • 掩码的作用:copyTo方法传入掩码后,只会把掩码中白色区域(255)对应的像素复制到目标Mat,这样就只保留了皮肤区域的HSV数据,避免背景干扰。

3. 调试小技巧

  • 可以把skinMask转换成BGR格式显示在界面上,看看皮肤检测的准确率,调整阈值或者形态学操作的参数
  • 打印出来的均值和范围可以用来后续的皮肤跟踪或者手势识别,比如设置HSV的皮肤阈值做二次验证

内容的提问来源于stack exchange,提问作者sobia qaiser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:15:25