第七章 学习OpenCV(12)
#include <cv.h>
#include <highgui.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
using namespace std;
CvPoint Current_Point; //全局变量才可通过普通成员引用变更其值
bool find_point(IplImage *img, char val);
void Create_Imask(IplImage *src, IplImage *dst);
void Create_RIO(IplImage *dst, IplImage *match_temp);
void Find_Hand_Region(IplImage *model, IplImage *test, IplImage *mask, IplImage *dst);
int main(int argc, char* argv[])
{
IplImage *src1, *src2, *Imask; //肤色模板 视频流 手掌掩码
IplImage *dst, *match_temp; //肤色区域图像 模板匹配图像
CvCapture* capture;
if (!(src1 = cvLoadImage("D:\\Template\\OpenCV\\Template60_Hand_Track _Match_Template\\Debug\\hand.jpg")))
return -1; //肤色模板
if (!(match_temp = cvLoadImage("D:\\Template\\OpenCV\\Template60_Hand_Track _Match_Template\\Debug\\match_temp.jpg")))
return -2; //匹配模板图像
if (argc == 1) //此处代码是做一个判断,有摄像头设备则读入摄像头设备的图像信息,没有则播放本地视频文件
capture = cvCreateCameraCapture(0);
else
return -3; //没有摄像头
src2 = cvQueryFrame(capture); //获取摄像头图像帧
Imask = cvCreateImage(cvGetSize(src1), src1->depth, 1); //手掌掩码图像
dst = cvCreateImage(cvGetSize(src2), IPL_DEPTH_8U, 1); //处理后的反射投影
int result_width = src2->width - match_temp->width + 1;
int result_height = src2->height - match_temp->height + 1;
CvSize result_size = cvSize(result_width, result_height);
IplImage *result = cvCreateImage(result_size, IPL_DEPTH_32F, 1);
Create_Imask(src1, Imask); //创建肤色掩码图像
cvNamedWindow("Match_Template", 1);
cvNamedWindow("BACK_Projection", 1);
cvNamedWindow("Destination", 1);
cvNamedWindow("Hand", 1);
cvNamedWindow("SQDIFF_NORMED", 1);
cvShowImage("Match_Template", match_temp);
while (1)
{
src2 = cvQueryFrame(capture);
//Find_Hand_Region(src1, src2, Imask, dst); //寻找肤色区域
cvMatchTemplate(src2, match_temp, result, 1); //模板匹配
//cvNormalize(result, result, 1, 0, CV_MINMAX); //元素规范化 平移缩放返回值[0,1]
if (!src2)
break;
cvShowImage("SQDIFF_NORMED", result);
char c = cvWaitKey(32);
if (c == 27)
break;
}
cvWaitKey();
cvReleaseCapture(&capture);
cvReleaseImage(&src1);
cvReleaseImage(&Imask);
cvReleaseImage(&dst);
cvReleaseImage(&match_temp);
cvReleaseImage(&result);
cvDestroyAllWindows();
}
/******************遍历图像-指针算法********************/
bool find_point(IplImage *img, char val)
{
char* ptr = NULL;
if (img->nChannels == 1)
{
ptr = img->imageData;
if (ptr != NULL)
{
for (int i = 0; i < img->height; i++) //矩阵指针行寻址
{
ptr = (img->imageData + i*(img->widthStep)); //i 行 j 列
for (int j = 0; j < img->width; j++) //矩阵指针列寻址
{
if (ptr[j] == val) //判断某点像素是否为255
{
Current_Point.x = j;
Current_Point.y = i;
return true;
}
}
}
}
}
return false;
}
void Create_Imask(IplImage *src, IplImage *dst)
{
int Last_Area = 0; //上一个区域面积
int Current_Area = 0; //当前区域面积
int threshold_type = CV_THRESH_BINARY; //阈值类型
CvPoint Last_Point; //值为255点的上一点
CvConnectedComp comp; //被填充区域统计属性
IplImage *gray, *threshold, *temp,*open; //灰度图像
Last_Point = cvPoint(0, 0); //初始化上一点
Current_Point = cvPoint(0, 0); //初始化当前点
gray = cvCreateImage(cvGetSize(src), src->depth, 1);
threshold = cvCreateImage(cvGetSize(src), src->depth, 1);
temp = cvCreateImage(cvGetSize(src), src->depth, 1);
open = cvCreateImage(cvGetSize(src), src->depth, 1);
cvCvtColor(src, gray, CV_BGR2GRAY); //源图像->灰度图像
//二值阈值化
cvThreshold(gray, threshold, 100, 255, threshold_type);
//开运算,去除小亮区域,其他联结 NULL:3*3参考点为中心的核
cvMorphologyEx(threshold, open, temp, NULL, CV_MOP_OPEN, 1);
cvNamedWindow("肤色模板", 1);
cvNamedWindow("肤色掩码", 1);
cvShowImage("肤色模板", src);
cvShowImage("肤色掩码", dst);
//漫水填充 获得手掌掩码
cvCopy(open, dst); //复制生成手掌掩码
do
{
if (find_point(dst, 255)) //找像素值为255的像素点
{
cout << " X: " << Current_Point.x << " Y: " << Current_Point.y << endl;
cvFloodFill(dst, Current_Point, cvScalar(100), cvScalar(0), cvScalar(0),
&comp, 8 | CV_FLOODFILL_FIXED_RANGE); //对值为255的点进行漫水填充,值100
Current_Area = comp.area; //当前区域面积
if (Last_Area<Current_Area) //当前区域大于上一区域,上一区域清0
{
if (Last_Area>0)
cvFloodFill(dst, Last_Point, cvScalar(0), cvScalar(0), cvScalar(0),
&comp, 8 | CV_FLOODFILL_FIXED_RANGE); //上一区域赋值0
cvShowImage("肤色掩码", dst);
cvWaitKey(500);
Last_Area = Current_Area; //当前区域赋值给上一区域
Last_Point = Current_Point; //当前点赋值给上一点
}
else //当前区域小于等于上一区域,当前区域清0
{
if (Current_Area>0)
cvFloodFill(dst, Current_Point, cvScalar(0), cvScalar(0), cvScalar(0),
&comp, 8 | CV_FLOODFILL_FIXED_RANGE); //当前区域赋值0
cvShowImage("肤色掩码", dst);
cvWaitKey(500);
}
}
else //最后剩余的最大区域赋值255
{
cvFloodFill(dst, Last_Point, cvScalar(255), cvScalar(0), cvScalar(0), &comp, 8 | CV_FLOODFILL_FIXED_RANGE);
cvShowImage("肤色掩码", dst);
cvWaitKey(500);
//上一区域赋值0
break;
}
} while (true);
//cvSaveImage("Imask.jpg", dst);
cvReleaseImage(&gray);
cvReleaseImage(&threshold);
cvReleaseImage(&temp);
cvReleaseImage(&open);
}
void Find_Hand_Region(IplImage *model, IplImage *test, IplImage *mask, IplImage *dst)
{
int threshold_type = CV_THRESH_BINARY; //阈值类型
//临时图像 反向投影图像
IplImage *temp = cvCreateImage(cvSize(model->width, model->height), IPL_DEPTH_8U, 1);
IplImage *back_projection = cvCreateImage(cvSize(test->width, test->height), IPL_DEPTH_8U, 1);
//RGB
IplImage *r_plane_1 = cvCreateImage(cvSize(model->width, model->height), IPL_DEPTH_8U, 1);
IplImage *g_plane_1 = cvCreateImage(cvSize(model->width, model->height), IPL_DEPTH_8U, 1);
IplImage *b_plane_1 = cvCreateImage(cvSize(model->width, model->height), IPL_DEPTH_8U, 1);
IplImage *r_plane_2 = cvCreateImage(cvSize(test->width, test->height), IPL_DEPTH_8U, 1);
IplImage *g_plane_2 = cvCreateImage(cvSize(test->width, test->height), IPL_DEPTH_8U, 1);
IplImage *b_plane_2 = cvCreateImage(cvSize(test->width, test->height), IPL_DEPTH_8U, 1);
IplImage *planes1[] = { r_plane_1, g_plane_1, b_plane_1 }; //色相饱和度数组
IplImage *planes2[] = { r_plane_2, g_plane_2, b_plane_2 }; //色相饱和度数组
cvCvtPixToPlane(model, b_plane_1, g_plane_1, r_plane_1, NULL); //图像分割
cvCvtPixToPlane(test, b_plane_2, g_plane_2, r_plane_2, NULL); //图像分割
int r_bins = 32, g_bins = 32, b_bins = 32;
//建立直方图
CvHistogram *hist_model, *hist_test;
int hist_size[] = { r_bins, g_bins, b_bins }; //对应维数包含bins个数的数组
float r_ranges[] = { 0, 255 }; //R通道划分范围
float g_ranges[] = { 0, 255 }; //G通道划分范围
float b_ranges[] = { 0, 255 }; //R通道划分范围
float* ranges[] = { r_ranges, g_ranges, b_ranges }; //划分范围数对, ****均匀bin,range只要最大最小边界
//创建直方图 (维数,对应维数bins个数,密集矩阵方式存储,划分范围数对,均匀直方图)
hist_model = cvCreateHist(3, hist_size, CV_HIST_ARRAY, ranges, 1);
hist_test = cvCreateHist(3, hist_size, CV_HIST_ARRAY, ranges, 1);
cvCalcHist(planes1, hist_model, 0, mask); //计算直方图(图像,直方图结构,不累加,掩码)
cvCalcHist(planes2, hist_test, 0, 0); //计算直方图(图像,直方图结构,不累加,掩码)
//cvNormalizeHist(hist_model, 1.0); //直方图归一化
//cvNormalizeHist(hist_test, 1.0); //直方图归一化
//像素点的反射投影 创建测试hist的图像数组 结果图像 模板hist
cvCalcBackProject(planes2, back_projection, hist_model);
cvSmooth(back_projection, dst, CV_MEDIAN, 11); //中值滤波 去除椒盐噪声
//开运算,去除小亮区域,其他联结 NULL:3*3参考点为中心的核
cvMorphologyEx(dst, dst, temp, NULL, CV_MOP_OPEN, 1);
cvThreshold(dst, dst, 0, 255, threshold_type); //二值阈值化
//边缘检测 src dst 边缘连接 边缘初始分割 核
//cvCanny(dst, dst,90,180,3);
//得到手掌轮廓 绘制轮廓线
//getContoursByC(dst, dst);
cvShowImage("BACK_Projection", back_projection);
cvShowImage("Destination", dst);
cvXorS(dst, cvScalar(255), dst); //掩码图像按位异或,求反生成新的掩码处理模板
cvSet(test, cvScalarAll(0), dst);
cvShowImage("Hand", test);
//cvSaveImage("DST.jpg", dst);
cvReleaseHist(&hist_model);
cvReleaseHist(&hist_test);
cvReleaseImage(&back_projection);
cvReleaseImage(&temp);
cvReleaseImage(&r_plane_1);
cvReleaseImage(&g_plane_1);
cvReleaseImage(&b_plane_1);
cvReleaseImage(&r_plane_2);
cvReleaseImage(&g_plane_2);
cvReleaseImage(&b_plane_2);
}
运行结果如下图:
http://www.jiaoanw.com/%E6%95%99%E6%A1%88%E6%A0%BC%E5%BC%8F/article-43870-12.html
http://www.jiaoanw.com/
true
教案网
http://www.jiaoanw.com/%E6%95%99%E6%A1%88%E6%A0%BC%E5%BC%8F/article-43870-12.html
report
18413
#include cv.h #include highgui.h #include stdlib.h #include stdio.h #include math.h using namespace std ;CvPoint Current_Point; //全局变量才可通过普通成员引用变更其值 bool find_point
谁让你那么遭人恨呢