OpenCv学习笔记

来源:互联网 发布:激活windows 编辑:程序博客网 时间:2024/06/05 20:58

    11月份有一个项目需要用到手势识别功能,google之,大爱OpenCv,记录下自己的学习历程,让我们为互联网的开源精神Cheers.

   

    项目采用Qt + Opencv + win7环境下实现 

  

 一、

   首先我们要 win7下配置OpenCV的Qt开发环境,具体参考如下

  http://blog.csdn.net/qiurisuixiang/article/details/8665278

   当你的test code 成功实现一张图片显示的时候,congratulate you,你的环境已经搭建成功了。

二、

   做完初步的环境搭建,让我们来做一些好玩的事情,实现对一个物体的背景轮廓分离。这里我采用了大津算法,初步实现了背景和背景的分离。

   贴Code

  

#include"cv.h"#include"cxcore.h"#include"highgui.h"void cvThresholdOtsu(IplImage* src, IplImage* dst){    int height=src->height;    int width=src->width;    //histogram    float histogram[256]={0};    for(int i=0;i<height;i++)    {        unsigned char* p=(unsigned char*)src->imageData+src->widthStep*i;        for(int j=0;j<width;j++)        {            histogram[*p++]++;        }    }    //normalize histogram    int size=height*width;    for(int i=0;i<256;i++)    {        histogram[i]=histogram[i]/size;    }    //average pixel value    float avgValue=0;    for(int i=0;i<256;i++)    {        avgValue+=i*histogram[i];    }    int threshold;    float maxVariance=0;    float w=0,u=0;    //自适应阈值    for(int i=0;i<256;i++)    {        w+=histogram[i];        u+=i*histogram[i];        float t=avgValue*w-u;        float variance=t*t/(w*(1-w));        if(variance>maxVariance)        {            maxVariance=variance;            threshold=i;        }    }    cvThreshold(src,dst,threshold,255,CV_THRESH_BINARY);//设置阈值}void cvSkinOtsu(IplImage* src, IplImage* dst){    assert(dst->nChannels==1&& src->nChannels==3);    IplImage* ycrcb=cvCreateImage(cvGetSize(src),8,3);    IplImage* cr=cvCreateImage(cvGetSize(src),8,1);    cvCvtColor(src,ycrcb,CV_BGR2YCrCb);    cvSplit(ycrcb,0,cr,0,0);    cvThresholdOtsu(cr,cr);    cvCopyImage(cr,dst);    cvReleaseImage(&cr);    cvReleaseImage(&ycrcb);}int main(int argc,char *argv[]){    IplImage *src=cvLoadImage("E:/hand.jpg",1);    IplImage *binary_img=cvCreateImage(cvGetSize(src),8,1);    cvSkinOtsu(src, binary_img);    CvMemStorage *pcvMStorage = cvCreateMemStorage();    CvSeq *pcvSeq = NULL;    cvFindContours(binary_img, pcvMStorage, &pcvSeq, sizeof(CvContour),\                       CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));    IplImage *pOutlineImage = cvCreateImage(cvGetSize(binary_img), IPL_DEPTH_8U, 3);    cvDrawContours(pOutlineImage, pcvSeq, CV_RGB(255,0,0), CV_RGB(0,255,0), 5, 2);    cvNamedWindow("Image",1);    cvNamedWindow("binary",1);    cvNamedWindow("end",1);    cvShowImage("Image",src);    cvShowImage("binary",binary_img);    cvShowImage("end", pOutlineImage);    cvWaitKey(0);    cvDestroyWindow("Image");    cvReleaseImage(&src);    cvDestroyWindow("binary");    cvReleaseImage(&binary_img);    cvDestroyWindow("end");    cvReleaseImage(&pOutlineImage);    return 0;}

 

通过以上代码我们可以实现初步的轮廓提取,贴上一张图



具体的实现算法google之,简要概括就是通过类间方差识别出手掌和背景的分离指标,用这个算出手掌和背景的分离阈值,从而对图像二值化,最后使用cvFindContours对二值化图像寻找轮廓显示。未完待续。