使用opencv提取手部信息

1. 前言

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

使用opencv提取手部信息_第1张图片

2. 处理流程

2.1 处理思路及流程

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

很容易发现, 我们需要的是Cr 里面的图形, 于是对Cr 图像做进一步处理
先使用OSTU 全局阈值做二值化
使用opencv提取手部信息_第6张图片
开运算 去除噪点
使用opencv提取手部信息_第7张图片
提取最大面积轮廓
使用opencv提取手部信息_第8张图片

2.2 实现代码

#include 
#include 

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 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> contours;                                 // 利用最大范围查找手臂
    findContours(target, contours, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE);
    double mymax = 0;
    vector 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> final_cont;
    final_cont.push_back(max_contours);
    drawContours(src, final_cont, -1, Scalar(255));
    imshow("max_area", src);

    waitKey();
    return 0;
}

3. 视频处理

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

#include 
#include 

using namespace cv;
using namespace std;

void dealWithImg(Mat & src){
    Mat src_YCrCb;
    cvtColor(src, src_YCrCb, CV_RGB2YCrCb);                     // 转化到 YCRCB 空间处理
    vector 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> contours;                                 // 利用最大范围查找手臂
    findContours(target, contours, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE);
    double mymax = 0;
    vector 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> 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;
}

你可能感兴趣的:(图像处理与机器视觉,C/C++,opencv)