手势识别与行人检测 上

千寻的第一篇博客

研究生期间做的小项目,话不多说,记录供大家分享。

 

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

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值