当前位置: 代码迷 >> Android >> Android下掌纹识别第一步:基于OpenCV的6种肤色分割 源码和效果图
  详细解决方案

Android下掌纹识别第一步:基于OpenCV的6种肤色分割 源码和效果图

热度:63   发布时间:2016-05-01 11:36:12.0
Android上掌纹识别第一步:基于OpenCV的6种肤色分割 源码和效果图

    六种方法分别是:基于RGB分割,基于RG同道的分割,ycrcb+otsu(ostu可以参考http://blog.csdn.net/onezeros/article/details/6136770,

http://wenku.baidu.com/view/05c47e03bed5b9f3f90f1ce4.html),YCrCb空间,YUV空间,HSV空间。下一步就是通过JNI将这些检测移植到android上,最终目标是实现Android智能手机利用掌纹开关机。

环境是在qt下,.pro文件里增加如下代码:

INCLUDEPATH += /usr/include/opencvLIBS += /usr/lib/libcv.so \/usr/lib/libcvaux.so \/usr/lib/libcxcore.so \/usr/lib/libhighgui.so \/usr/lib/libml.so

请看源码:

#include <iostream>#include "cv.h"#include "highgui.h"void SkinRGB(IplImage* rgb,IplImage* _dst);void cvSkinRG(IplImage* rgb,IplImage* gray);void cvThresholdOtsu(IplImage* src, IplImage* dst);void cvSkinOtsu(IplImage* src, IplImage* dst);void cvSkinYCbCr(IplImage* img, IplImage* mask);void cvSkinYUV(IplImage* src,IplImage* dst);void cvSkinHSV(IplImage* src,IplImage* dst);using namespace std;// skin region location using rgb limitationint main(){    IplImage *srcImg = cvLoadImage("/home/yan/download/testPalm4.jpg", 1);    IplImage *dstRGB = cvCreateImage(cvGetSize(srcImg), 8, 3);    IplImage *dstRG = cvCreateImage(cvGetSize(srcImg), 8, 1);    IplImage* dst_crotsu=cvCreateImage(cvGetSize(srcImg),8,1);    IplImage* dst_ycbcr=cvCreateImage(cvGetSize(srcImg),8,1);    IplImage* dst_yuv=cvCreateImage(cvGetSize(srcImg),8,3);    IplImage* dst_hsv=cvCreateImage(cvGetSize(srcImg),8,3);    SkinRGB(srcImg, dstRGB);    cvSaveImage("/home/yan/download/1_dstRGB.jpg", dstRGB);    cvSkinRG(srcImg, dstRG);    cvSaveImage("/home/yan/download/2_dstRG.jpg", dstRG);    cvSkinOtsu(srcImg, dst_crotsu);    cvSaveImage("/home/yan/download/3_dst_crotsu.jpg", dst_crotsu);    cvSkinYCbCr(srcImg, dst_ycbcr);    cvSaveImage("/home/yan/download/4_dst_ycbcr.jpg", dst_ycbcr);    cvSkinYUV(srcImg, dst_yuv);    cvSaveImage("/home/yan/download/5_dst_yuv.jpg", dst_yuv);    cvSkinHSV(srcImg, dst_hsv);    cvSaveImage("/home/yan/download/6_dst_hsv.jpg", dst_hsv);    cvNamedWindow("srcImg", 1);    cvShowImage("srcImg", srcImg);    cvNamedWindow("dstRGB", 1);    cvShowImage("dstRGB", dstRGB);    cvNamedWindow("dstRG", 1);    cvShowImage("dstRG", dstRG);    cvNamedWindow("dstcrotsu", 1);    cvShowImage("dstcrotsu", dst_crotsu);    cvNamedWindow("dst_ycbcr", 1);    cvShowImage("dst_ycbcr", dst_ycbcr);    cvNamedWindow("dst_yuv", 1);    cvShowImage("dst_yuv", dst_yuv);    cvNamedWindow("dst_hsv", 1);    cvShowImage("dst_hsv", dst_hsv);    cvWaitKey(0);    cout << "Hello World!" << endl;    return 0;}void SkinRGB(IplImage* rgb,IplImage* _dst){    cout<<"111"<<endl;    assert(rgb->nChannels==3&& _dst->nChannels==3);    static const int R=2;    static const int G=1;    static const int B=0;    IplImage* dst=cvCreateImage(cvGetSize(_dst),8,3);    cvZero(dst);    for (int h=0;h<rgb->height;h++) {        unsigned char* prgb=(unsigned char*)rgb->imageData+h*rgb->widthStep;        unsigned char* pdst=(unsigned char*)dst->imageData+h*dst->widthStep;        for (int w=0;w<rgb->width;w++) {            if ((prgb[R]>95 && prgb[G]>40 && prgb[B]>20 &&                 prgb[R]-prgb[B]>15 && prgb[R]-prgb[G]>15/*&&                     !(prgb[R]>170&&prgb[G]>170&&prgb[B]>170)*/)||//uniform illumination                    (prgb[R]>200 && prgb[G]>210 && prgb[B]>170 &&                     abs(prgb[R]-prgb[B])<=15 && prgb[R]>prgb[B]&& prgb[G]>prgb[B])//lateral illumination                    ) {                memcpy(pdst,prgb,3);            }            prgb+=3;            pdst+=3;        }    }    cvCopyImage(dst,_dst);    cvReleaseImage(&dst);}void cvSkinRG(IplImage* rgb,IplImage* gray){    assert(rgb->nChannels==3&&gray->nChannels==1);    const int R=2;    const int G=1;    const int B=0;    double Aup=-1.8423;    double Bup=1.5294;    double Cup=0.0422;    double Adown=-0.7279;    double Bdown=0.6066;    double Cdown=0.1766;    for (int h=0; h<rgb->height; h++)    {        unsigned char* pGray=(unsigned char*)gray->imageData+h*gray->widthStep;        unsigned char* pRGB=(unsigned char* )rgb->imageData+h*rgb->widthStep;        for (int w=0; w<rgb->width; w++)        {            int s=pRGB[R]+pRGB[G]+pRGB[B];            double r=(double)pRGB[R]/s;            double g=(double)pRGB[G]/s;            double Gup=Aup*r*r+Bup*r+Cup;            double Gdown=Adown*r*r+Bdown*r+Cdown;            double Wr=(r-0.33)*(r-0.33)+(g-0.33)*(g-0.33);            if (g<Gup && g>Gdown && Wr>0.004)            {                *pGray=255;            }            else            {                *pGray=0;            }            pGray++;            pRGB+=3;        }    }}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);}void cvSkinYCbCr(IplImage* img, IplImage* mask){    CvSize imageSize = cvSize(img->width, img->height);    IplImage *imgY = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);    IplImage *imgCr = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);    IplImage *imgCb = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);    IplImage *imgYCrCb = cvCreateImage(imageSize, img->depth, img->nChannels);    cvCvtColor(img,imgYCrCb,CV_BGR2YCrCb);    cvSplit(imgYCrCb, imgY, imgCr, imgCb, 0);    int y, cr, cb, l, x1, y1, value;    unsigned char *pY, *pCr, *pCb, *pMask;    pY = (unsigned char *)imgY->imageData;    pCr = (unsigned char *)imgCr->imageData;    pCb = (unsigned char *)imgCb->imageData;    pMask = (unsigned char *)mask->imageData;    cvSetZero(mask);    l = img->height * img->width;    for (int i = 0; i < l; i++){        y  = *pY;        cr = *pCr;        cb = *pCb;        cb -= 109;        cr -= 152                ;        x1 = (819*cr-614*cb)/32 + 51;        y1 = (819*cr+614*cb)/32 + 77;        x1 = x1*41/1024;        y1 = y1*73/1024;        value = x1*x1+y1*y1;        if(y<100)	(*pMask)=(value<700) ? 255:0;        else		(*pMask)=(value<850)? 255:0;        pY++;        pCr++;        pCb++;        pMask++;    }    cvReleaseImage(&imgY);    cvReleaseImage(&imgCr);    cvReleaseImage(&imgCb);    cvReleaseImage(&imgYCrCb);}void cvSkinYUV(IplImage* src,IplImage* dst){    IplImage* ycrcb=cvCreateImage(cvGetSize(src),8,3);    //IplImage* cr=cvCreateImage(cvGetSize(src),8,1);    //IplImage* cb=cvCreateImage(cvGetSize(src),8,1);    cvCvtColor(src,ycrcb,CV_BGR2YCrCb);    //cvSplit(ycrcb,0,cr,cb,0);    static const int Cb=2;    static const int Cr=1;    static const int Y=0;    //IplImage* dst=cvCreateImage(cvGetSize(_dst),8,3);    cvZero(dst);    for (int h=0; h<src->height; h++)    {        unsigned char* pycrcb=(unsigned char*)ycrcb->imageData+h*ycrcb->widthStep;        unsigned char* psrc=(unsigned char*)src->imageData+h*src->widthStep;        unsigned char* pdst=(unsigned char*)dst->imageData+h*dst->widthStep;        for (int w=0; w<src->width; w++)        {            if (pycrcb[Cr]>=133&&pycrcb[Cr]<=173&&pycrcb[Cb]>=77&&pycrcb[Cb]<=127)            {                memcpy(pdst,psrc,3);            }            pycrcb+=3;            psrc+=3;            pdst+=3;        }    }    //cvCopyImage(dst,_dst);    //cvReleaseImage(&dst);}void cvSkinHSV(IplImage* src,IplImage* dst){    IplImage* hsv=cvCreateImage(cvGetSize(src),8,3);    //IplImage* cr=cvCreateImage(cvGetSize(src),8,1);    //IplImage* cb=cvCreateImage(cvGetSize(src),8,1);    cvCvtColor(src,hsv,CV_BGR2HSV);    //cvSplit(ycrcb,0,cr,cb,0);    static const int V=2;    static const int S=1;    static const int H=0;    //IplImage* dst=cvCreateImage(cvGetSize(_dst),8,3);    cvZero(dst);    for (int h=0; h<src->height; h++)    {        unsigned char* phsv=(unsigned char*)hsv->imageData+h*hsv->widthStep;        unsigned char* psrc=(unsigned char*)src->imageData+h*src->widthStep;        unsigned char* pdst=(unsigned char*)dst->imageData+h*dst->widthStep;        for (int w=0; w<src->width; w++)        {            if (phsv[H]>=7&&phsv[H]<=29)            {                memcpy(pdst,psrc,3);            }            phsv+=3;            psrc+=3;            pdst+=3;        }    }    //cvCopyImage(dst,_dst);    //cvReleaseImage(&dst);}
下面是效果图:

测试图片:

下图的贴图依次对应上面的六种方法:






从上面的结果对比图中可以清晰看的,ycrcb+ostu的效果无疑是最好的。其次是rgb和yuv方法。这个图片效果之所以这么好是因为测试图片拍摄的时候背景为白色。然后,遗憾的是,当背景色不纯的时候,比如有红也有黑,效果就很不理想了。实验发现,当背景为纯色,且是白色或黑色时,效果最好。

参考:

http://blog.sina.com.cn/s/blog_9ce5a1b501017otq.html

http://blog.csdn.net/scyscyao/article/details/5468577

http://wenku.baidu.com/view/05c47e03bed5b9f3f90f1ce4.html

http://blog.csdn.net/onezeros/article/details/6136770

    --------------------------本掌纹是作者自己的,转载请注明作者yanzi1225627



  相关解决方案