使用opencv提取手部信息

1. 前言

这两天对大神的一篇博客中的东西非常感兴趣 http://blog.csdn.net/onezeros/article/details/6110838想到自己也算是研究计算机视觉的人, 于是就想把大神的这个东西给复现出来。 正好其中用到了一个手部信息提取的一个功能, 按照自己的想法给实现了一下。
实现效果:
这里写图片描述
这里写图片描述

2. 处理流程

2.1 处理思路及流程

首先我们先分析采集的图像中的某一帧图像信息
这里写图片描述
发现人的肤色其实是这个场景中非常特殊的成分(有些偏红, 不知道是不是这样, 我的颜色感知总是有些问题。。。), 于是考虑将他转化到 YCrCb 空间http://baike.baidu.com/link?url=5hoOSJjw3kITEqvd_479q5vOiJpTucbL9vI9o4UNhzghM2e9tTRlXYmKKVh_-qPOQCmSO3cLNjWPoU6QoUCs8K
其中 Cb 反应的是蓝色 与 RGB亮度之间的差异, Cr 是红色
Y:
这里写图片描述
Cb
这里写图片描述
Cr
这里写图片描述

很容易发现, 我们需要的是Cr 里面的图形, 于是对Cr 图像做进一步处理
先使用OSTU 全局阈值做二值化
这里写图片描述
开运算 去除噪点
这里写图片描述
提取最大面积轮廓
这里写图片描述

2.2 实现代码

#include <opencv.hpp>
#include <string>

using namespace cv;
using namespace std;

int main(){
    Mat src = imread("1.png");
    imshow("src", src);

    Mat src_YCrCb;
    cvtColor(src, src_YCrCb, CV_RGB2YCrCb);                     // 转化到 YCRCB 空间处理
    vector<Mat> channels;
    split(src_YCrCb, channels);
    cout << channels.size() << endl;

    imshow("Y", channels[0]);
    imshow("Cr", channels[1]);
    imshow("Cb", channels[2]);

    Mat target = channels[2];
    threshold(target, target, 0, 255, CV_THRESH_OTSU);              // 二值化处理
    imshow("target", target);

    Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));   // 开运算去除噪点
    morphologyEx(target, target, MORPH_OPEN, element);
    imshow("open", target);

    vector<vector<Point>> contours;                                 // 利用最大范围查找手臂
    findContours(target, contours, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE);
    double mymax = 0;
    vector<Point> max_contours;
    for (int i = 0; i < contours.size(); i++){
        double area = contourArea(contours[i]);
        if (area > mymax){
            mymax = area;
            max_contours = contours[i];
        }
    }
    vector<vector<Point>> final_cont;
    final_cont.push_back(max_contours);
    drawContours(src, final_cont, -1, Scalar(255));
    imshow("max_area", src);

    waitKey();
    return 0;
}

3. 视频处理

有了上面的处理, 我们可以非常类似的去处理一个视频数据
相应实现代码

#include <opencv.hpp>
#include <string>

using namespace cv;
using namespace std;

void dealWithImg(Mat & src){
    Mat src_YCrCb;
    cvtColor(src, src_YCrCb, CV_RGB2YCrCb);                     // 转化到 YCRCB 空间处理
    vector<Mat> channels;
    split(src_YCrCb, channels);

    Mat target = channels[2];
    threshold(target, target, 0, 255, CV_THRESH_OTSU);              // 二值化处理

    Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));   // 开运算去除噪点
    morphologyEx(target, target, MORPH_OPEN, element);

    vector<vector<Point>> contours;                                 // 利用最大范围查找手臂
    findContours(target, contours, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE);
    double mymax = 0;
    vector<Point> max_contours;
    for (int i = 0; i < contours.size(); i++){
        double area = contourArea(contours[i]);
        if (area > mymax){
            mymax = area;
            max_contours = contours[i];
        }
    }
    vector<vector<Point>> final_cont;
    final_cont.push_back(max_contours);
    drawContours(src, final_cont, -1, Scalar(255));
}

int main(){
    string filename = R"(C:\Users\Administrator\Desktop\computer vision\3d-reconstruction-tools\data\videos\video0.avi)";
    VideoCapture cap(filename);
    if (!cap.isOpened()){
        cerr << "can not open camera" << endl;
        exit(-1);
    }

    Mat src;
    while (cap.read(src)){
        dealWithImg(src);
        imshow("src", src);
        int key = waitKey(3);
        if (key == 27)
            break;      
    }

    return 0;
}
  • 2
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值