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;
}