千寻的第一篇博客
研究生期间做的小项目,话不多说,记录供大家分享。
1.手势识别程序
功能:读取当前路径下的.jpg文件,对图片中的手势进行提取,并将手势的HU距信息进行保存
原理:手势肤色信息在CrCb色彩空间呈椭圆模型分布,通过色彩空间转化,在CrCb色彩空间对手势信息进行提取。
实际过程中,图片中包含许多类肤色部分。通过Canny算子对边缘进行检测,提取出面积最大的边缘区域记为手势区域。
#include<opencv2/opencv.hpp>
#include<vector>
#include<math.h>
#include<iostream>
#include<io.h>
#include<string>
using namespace cv;
using namespace std;
//using namespace ml;
//*-------------------------------------------------------------------------------------------------------
//* 函数功能
//* 主函数,我们的程序从这里开始执行
//---------------------------------------------------------------------------------------------------------*/
const char path[100]="*.jpg";
int main()
{
RNG rng(12345);
/*Mat dst;
Mat srcImage,qq;*/
Mat tempMat;
Mat GaussianBlurtempMat;
vector<string>fileName;
struct _finddata_t fileinfo;
long handle;
handle=_findfirst(path,&fileinfo);
if(!handle)
{
cout<<"输入的路径有错误"<<endl;
return -1;
}
else
{
fileName.push_back(fileinfo.name);
while(_findnext(handle,&fileinfo)==0)
{
fileName.push_back(fileinfo.name);
}
}
vector<Mat>srcMat(fileName.size());
for(int i=0;i<fileName.size();i++) //测试加载图像是否成功
{
cout<<fileName[i]<<" "<<endl;
srcMat[i]=imread(fileName[i],CV_LOAD_IMAGE_COLOR); //加载图像,参数 CV_LOAD_IMAGE_COLOR 意味着不管原始图像的通道数是多少,都将被转换为3通道输入
}
if(_findclose(handle)==0)
cout<<"文件句柄成功关闭"<<endl;
else
cout<<"文件句柄关闭失败..."<<endl;
vector<vector<double>>HuData/*(fileName.size())*/; //HuData,用来保存图片数组中每幅图片的HU距值,我们通过HU距值来进行网络模型训练
for(int k=0;k<fileName.size();k++) //依次遍历图片数组
{
cvtColor(srcMat[k],tempMat,CV_BGR2YCrCb); //将图像转化为YCrCb色彩空间
namedWindow("cr",WINDOW_AUTOSIZE);
namedWindow("normalizedImage",WINDOW_AUTOSIZE);
//滤波
GaussianBlur(tempMat,GaussianBlurtempMat,Size(3,3),0,0);
//对加载的原图像进行通道分离
vector<Mat>channels;
split(GaussianBlurtempMat, channels);
Mat imageBlueChannel,cr,cb;
imageBlueChannel = channels.at(0); //提取蓝色通道
cr = channels.at(1);
cb = channels.at(2);
Mat cr1,cb2;
threshold(cr, cr1, 139, 143, THRESH_BINARY); //阈值分割,设置的阈值均为经验值
threshold(cb, cb2, 120, 127, THRESH_BINARY);
imshow("cr",cr1);
//膨胀腐蚀操作 ,开闭运算
int s = 3 ;
Mat structureElement = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));
//预处理方法 膨胀腐蚀在膨胀 本文以cr 通道进行演示,大家可以通过cr,cb两通道特征,进行图像提取
dilate(cr1, cr, structureElement, Point(-1, -1),2);
erode(cr, cr, structureElement,Point(-1, -1),3);
dilate(cr, cr, structureElement, Point(-1, -1),2);
//边缘提取
Mat edgeMat;
Canny(cr, edgeMat, 150,150* 2, 3, false);
//提取最大值最小值,将其通过矩形区域进行标记
Mat bin_output;
vector<vector<Point>> contours;
vector<Vec4i> hierachy;
//发现轮廓
findContours(edgeMat, contours, hierachy, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE);
Mat resultImage = Mat ::zeros(edgeMat.size(),CV_8U);
//提取出轮廓数组中最大的轮廓
int j=0;
size_t max=contours[j].size();
for (size_t i = 0; i < contours.size(); i++) {
if(contours[i].size()<100)
{
continue;
}
else if(contours[i].size()>max)
{
max=contours[i].size();
j=i;
}else
{
continue;
}
}
//绘制轮廓信息
drawContours(resultImage, contours, j, Scalar(255, 0, 255));
//在轮廓区域画图形标志
vector<vector<Point>> contours_ploy(contours.size());
vector<Rect> ploy_rects(contours.size());
vector<Point2f> ccs(contours.size());
vector<float> radius(contours.size());
vector<RotatedRect> minRects(contours.size());
vector<RotatedRect> myellipse(contours.size());
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
//减少多边形轮廓点数
approxPolyDP(Mat(contours[j]), contours_ploy[j], 3, true);
//计算轮廓的垂直边界最小矩形
ploy_rects[j] = boundingRect(contours_ploy[j]);
Mat roi=resultImage(Rect(ploy_rects[j].x,ploy_rects[j].y,ploy_rects[j].width,ploy_rects[j].height));
//提取的关键就是Rect(0,0,30,30),其中0 ,0表示感兴趣区域的左上角位置,后面的30,30表示感兴趣部分的宽度和高度
Mat img1,img2;
roi.copyTo(img1);//将感兴趣区域赋值到img1
//对感兴趣区域做归一化处理
resize(img1, img2, cv::Size(180, 180), (0, 0), (0, 0), cv::INTER_LINEAR);
imshow("normalizedImage",img2);
//提取出Hu距,计算矩
vector<Moments> mu(contours.size());
mu[j] = moments(contours[j], false );
vector<double>Data;
Data.push_back(mu[j].nu20);
Data.push_back(mu[j].nu11);
Data.push_back(mu[j].nu02);
Data.push_back(mu[j].nu30);
Data.push_back(mu[j].nu21);
Data.push_back(mu[j].nu12);
Data.push_back(mu[j].nu03);
HuData.push_back(Data);
}
cout<<"===================="<<endl;
for(int i=0;i<fileName.size();i++) //测试是否装载成功
{
for(int j=0;j<HuData[0].size();j++)
{
cout<<HuData[i][j]<<" ";
}
cout<<endl;
}
waitKey(0);
return 0;
}