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

 

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

分类: OpenCV图像处理
 
原文链接  http://blog.csdn.net/yanzi1225627/article/details/8600169

    六种方法分别是:基于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文件里增加如下代码:

 

  1. INCLUDEPATH += /usr/include/opencv  
  2.   
  3. LIBS += /usr/lib/libcv.so \  
  4. /usr/lib/libcvaux.so \  
  5. /usr/lib/libcxcore.so \  
  6. /usr/lib/libhighgui.so \  
  7. /usr/lib/libml.so  

请看源码:

 

 

  1. #include <iostream>  
  2. #include "cv.h"  
  3. #include "highgui.h"  
  4.   
  5.   
  6. void SkinRGB(IplImage* rgb,IplImage* _dst);  
  7. void cvSkinRG(IplImage* rgb,IplImage* gray);  
  8. void cvThresholdOtsu(IplImage* src, IplImage* dst);  
  9. void cvSkinOtsu(IplImage* src, IplImage* dst);  
  10. void cvSkinYCbCr(IplImage* img, IplImage* mask);  
  11. void cvSkinYUV(IplImage* src,IplImage* dst);  
  12. void cvSkinHSV(IplImage* src,IplImage* dst);  
  13.   
  14.   
  15.   
  16.   
  17.   
  18.   
  19. using namespace std;  
  20.   
  21. // skin region location using rgb limitation  
  22.   
  23.   
  24.   
  25. int main()  
  26. {  
  27.     IplImage *srcImg = cvLoadImage("/home/yan/download/testPalm4.jpg", 1);  
  28.     IplImage *dstRGB = cvCreateImage(cvGetSize(srcImg), 8, 3);  
  29.     IplImage *dstRG = cvCreateImage(cvGetSize(srcImg), 8, 1);  
  30.     IplImage* dst_crotsu=cvCreateImage(cvGetSize(srcImg),8,1);  
  31.     IplImage* dst_ycbcr=cvCreateImage(cvGetSize(srcImg),8,1);  
  32.     IplImage* dst_yuv=cvCreateImage(cvGetSize(srcImg),8,3);  
  33.     IplImage* dst_hsv=cvCreateImage(cvGetSize(srcImg),8,3);  
  34.   
  35.     SkinRGB(srcImg, dstRGB);  
  36.     cvSaveImage("/home/yan/download/1_dstRGB.jpg", dstRGB);  
  37.   
  38.     cvSkinRG(srcImg, dstRG);  
  39.     cvSaveImage("/home/yan/download/2_dstRG.jpg", dstRG);  
  40.   
  41.     cvSkinOtsu(srcImg, dst_crotsu);  
  42.     cvSaveImage("/home/yan/download/3_dst_crotsu.jpg", dst_crotsu);  
  43.   
  44.     cvSkinYCbCr(srcImg, dst_ycbcr);  
  45.     cvSaveImage("/home/yan/download/4_dst_ycbcr.jpg", dst_ycbcr);  
  46.   
  47.     cvSkinYUV(srcImg, dst_yuv);  
  48.     cvSaveImage("/home/yan/download/5_dst_yuv.jpg", dst_yuv);  
  49.   
  50.     cvSkinHSV(srcImg, dst_hsv);  
  51.     cvSaveImage("/home/yan/download/6_dst_hsv.jpg", dst_hsv);  
  52.   
  53.   
  54.     cvNamedWindow("srcImg", 1);  
  55.     cvShowImage("srcImg", srcImg);  
  56.   
  57.     cvNamedWindow("dstRGB", 1);  
  58.     cvShowImage("dstRGB", dstRGB);  
  59.   
  60.     cvNamedWindow("dstRG", 1);  
  61.     cvShowImage("dstRG", dstRG);  
  62.   
  63.     cvNamedWindow("dstcrotsu", 1);  
  64.     cvShowImage("dstcrotsu", dst_crotsu);  
  65.   
  66.     cvNamedWindow("dst_ycbcr", 1);  
  67.     cvShowImage("dst_ycbcr", dst_ycbcr);  
  68.   
  69.     cvNamedWindow("dst_yuv", 1);  
  70.     cvShowImage("dst_yuv", dst_yuv);  
  71.   
  72.     cvNamedWindow("dst_hsv", 1);  
  73.     cvShowImage("dst_hsv", dst_hsv);  
  74.     cvWaitKey(0);  
  75.     cout << "Hello World!" << endl;  
  76.     return 0;  
  77. }  
  78. void SkinRGB(IplImage* rgb,IplImage* _dst)  
  79. {  
  80.     cout<<"111"<<endl;  
  81.     assert(rgb->nChannels==3&& _dst->nChannels==3);  
  82.   
  83.     static const int R=2;  
  84.     static const int G=1;  
  85.     static const int B=0;  
  86.   
  87.     IplImage* dst=cvCreateImage(cvGetSize(_dst),8,3);  
  88.     cvZero(dst);  
  89.   
  90.     for (int h=0;h<rgb->height;h++) {  
  91.         unsigned char* prgb=(unsigned char*)rgb->imageData+h*rgb->widthStep;  
  92.         unsigned char* pdst=(unsigned char*)dst->imageData+h*dst->widthStep;  
  93.         for (int w=0;w<rgb->width;w++) {  
  94.             if ((prgb[R]>95 && prgb[G]>40 && prgb[B]>20 &&  
  95.                  prgb[R]-prgb[B]>15 && prgb[R]-prgb[G]>15/*&& 
  96.                      !(prgb[R]>170&&prgb[G]>170&&prgb[B]>170)*/)||//uniform illumination  
  97.                     (prgb[R]>200 && prgb[G]>210 && prgb[B]>170 &&  
  98.                      abs(prgb[R]-prgb[B])<=15 && prgb[R]>prgb[B]&& prgb[G]>prgb[B])//lateral illumination  
  99.                     ) {  
  100.                 memcpy(pdst,prgb,3);  
  101.             }  
  102.             prgb+=3;  
  103.             pdst+=3;  
  104.         }  
  105.     }  
  106.     cvCopyImage(dst,_dst);  
  107.     cvReleaseImage(&dst);  
  108. }  
  109.   
  110. void cvSkinRG(IplImage* rgb,IplImage* gray)  
  111. {  
  112.     assert(rgb->nChannels==3&&gray->nChannels==1);  
  113.   
  114.     const int R=2;  
  115.     const int G=1;  
  116.     const int B=0;  
  117.   
  118.     double Aup=-1.8423;  
  119.     double Bup=1.5294;  
  120.     double Cup=0.0422;  
  121.     double Adown=-0.7279;  
  122.     double Bdown=0.6066;  
  123.     double Cdown=0.1766;  
  124.     for (int h=0; h<rgb->height; h++)  
  125.     {  
  126.         unsigned char* pGray=(unsigned char*)gray->imageData+h*gray->widthStep;  
  127.         unsigned char* pRGB=(unsigned char* )rgb->imageData+h*rgb->widthStep;  
  128.         for (int w=0; w<rgb->width; w++)  
  129.         {  
  130.             int s=pRGB[R]+pRGB[G]+pRGB[B];  
  131.             double r=(double)pRGB[R]/s;  
  132.             double g=(double)pRGB[G]/s;  
  133.             double Gup=Aup*r*r+Bup*r+Cup;  
  134.             double Gdown=Adown*r*r+Bdown*r+Cdown;  
  135.             double Wr=(r-0.33)*(r-0.33)+(g-0.33)*(g-0.33);  
  136.             if (g<Gup && g>Gdown && Wr>0.004)  
  137.             {  
  138.                 *pGray=255;  
  139.             }  
  140.             else  
  141.             {  
  142.                 *pGray=0;  
  143.             }  
  144.             pGray++;  
  145.             pRGB+=3;  
  146.         }  
  147.     }  
  148.   
  149. }  
  150. void cvThresholdOtsu(IplImage* src, IplImage* dst)  
  151. {  
  152.     int height=src->height;  
  153.     int width=src->width;  
  154.   
  155.     //histogram  
  156.     float histogram[256]= {0};  
  157.     for(int i=0; i<height; i++)  
  158.     {  
  159.         unsigned char* p=(unsigned char*)src->imageData+src->widthStep*i;  
  160.         for(int j=0; j<width; j++)  
  161.         {  
  162.             histogram[*p++]++;  
  163.         }  
  164.     }  
  165.     //normalize histogram  
  166.     int size=height*width;  
  167.     for(int i=0; i<256; i++)  
  168.     {  
  169.         histogram[i]=histogram[i]/size;  
  170.     }  
  171.   
  172.     //average pixel value  
  173.     float avgValue=0;  
  174.     for(int i=0; i<256; i++)  
  175.     {  
  176.         avgValue+=i*histogram[i];  
  177.     }  
  178.   
  179.     int threshold;  
  180.     float maxVariance=0;  
  181.     float w=0,u=0;  
  182.     for(int i=0; i<256; i++)  
  183.     {  
  184.         w+=histogram[i];  
  185.         u+=i*histogram[i];  
  186.   
  187.         float t=avgValue*w-u;  
  188.         float variance=t*t/(w*(1-w));  
  189.         if(variance>maxVariance)  
  190.         {  
  191.             maxVariance=variance;  
  192.             threshold=i;  
  193.         }  
  194.     }  
  195.     cvThreshold(src,dst,threshold,255,CV_THRESH_BINARY);  
  196. }  
  197.   
  198. void cvSkinOtsu(IplImage* src, IplImage* dst)  
  199. {  
  200.     assert(dst->nChannels==1&& src->nChannels==3);  
  201.   
  202.     IplImage* ycrcb=cvCreateImage(cvGetSize(src),8,3);  
  203.     IplImage* cr=cvCreateImage(cvGetSize(src),8,1);  
  204.     cvCvtColor(src,ycrcb,CV_BGR2YCrCb);  
  205.     cvSplit(ycrcb,0,cr,0,0);  
  206.   
  207.     cvThresholdOtsu(cr,cr);  
  208.     cvCopyImage(cr,dst);  
  209.     cvReleaseImage(&cr);  
  210.     cvReleaseImage(&ycrcb);  
  211. }  
  212. void cvSkinYCbCr(IplImage* img, IplImage* mask)  
  213. {  
  214.     CvSize imageSize = cvSize(img->width, img->height);  
  215.     IplImage *imgY = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);  
  216.     IplImage *imgCr = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);  
  217.     IplImage *imgCb = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);  
  218.   
  219.   
  220.     IplImage *imgYCrCb = cvCreateImage(imageSize, img->depth, img->nChannels);  
  221.     cvCvtColor(img,imgYCrCb,CV_BGR2YCrCb);  
  222.     cvSplit(imgYCrCb, imgY, imgCr, imgCb, 0);  
  223.     int y, cr, cb, l, x1, y1, value;  
  224.     unsigned char *pY, *pCr, *pCb, *pMask;  
  225.   
  226.     pY = (unsigned char *)imgY->imageData;  
  227.     pCr = (unsigned char *)imgCr->imageData;  
  228.     pCb = (unsigned char *)imgCb->imageData;  
  229.     pMask = (unsigned char *)mask->imageData;  
  230.     cvSetZero(mask);  
  231.     l = img->height * img->width;  
  232.     for (int i = 0; i < l; i++){  
  233.         y  = *pY;  
  234.         cr = *pCr;  
  235.         cb = *pCb;  
  236.         cb -= 109;  
  237.         cr -= 152  
  238.                 ;  
  239.         x1 = (819*cr-614*cb)/32 + 51;  
  240.         y1 = (819*cr+614*cb)/32 + 77;  
  241.         x1 = x1*41/1024;  
  242.         y1 = y1*73/1024;  
  243.         value = x1*x1+y1*y1;  
  244.         if(y<100)    (*pMask)=(value<700) ? 255:0;  
  245.         else        (*pMask)=(value<850)? 255:0;  
  246.         pY++;  
  247.         pCr++;  
  248.         pCb++;  
  249.         pMask++;  
  250.     }  
  251.     cvReleaseImage(&imgY);  
  252.     cvReleaseImage(&imgCr);  
  253.     cvReleaseImage(&imgCb);  
  254.     cvReleaseImage(&imgYCrCb);  
  255. }  
  256.   
  257. void cvSkinYUV(IplImage* src,IplImage* dst)  
  258. {  
  259.     IplImage* ycrcb=cvCreateImage(cvGetSize(src),8,3);  
  260.     //IplImage* cr=cvCreateImage(cvGetSize(src),8,1);  
  261.     //IplImage* cb=cvCreateImage(cvGetSize(src),8,1);  
  262.     cvCvtColor(src,ycrcb,CV_BGR2YCrCb);  
  263.     //cvSplit(ycrcb,0,cr,cb,0);  
  264.   
  265.     static const int Cb=2;  
  266.     static const int Cr=1;  
  267.     static const int Y=0;  
  268.   
  269.     //IplImage* dst=cvCreateImage(cvGetSize(_dst),8,3);  
  270.     cvZero(dst);  
  271.   
  272.     for (int h=0; h<src->height; h++)  
  273.     {  
  274.         unsigned char* pycrcb=(unsigned char*)ycrcb->imageData+h*ycrcb->widthStep;  
  275.         unsigned char* psrc=(unsigned char*)src->imageData+h*src->widthStep;  
  276.         unsigned char* pdst=(unsigned char*)dst->imageData+h*dst->widthStep;  
  277.         for (int w=0; w<src->width; w++)  
  278.         {  
  279.             if (pycrcb[Cr]>=133&&pycrcb[Cr]<=173&&pycrcb[Cb]>=77&&pycrcb[Cb]<=127)  
  280.             {  
  281.                 memcpy(pdst,psrc,3);  
  282.             }  
  283.             pycrcb+=3;  
  284.             psrc+=3;  
  285.             pdst+=3;  
  286.         }  
  287.     }  
  288.     //cvCopyImage(dst,_dst);  
  289.     //cvReleaseImage(&dst);  
  290. }  
  291.   
  292. void cvSkinHSV(IplImage* src,IplImage* dst)  
  293. {  
  294.     IplImage* hsv=cvCreateImage(cvGetSize(src),8,3);  
  295.     //IplImage* cr=cvCreateImage(cvGetSize(src),8,1);  
  296.     //IplImage* cb=cvCreateImage(cvGetSize(src),8,1);  
  297.     cvCvtColor(src,hsv,CV_BGR2HSV);  
  298.     //cvSplit(ycrcb,0,cr,cb,0);  
  299.   
  300.     static const int V=2;  
  301.     static const int S=1;  
  302.     static const int H=0;  
  303.   
  304.     //IplImage* dst=cvCreateImage(cvGetSize(_dst),8,3);  
  305.     cvZero(dst);  
  306.   
  307.     for (int h=0; h<src->height; h++)  
  308.     {  
  309.         unsigned char* phsv=(unsigned char*)hsv->imageData+h*hsv->widthStep;  
  310.         unsigned char* psrc=(unsigned char*)src->imageData+h*src->widthStep;  
  311.         unsigned char* pdst=(unsigned char*)dst->imageData+h*dst->widthStep;  
  312.         for (int w=0; w<src->width; w++)  
  313.         {  
  314.             if (phsv[H]>=7&&phsv[H]<=29)  
  315.             {  
  316.                 memcpy(pdst,psrc,3);  
  317.             }  
  318.             phsv+=3;  
  319.             psrc+=3;  
  320.             pdst+=3;  
  321.         }  
  322.     }  
  323.     //cvCopyImage(dst,_dst);  
  324.     //cvReleaseImage(&dst);  
  325. }  
下面是效果图:

 

测试图片:

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

 

 

 

 

从上面的结果对比图中可以清晰看的,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

 

posted on 2015-11-17 19:01  qingchen1984  阅读(650)  评论(2编辑  收藏  举报

导航