本章学习轮廓识别
// bbb.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int _tmain()
{
const std::string sourceReference = "c://avi.avi";
int delay = 1;
char c;
int frameNum = -1; // Frame counter
VideoCapture captRefrnc(sourceReference);
if ( !captRefrnc.isOpened())
{
// cout << "Could not open reference " << sourceReference << endl;
return -1;
}
Size refS = Size( (int) captRefrnc.get(CV_CAP_PROP_FRAME_WIDTH),
(int) captRefrnc.get(CV_CAP_PROP_FRAME_HEIGHT) );
bool bHandFlag = false;
const char* WIN_SRC = "Source";
const char* WIN_RESULT = "Result";
// Windows
namedWindow(WIN_SRC, CV_WINDOW_AUTOSIZE );
namedWindow(WIN_RESULT, CV_WINDOW_AUTOSIZE);
Mat frame; // 输入视频帧序列
Mat frameHSV; // hsv空间
Mat mask(frame.rows, frame.cols, CV_8UC1); // 2值掩膜
Mat dst(frame); // 输出图像
// Mat frameSplit[4];
vector< vector<Point> > contours; // 轮廓
vector< vector<Point> > filterContours; // 筛选后的轮廓
vector< Vec4i > hierarchy; // 轮廓的结构信息
vector< Point > hull; // 凸包络的点集
while(true) //Show the image captured in the window and repeat
{
captRefrnc >> frame;
if( frame.empty() )
{
cout << " < < < Game over! > > > ";
break;
}
imshow( WIN_SRC, frame);
// Begin
// 中值滤波,去除椒盐噪声
medianBlur(frame, frame, 5);
// GaussianBlur( frame, frameHSV, Size(9, 9), 2, 2 );
// imshow("blur2", frameHSV);
// pyrMeanShiftFiltering(frame, frameHSV, 10, 10);
// imshow(WIN_BLUR, frameHSV);
// 转换到HSV颜色空间,更容易处理
cvtColor( frame, frameHSV, CV_BGR2HSV );
// split(frameHSV, frameSplit);
// imshow(WIN_H, frameSplit[0]);
// imshow(WIN_S, frameSplit[1]);
// imshow(WIN_V, frameSplit[2]);
Mat dstTemp1(frame.rows, frame.cols, CV_8UC1);
Mat dstTemp2(frame.rows, frame.cols, CV_8UC1);
// 对HSV空间进行量化,得到2值图像,亮的部分为手的形状
inRange(frameHSV, Scalar(0,30,30), Scalar(40,170,256), dstTemp1);
inRange(frameHSV, Scalar(156,30,30), Scalar(180,170,256), dstTemp2);
bitwise_or(dstTemp1, dstTemp2, mask);
// inRange(frameHSV, Scalar(0,30,30), Scalar(180,170,256), dst);
// 形态学操作,去除噪声,并使手的边界更加清晰
Mat element = getStructuringElement(MORPH_RECT, Size(3,3));
erode(mask, mask, element);
morphologyEx(mask, mask, MORPH_OPEN, element);
dilate(mask, mask, element);
morphologyEx(mask, mask, MORPH_CLOSE, element);
frame.copyTo(dst, mask);
contours.clear();
hierarchy.clear();
filterContours.clear();
// 得到手的轮廓
findContours(mask, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
// 去除伪轮廓
for (size_t i = 0; i < contours.size(); i++)
{
// approxPolyDP(Mat(contours[i]), Mat(approxContours[i]), arcLength(Mat(contours[i]), true)*0.02, true);
if (fabs(contourArea(Mat(contours[i]))) > 30000) //判断手进入区域的阈值
{
filterContours.push_back(contours[i]);
}
}
// 画轮廓
drawContours(dst, filterContours, -1, Scalar(0,0,255), 3/*, 8, hierarchy*/);
// 得到轮廓的凸包络
for (size_t j=0; j<filterContours.size(); j++)
{
convexHull(Mat(filterContours[j]), hull, true);
int hullcount = (int)hull.size();
for (int i=0; i<hullcount-1; i++)
{
line(dst, hull[i+1], hull[i], Scalar(255,0,0), 2, CV_AA);
}
line(dst, hull[hullcount-1], hull[0], Scalar(255,0,0), 2, CV_AA);
}
imshow(WIN_RESULT, dst);
dst.release();
// End
c = cvWaitKey(delay);
if (c == 27) break;
}
return 0;
}
源代码下载地址如下:http://download.csdn.net/detail/qq5132834/8358691
运行效果如下图所示: