Android实现基于肤色的皮肤检测

移动开发 Android
以前,一直没明白yuv和YcbCr之间的差异,想必有些朋友也会有同样的疑惑。所以,我看完之后就记载下来了。

在android上实现基于肤色的皮肤检测的几个技术要点:

(1)android上使用相机预览,包括相机api的使用和surfaceview的应用。

(2)android上相机使用的色彩空间NV12.

(3)NV12是YCrCb的色彩空间,了解YCrCb色彩空间。YCrCb和YUV之间的转换。

yuv色彩模型来源于rgb模型,该模型的特点是将亮度和色度分离开,从而适合于图像处理领域。YCbCr模型来源于yuv模型.

(4)YCrCb色彩空间表示的人类肤色的特征。这个特征是133≤Cr≤173,77≤Cb≤127.实验表明Cr在[140,160]区间是符合黄种人的肤色。

YUV和RGB的转换:

★这里是不是不是yuv而是Y Cb Cr???★

 Y = 0.299 R + 0.587 G + 0.114 B

U = -0.1687 R - 0.3313 G + 0.5 B + 128

V = 0.5 R - 0.4187 G - 0.0813 B + 128

 R = Y + 1.402 (V-128)

G = Y - 0.34414 (U-128) - 0.71414 (V-128)

B = Y + 1.772 (U-128)

 以前,一直没明白yuv和YcbCr之间的差异,想必有些朋友也会有同样的疑惑。

所以,我看完之后就记载下来了。

一、和rgb之间换算公式的差异

yuv<-->rgb

Y'= 0.299*R' + 0.587*G' + 0.114*B'

U'= -0.147*R' - 0.289*G' + 0.436*B' = 0.492*(B'- Y')

V'= 0.615*R' - 0.515*G' - 0.100*B' = 0.877*(R'- Y')

R' = Y' + 1.140*V'

G' = Y' - 0.394*U' - 0.581*V'

B' = Y' + 2.032*U'

yCbCr<-->rgb

Y’ = 0.257*R' + 0.504*G' + 0.098*B' + 16

Cb' = -0.148*R' - 0.291*G' + 0.439*B' + 128

Cr' = 0.439*R' - 0.368*G' - 0.071*B' + 128

R' = 1.164*(Y’-16) + 1.596*(Cr'-128)

G' = 1.164*(Y’-16) - 0.813*(Cr'-128) - 0.392*(Cb'-128)

B' = 1.164*(Y’-16) + 2.017*(Cb'-128)

Note: 上面各个符号都带了一撇,表示该符号在原值基础上进行了gamma correction

源代码如下:

  1. 001 package com.example.hearrate; 
  2. 002   
  3. 003 import java.io.FileNotFoundException; 
  4. 004 import java.io.FileOutputStream; 
  5. 005 import java.io.IOException; 
  6. 006 import java.util.List; 
  7. 007   
  8. 008 import android.graphics.Bitmap; 
  9. 009 import android.graphics.BitmapFactory; 
  10. 010 import android.graphics.Canvas; 
  11. 011 import android.graphics.Color; 
  12. 012 import android.graphics.Paint; 
  13. 013 import android.graphics.PixelFormat; 
  14. 014 import android.graphics.PorterDuffXfermode; 
  15. 015 import android.graphics.Rect; 
  16. 016 import android.hardware.Camera; 
  17. 017 import android.hardware.Camera.CameraInfo; 
  18. 018 import android.hardware.Camera.Size; 
  19. 019 import android.os.AsyncTask; 
  20. 020 import android.os.Build; 
  21. 021 import android.os.Bundle; 
  22. 022 import android.annotation.SuppressLint; 
  23. 023 import android.app.Activity; 
  24. 024 import android.content.res.Configuration; 
  25. 025 import android.util.Log; 
  26. 026 import android.view.Menu; 
  27. 027 import android.view.SurfaceHolder; 
  28. 028 import android.view.SurfaceView; 
  29. 029 import android.graphics.PorterDuff; 
  30. 030 import android.graphics.PorterDuff.Mode; 
  31. 031 public class MainActivity extends Activity implements  SurfaceHolder.Callback ,Camera.PreviewCallback{ 
  32. 032 SurfaceHolder mHolder; 
  33. 033 SurfaceView mView; 
  34. 034 SurfaceView mLayer; 
  35. 035 SurfaceHolder mLayerHolder; 
  36. 036 private Camera mCamera =null
  37. 037 private boolean bIfPreview =false
  38. 038 private int mPreviewHeight; 
  39. 039 private int mPreviewWidth; 
  40. 040 private Canvas canvas; 
  41. 041 private Paint paint; 
  42. 042 private int facex=0,facey=0
  43. 043 private boolean bprocessing=false
  44. 044 private int[] RGBData; 
  45. 045 private byte[] mYUVData;   
  46. 046 private boolean bfront=false
  47. 047     @Override 
  48. 048     protected void onCreate(Bundle savedInstanceState) { 
  49. 049         super.onCreate(savedInstanceState); 
  50. 050         setContentView(R.layout.activity_main); 
  51. 051         mView=(SurfaceView)findViewById(R.id.layer0); 
  52. 052         paint = new Paint(); 
  53. 053         paint.setColor(Color.RED); 
  54. 054         paint.setAntiAlias(true); 
  55. 055   
  56. 056         mPreviewWidth=320
  57. 057         mPreviewHeight=400
  58. 058         mHolder=mView.getHolder(); 
  59. 059         mHolder.addCallback(this); 
  60. 060         mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
  61. 061           
  62. 062         mLayer=(SurfaceView)findViewById(R.id.layer1); 
  63. 063         mLayer.setZOrderOnTop(true); 
  64. 064         //mLayer.setEGLConfigChooser(8, 8, 8, 8, 16, 0); 
  65. 065       
  66. 066           
  67. 067         mLayerHolder=mLayer.getHolder(); 
  68. 068         mLayerHolder.setFormat(PixelFormat.TRANSPARENT); 
  69. 069         mLayerHolder.addCallback(this); 
  70. 070         mLayerHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
  71. 071     } 
  72. 072 void drawlayer1() 
  73. 073 { 
  74. 074     canvas=mLayerHolder.lockCanvas(); 
  75. 075     // canvas.drawRGB(0, 0, 0); 
  76. 076     // canvas.save(); 
  77. 077      Bitmap bmp=BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); 
  78. 078      //绘制 
  79. 079     // canvas.drawBitmap(bmp, null, paint); 
  80. 080      drawImage(canvas,bmp,facex,facex,72,72,0,0); 
  81. 081      canvas.restore(); 
  82. 082      bmp=null
  83. 083      mLayerHolder.unlockCanvasAndPost(canvas); 
  84. 084 } 
  85. 085     @Override 
  86. 086     public boolean onCreateOptionsMenu(Menu menu) { 
  87. 087         // Inflate the menu; this adds items to the action bar if it is present. 
  88. 088         getMenuInflater().inflate(R.menu.activity_main, menu); 
  89. 089         return true
  90. 090     } 
  91. 091   
  92. 092     @Override 
  93. 093     public void surfaceChanged(SurfaceHolder arg0, int arg1, int width, int height) { 
  94. 094         // TODO Auto-generated method stub 
  95. 095         mPreviewWidth=width; 
  96. 096         mPreviewHeight=height; 
  97. 097         if(arg0.equals(mLayerHolder)) 
  98. 098         { 
  99. 099             //drawlayer1(); 
  100. 100             return
  101. 101         } 
  102. 102           
  103. 103         RGBData= new int[mPreviewHeight* mPreviewWidth]; 
  104. 104         mYUVData= new byte[mPreviewHeight* mPreviewWidth+(mPreviewHeight/2)* (mPreviewWidth/2)+(mPreviewHeight/2)* (mPreviewWidth/2)]; 
  105. 105             initCamera(); 
  106. 106     } 
  107. 107   
  108. 108     @SuppressLint("NewApi"
  109. 109     @Override 
  110. 110     public void surfaceCreated(SurfaceHolder arg0) { 
  111. 111         // TODO Auto-generated method stub 
  112. 112         // TODO Auto-generated method stub 
  113. 113         if(arg0.equals(mLayerHolder)) 
  114. 114             return
  115. 115 if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.GINGERBREAD) 
  116. 116 { 
  117. 117 for(int i=0;i<Camera.getNumberOfCameras();i++) 
  118. 118 { 
  119. 119 CameraInfo info=new CameraInfo(); 
  120. 120 Camera.getCameraInfo(i, info); 
  121. 121 if(info.facing==CameraInfo.CAMERA_FACING_FRONT) 
  122. 122 { 
  123. 123     //mCamera = Camera.open(i); 
  124. 124     //bfront=true; 
  125. 125 } 
  126. 126 } 
  127. 127 } 
  128. 128 if(mCamera==null
  129. 129 { 
  130. 130         mCamera = Camera.open();// 开启摄像头(2.3版本后支持多摄像头,需传入参数) 
  131. 131         bfront=false
  132. 132 } 
  133. 133          try 
  134. 134         { 
  135. 135                
  136. 136         mCamera.setPreviewDisplay(mHolder);//set the surface to be used for live preview 
  137. 137           
  138. 138         Log("成功打开"); 
  139. 139         } catch (Exception ex) 
  140. 140         { 
  141. 141          if(null != mCamera) 
  142. 142         { 
  143. 143         mCamera.release(); 
  144. 144         mCamera = null
  145. 145         } 
  146. 146          canvas=mHolder.lockCanvas(); 
  147. 147          canvas.drawRGB(000); 
  148. 148          canvas.save(); 
  149. 149          Bitmap bmp=BitmapFactory.decodeResource(getResources(), R.drawable.bg); 
  150. 150          //绘制 
  151. 151         // canvas.drawBitmap(bmp, null, paint); 
  152. 152          drawImage(canvas,bmp,0,0,mPreviewWidth,mPreviewHeight,0,0); 
  153. 153          canvas.restore(); 
  154. 154          bmp=null
  155. 155 mHolder.unlockCanvasAndPost(canvas); 
  156. 156          Log("打开失败"+ex.getMessage()); 
  157. 157         } 
  158. 158     } 
  159. 159 //  GameView.drawImage(canvas, mBitDestTop, miDTX, mBitQQ.getHeight(), mBitDestTop.getWidth(), mBitDestTop.getHeight()/2, 0, 0); 
  160. 160   public static void drawImage(Canvas canvas, Bitmap blt, int x, int y, int w, int h, int bx, int by) 
  161. 161   {                                                        //x,y表示绘画的起点, 
  162. 162       Rect src = new Rect();// 图片 
  163. 163       Rect dst = new Rect();// 屏幕位置及尺寸 
  164. 164       //src 这个是表示绘画图片的大小 
  165. 165       src.left = bx;   //0,0  
  166. 166       src.top = by; 
  167. 167       src.right = bx + w;// mBitDestTop.getWidth();,这个是桌面图的宽度, 
  168. 168       src.bottom = by + h;//mBitDestTop.getHeight()/2;// 这个是桌面图的高度的一半 
  169. 169       // 下面的 dst 是表示 绘画这个图片的位置 
  170. 170       dst.left = x;    //miDTX,//这个是可以改变的,也就是绘图的起点X位置 
  171. 171       dst.top = y;    //mBitQQ.getHeight();//这个是QQ图片的高度。 也就相当于 桌面图片绘画起点的Y坐标 
  172. 172       dst.right = x + w;    //miDTX + mBitDestTop.getWidth();// 表示需绘画的图片的右上角 
  173. 173       dst.bottom = y + h;    // mBitQQ.getHeight() + mBitDestTop.getHeight();//表示需绘画的图片的右下角 
  174. 174       canvas.drawBitmap(blt, src, dst, null);//这个方法  第一个参数是图片原来的大小,第二个参数是 绘画该图片需显示多少。也就是说你想绘画该图片的某一些地方,而不是全部图片,第三个参数表示该图片绘画的位置 
  175. 175         
  176. 176       src = null
  177. 177       dst = null
  178. 178   } 
  179. 179     @Override 
  180. 180     public void surfaceDestroyed(SurfaceHolder arg0) { 
  181. 181         // TODO Auto-generated method stub 
  182. 182         if(arg0.equals(mLayerHolder)) 
  183. 183             return
  184. 184          if(null != mCamera) 
  185. 185          { 
  186. 186          mCamera.setPreviewCallback(null); //!!这个必须在前,不然退出出错 
  187. 187          mCamera.stopPreview(); 
  188. 188          bIfPreview = false
  189. 189          mCamera.release(); 
  190. 190          mCamera = null
  191. 191          } 
  192. 192     } 
  193. 193   
  194. 194   
  195. 195     @Override 
  196. 196     public void onPreviewFrame(byte[] data, Camera camera) { 
  197. 197         // TODO Auto-generated method stub 
  198. 198         Log("going into onPreviewFrame"+data.length); 
  199. 199           
  200. 200          int imageWidth = camera.getParameters().getPreviewSize().width  ; 
  201. 201             int imageHeight =camera.getParameters().getPreviewSize().height ; 
  202. 202           //  int RGBData[] = new int[imageWidth* imageHeight]; 
  203. 203            if(!bprocessing) 
  204. 204            { 
  205. 205             System.arraycopy(data, 0, mYUVData, 0, data.length); 
  206. 206               
  207. 207             new ProcessTask().execute(mYUVData); 
  208. 208            } 
  209. 209           //  decodeYUV420SP(RGBData, mYUVData, imageWidth, imageHeight); 
  210. 210   
  211. 211          //   Bitmap bitmap = Bitmap.createBitmap(imageWidth, imageHeight, Bitmap.Config.ARGB_8888); 
  212. 212          //   bitmap.setPixels(RGBData, 0, imageWidth, 0, 0, imageWidth, imageHeight); 
  213. 213           //  FileOutputStream outStream = null; 
  214. 214            // ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
  215. 215               
  216. 216            // outStream = new FileOutputStream(String.format("/sdcard/%d.bmp", System.currentTimeMillis())); 
  217. 217            // outStream.write(bitmap.); 
  218. 218           //  outStream.close(); 
  219. 219             /* 
  220. 220             FileOutputStream out; 
  221. 221             try { 
  222. 222                 String path=String.format("/mnt/sdcard/%d.png", System.currentTimeMillis()); 
  223. 223                 out = new FileOutputStream(path); 
  224. 224                 bitmap.compress(Bitmap.CompressFormat.PNG, 90, out); 
  225. 225                 out.close(); 
  226. 226             } catch (FileNotFoundException e) { 
  227. 227                 // TODO Auto-generated catch block 
  228. 228                 e.printStackTrace(); 
  229. 229             } catch (IOException e) { 
  230. 230                 // TODO Auto-generated catch block 
  231. 231                 e.printStackTrace(); 
  232. 232             } 
  233. 233     */ 
  234. 234          //mYUV420sp = data; // 获取原生的YUV420SP数据 
  235. 235     //int mInitPos= mPreviewWidth*mPreviewHeight; 
  236. 236   
  237. 237     //if(mYUV420sp.length<=mInitPos+1) 
  238. 238     //  return; 
  239. 239     //byte cr=0; 
  240. 240     //int framesize=mInitPos; 
  241. 241     //int uvp=0; 
  242. 242     //int i,j,u=0,v=0,yp = 0; 
  243. 243     //int uvp=framesize+(i>>1)*w+j; 
  244. 244 //  canvas=mLayerHolder.lockCanvas(); 
  245. 245     // canvas.drawRGB(0, 0, 0); 
  246. 246 //  canvas.save(); 
  247. 247     // Bitmap bmp=BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); 
  248. 248      //绘制 
  249. 249     // canvas.drawBitmap(bmp, null, paint); 
  250. 250     // drawImage(canvas,bmp,facex,facex,72,72,0,0); 
  251. 251       
  252. 252       
  253. 253     // bmp=null; 
  254. 254     //  int RGBData[] = new int[mPreviewHeight* mPreviewWidth]; 
  255. 255    //   byte[] mYUVData = new byte[mYUV420sp.length];    
  256. 256    //   System.arraycopy(mYUV420sp, 0, mYUVData, 0, mYUV420sp.length); 
  257. 257 /* 
  258. 258     for( i=0,yp = 0;i<mPreviewHeight;i++) 
  259. 259     { 
  260. 260         uvp=framesize+(i>>1)*mPreviewWidth; 
  261. 261         for( j=0;j<mPreviewWidth;j++) 
  262. 262         { 
  263. 263             int y = (0xff & ((int) mYUVData[yp])) - 16; 
  264. 264             if (y < 0) y = 0; 
  265. 265               if((j&1)==0) 
  266. 266                       { 
  267. 267                 v = (0xff & mYUVData[uvp++]) - 128; 
  268. 268                 u = (0xff & mYUVData[uvp++]) - 128; 
  269. 269                      } 
  270. 270              // if(133≤Cr≤173,77≤Cb≤127 
  271. 271              if(v>133&&v<173) 
  272. 272                 canvas.drawPoint(j, i, paint); 
  273. 273                
  274. 274              int y1192 = 1192 * y; 
  275. 275   
  276. 276             int r = (y1192 + 1634 * v); 
  277. 277   
  278. 278             int g = (y1192 - 833 * v - 400 * u); 
  279. 279   
  280. 280             int b = (y1192 + 2066 * u); 
  281. 281   
  282. 282             if (r < 0) r = 0; else if (r > 262143) r = 262143; 
  283. 283   
  284. 284         if (g < 0) g = 0; else if (g > 262143) g = 262143; 
  285. 285   
  286. 286             if (b < 0) b = 0; else if (b > 262143) b = 262143; 
  287. 287         //  int rgb=0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff); 
  288. 288               
  289. 289             //r=(rgb&0x00ff0000)>>4; 
  290. 290         //  g=(rgb&0x0000ff00)>>2; 
  291. 291         //  b=(rgb&0x000000ff); 
  292. 292           //    if(r>200&&g>200&&b>200) 
  293. 293            //     canvas.drawPoint(j, i, paint); 
  294. 294             //  rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff); 
  295. 295         } 
  296. 296           
  297. 297           
  298. 298     } 
  299. 299       
  300. 300   
  301. 301      canvas.restore(); 
  302. 302      mLayerHolder.unlockCanvasAndPost(canvas); 
  303. 303      */ 
  304. 304 /* 
  305. 305  * framesize=w*h; 
  306. 306  * yp=0; 
  307. 307  * for (int i=0;i<h;i++) 
  308. 308  * { 
  309. 309  *     uvp=framesize+(i>>1)*w; 
  310. 310  *  for(int j=0;j<w;j++,yp++) 
  311. 311  *  { 
  312. 312  *  int y = (0xff & ((int) yuv420sp[yp])) - 16; 
  313. 313  *     if(j&1==0) 
  314. 314  *     { 
  315. 315  *       v = (0xff & yuv420sp[uvp++]) - 128; 
  316. 316   
  317. 317   u = (0xff & yuv420sp[uvp++]) - 128; 
  318. 318  *     } 
  319. 319  *     
  320. 320  *     
  321. 321  *  } 
  322. 322  * } 
  323. 323  * 
  324. 324  * 
  325. 325  * */ 
  326. 326     } 
  327. 327     public void drawdetect() 
  328. 328     { 
  329. 329         canvas=mLayerHolder.lockCanvas(); 
  330. 330         
  331. 331         if(canvas==null
  332. 332             return
  333. 333         canvas.drawColor(Color.TRANSPARENT);  
  334. 334         Paint p = new Paint();  
  335. 335         //清屏   
  336. 336          p.setXfermode(new PorterDuffXfermode(Mode.CLEAR));  
  337. 337         canvas.drawPaint(p);  
  338. 338         p.setXfermode(new PorterDuffXfermode(Mode.SRC));  
  339. 339         canvas.save(); 
  340. 340         canvas.drawBitmap(RGBData, 0, mPreviewWidth, 00, mPreviewWidth, mPreviewHeight, true, p); 
  341. 341           
  342. 342          canvas.restore(); 
  343. 343          mLayerHolder.unlockCanvasAndPost(canvas); 
  344. 344     } 
  345. 345     public void detectwhite(byte[] yuv420sp, int width, int height) 
  346. 346     { 
  347. 347         //检测所有白色 
  348. 348         final int frameSize = width * height; 
  349. 349   
  350. 350         for (int j = 0, yp = 0; j < height; j++) { 
  351. 351         int uvp = frameSize + (j >> 1) * width, u = 0, v = 0
  352. 352         for (int i = 0; i < width; i++, yp++) { 
  353. 353             int y = (0xff & ((int) yuv420sp[yp])); 
  354. 354             if (y < 0) y = 0
  355. 355             if ((i & 1) == 0) { 
  356. 356                 v = (0xff & yuv420sp[uvp++]);; 
  357. 357                 u = (0xff & yuv420sp[uvp++]); 
  358. 358             } 
  359. 359             ///133≤Cr≤173,77≤Cb≤127 
  360. 360 if(y>250
  361. 361 { 
  362. 362     RGBData[yp]=Color.RED; 
  363. 363     // canvas.drawPoint(i, j, paint); 
  364. 364     }else 
  365. 365     { 
  366. 366         RGBData[yp]=Color.TRANSPARENT; 
  367. 367     } 
  368. 368   
  369. 369         } 
  370. 370           
  371. 371     } 
  372. 372   
  373. 373     } 
  374. 374     public void detectface(byte[] yuv420sp, int width, int height) 
  375. 375     { 
  376. 376           
  377. 377         final int frameSize = width * height; 
  378. 378   
  379. 379         for (int j = 0, yp = 0; j < height; j++) { 
  380. 380         int uvp = frameSize + (j >> 1) * width, u = 0, v = 0
  381. 381         for (int i = 0; i < width; i++, yp++) { 
  382. 382       
  383. 383             if ((i & 1) == 0) { 
  384. 384                 v = (0xff & yuv420sp[uvp++]);; 
  385. 385                 u = (0xff & yuv420sp[uvp++]); 
  386. 386             } 
  387. 387             ///133≤Cr≤173,77≤Cb≤127 
  388. 388 if((v)>133&&(v)<160&&(u>77)&&(u<127)) 
  389. 389 { 
  390. 390     RGBData[yp]=Color.RED; 
  391. 391     // canvas.drawPoint(i, j, paint); 
  392. 392     }else 
  393. 393     { 
  394. 394         RGBData[yp]=Color.TRANSPARENT; 
  395. 395     } 
  396. 396   
  397. 397         } 
  398. 398           
  399. 399     } 
  400. 400   
  401. 401     } 
  402. 402      public void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width, int height) { 
  403. 403         final int frameSize = width * height; 
  404. 404         canvas=mLayerHolder.lockCanvas(); 
  405. 405         Paint paint1 = new Paint();  
  406. 406         paint1.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));  
  407. 407         canvas.drawPaint(paint1); 
  408. 408         canvas.save(); 
  409. 409         for (int j = 0, yp = 0; j < height; j++) { 
  410. 410         int uvp = frameSize + (j >> 1) * width, u = 0, v = 0
  411. 411         for (int i = 0; i < width; i++, yp++) { 
  412. 412             int y = (0xff & ((int) yuv420sp[yp])) - 16
  413. 413             if (y < 0) y = 0
  414. 414             if ((i & 1) == 0) { 
  415. 415                 v = (0xff & yuv420sp[uvp++]) - 128
  416. 416                 u = (0xff & yuv420sp[uvp++]) - 128
  417. 417             } 
  418. 418             ///133≤Cr≤173,77≤Cb≤127 
  419. 419 if((v)>133&&(v)<160&&(u>77)&&(u<127)) 
  420. 420 { 
  421. 421      canvas.drawPoint(i, j, paint); 
  422. 422     } 
  423. 423 /* 
  424. 424  * 这个是yuv转RGB的处理  
  425. 425  *   */ 
  426. 426             int y1192 = 1192 * y; 
  427. 427             int r = (y1192 + 1634 * v); 
  428. 428             int g = (y1192 - 833 * v - 400 * u); 
  429. 429             int b = (y1192 + 2066 * u); 
  430. 430   
  431. 431             if (r < 0) r = 0else if (r > 262143) r = 262143
  432. 432             if (g < 0) g = 0else if (g > 262143) g = 262143
  433. 433             if (b < 0) b = 0else if (b > 262143) b = 262143
  434. 434   
  435. 435             rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff); 
  436. 436               
  437. 437              r = (rgb[yp] >> 16)&0xff
  438. 438                   g = (rgb[yp] >> 8) & 0xff
  439. 439                    b = rgb[yp] & 0xff
  440. 440                  //  if(r==255&&g==255&&b==255) 
  441. 441                   // canvas.drawPoint(i, j, paint); 
  442. 442   
  443. 443       
  444. 444         } 
  445. 445           
  446. 446     } 
  447. 447      canvas.restore(); 
  448. 448      mLayerHolder.unlockCanvasAndPost(canvas); 
  449. 449 } 
  450. 450   
  451. 451   
  452. 452     private void initCamera() 
  453. 453     { 
  454. 454         if (bIfPreview) 
  455. 455         { 
  456. 456             mCamera.stopPreview(); 
  457. 457         } 
  458. 458         if(null != mCamera) 
  459. 459         { 
  460. 460             try
  461. 461                 Camera.Parameters parameters = mCamera.getParameters(); 
  462. 462                 // parameters.setFlashMode("off"); // 无闪光灯 
  463. 463                  parameters.setPictureFormat(PixelFormat.JPEG); //Sets the image format for picture 设定相片格式为JPEG,默认为NV21 
  464. 464                 parameters.setPreviewFormat(PixelFormat.YCbCr_420_SP); //Sets the image format for preview picture,默认为NV21 
  465. 465                   
  466. 466                  mCamera.setPreviewCallback(this); 
  467. 467                  // 【调试】获取caera支持的PictrueSize,看看能否设置?? 
  468. 468                 List pictureSizes = mCamera.getParameters().getSupportedPictureSizes(); 
  469. 469                  List previewSizes = mCamera.getParameters().getSupportedPreviewSizes(); 
  470. 470                  List previewFormats = mCamera.getParameters().getSupportedPreviewFormats(); 
  471. 471                 List previewFrameRates = mCamera.getParameters().getSupportedPreviewFrameRates(); 
  472. 472                   
  473. 473                   Size psize = null
  474. 474                  for (int i = 0; i < pictureSizes.size(); i++) 
  475. 475                  { 
  476. 476                  psize = (Size) pictureSizes.get(i); 
  477. 477                   
  478. 478                  } 
  479. 479                   for (int i = 0; i < previewSizes.size(); i++) 
  480. 480                  { 
  481. 481                  psize = (Size) previewSizes.get(i); 
  482. 482                   
  483. 483                   } 
  484. 484                  Integer pf = null
  485. 485                  for (int i = 0; i < previewFormats.size(); i++) 
  486. 486                  { 
  487. 487                 pf = (Integer) previewFormats.get(i); 
  488. 488               
  489. 489                  } 
  490. 490                   
  491. 491                 // 设置拍照和预览图片大小 
  492. 492                  parameters.setPictureSize(640480); //指定拍照图片的大小 
  493. 493                 parameters.setPreviewSize(mPreviewWidth, mPreviewHeight); // 指定preview的大小 
  494. 494                  //这两个属性 如果这两个属性设置的和真实手机的不一样时,就会报错 
  495. 495                 if(bfront) 
  496. 496                 { 
  497. 497                  parameters.set("orientation""landscape"); // 
  498. 498                  parameters.set("rotation"0); // 镜头角度转90度(默认摄像头是横拍) 
  499. 499                     mCamera.setDisplayOrientation(0); // 在2.2以上可以使用 
  500. 500                 } 
  501. 501                 // 横竖屏镜头自动调整 
  502. 502             /*  if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) 
  503. 503                  { 
  504. 504                  parameters.set("orientation", "portrait"); // 
  505. 505                  parameters.set("rotation", 90); // 镜头角度转90度(默认摄像头是横拍) 
  506. 506                 mCamera.setDisplayOrientation(90); // 在2.2以上可以使用 
  507. 507                  } else// 如果是横屏 
  508. 508              { 
  509. 509                  parameters.set("orientation", "landscape"); // 
  510. 510                 mCamera.setDisplayOrientation(0); // 在2.2以上可以使用 
  511. 511              } 
  512. 512               */ 
  513. 513                   //添加对视频流处理函数 
  514. 514                 // 设定配置参数并开启预览 
  515. 515                  mCamera.setParameters(parameters); // 将Camera.Parameters设定予Camera 
  516. 516                  mCamera.startPreview(); // 打开预览画面 
  517. 517                  bIfPreview = true
  518. 518                  // 【调试】设置后的图片大小和预览大小以及帧率 
  519. 519                  Camera.Size csize = mCamera.getParameters().getPreviewSize(); 
  520. 520                  mPreviewHeight = csize.height; // 
  521. 521                 mPreviewWidth = csize.width; 
  522. 522                    
  523. 523                  csize = mCamera.getParameters().getPictureSize(); 
  524. 524                   
  525. 525                   
  526. 526             }catch(Exception e) 
  527. 527             { 
  528. 528                 Log(e.getMessage()); 
  529. 529             } 
  530. 530               
  531. 531         } 
  532. 532     } 
  533. 533     void Log(String msg) 
  534. 534     { 
  535. 535         System.out.println("LOG:"+msg); 
  536. 536     } 
  537. 537     int[] g_v_table,g_u_table,y_table; 
  538. 538     int[][] r_yv_table,b_yu_table; 
  539. 539     int inited = 0
  540. 540        
  541. 541   
  542. 542     void initTable() 
  543. 543     { 
  544. 544         g_v_table=new int[256]; 
  545. 545         g_u_table=new int[256]; 
  546. 546         y_table=new int[256]; 
  547. 547         r_yv_table=new int[256][256]; 
  548. 548         b_yu_table=new int[256][256]; 
  549. 549         if (inited == 0
  550. 550         { 
  551. 551             inited = 1
  552. 552             int m = 0,n=0
  553. 553             for (; m < 256; m++) 
  554. 554             { 
  555. 555                 g_v_table[m] = 833 * (m - 128); 
  556. 556                 g_u_table[m] = 400 * (m - 128); 
  557. 557                 y_table[m] = 1192 * (m - 16); 
  558. 558             } 
  559. 559             int temp = 0
  560. 560             for (m = 0; m < 256; m++) 
  561. 561                 for (n = 0; n < 256; n++) 
  562. 562                 { 
  563. 563                     temp = 1192 * (m - 16) + 1634 * (n - 128); 
  564. 564                     if (temp < 0) temp = 0else if (temp > 262143) temp = 262143
  565. 565                     r_yv_table[m][n] = temp; 
  566. 566        
  567. 567                     temp = 1192 * (m - 16) + 2066 * (n - 128); 
  568. 568                     if (temp < 0) temp = 0else if (temp > 262143) temp = 262143
  569. 569                     b_yu_table[m][n] = temp; 
  570. 570                 } 
  571. 571         } 
  572. 572     } 
  573. 573     public class ProcessTask extends AsyncTask<byte[], Void, Void> 
  574. 574     { 
  575. 575   
  576. 576         @Override 
  577. 577         protected void onPostExecute(Void result) { 
  578. 578             // TODO Auto-generated method stub 
  579. 579             super.onPostExecute(result); 
  580. 580             drawdetect(); 
  581. 581             bprocessing=false
  582. 582         } 
  583. 583   
  584. 584         @Override 
  585. 585         protected void onPreExecute() { 
  586. 586             // TODO Auto-generated method stub 
  587. 587             super.onPreExecute(); 
  588. 588             if(bprocessing) 
  589. 589                 this.cancel(true); 
  590. 590           
  591. 591         } 
  592. 592   
  593. 593         @Override 
  594. 594         protected Void doInBackground(byte[]... params) { 
  595. 595             // TODO Auto-generated method stub 
  596. 596             bprocessing=true
  597. 597             byte[] data=    params[0]; 
  598.                   
  599.                 //皮肤检测 
  600.                 detectface(data,mPreviewWidth, mPreviewHeight); 
  601.            //白色检测 
  602.                 //detectwhite(data,mPreviewWidth, mPreviewHeight); 
  603.           //  publishProgress(null); 
  604.                 return null
  605.             } 
  606.               
  607.         } 
  608.     } 

以下是layout

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  2.         xmlns:tools="http://schemas.android.com/tools" 
  3.         android:layout_width="match_parent" 
  4.         android:layout_height="match_parent" 
  5.         tools:context=".MainActivity" >   
  6.                 <FrameLayout 
  7.                     android:layout_width="match_parent" 
  8.                     android:layout_height="match_parent" > 
  9.                 <SurfaceView 
  10.             android:id="@+id/layer0" 
  11.             android:layout_width="match_parent" 
  12.             android:layout_height="match_parent" 
  13.             /> 
  14.       </FrameLayout>      
  15.             <FrameLayout 
  16.               android:layout_width="match_parent" 
  17.               android:layout_height="match_parent" > 
  18.                 <SurfaceView 
  19.             android:id="@+id/layer1" 
  20.             android:layout_width="match_parent" 
  21.             android:layout_height="match_parent" 
  22.             /> 
  23.       </FrameLayout>        
  24.     </RelativeLayout> 

以下是manifest

  1. <?xml version="1.0" encoding="utf-8"?> 
  2.   <manifest xmlns:android="http://schemas.android.com/apk/res/android" 
  3.       package="com.example.hearrate" 
  4.       android:versionCode="1" 
  5.       android:versionName="1.0" >    
  6.       <uses-sdk 
  7.           android:minSdkVersion="8" 
  8.           android:targetSdkVersion="17" /> 
  9.   <uses-permission android:name="android.permission.CAMERA"/> 
  10.   <!-- 在SDCard中创建与删除文件权限 --> 
  11.    
  12. <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>    
  13.   <!-- 往SDCard写入数据权限 -->    
  14.   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 
  15.   <uses-feature android:name="android.hardware.camera"/> 
  16.   <uses-feature android:name="android.hardware.camera.autofocus"/>   
  17.   <application 
  18.           android:allowBackup="true" 
  19.           android:icon="@drawable/ic_launcher"
  20. android:label="@string/app_name" 
  21.           android:theme="@style/AppTheme" > 
  22.           <activity 
  23.               android:name="com.example.hearrate.MainActivity" 
  24.               android:label="@string/app_name" 
  25.               android:theme="@android:style/Theme.NoTitleBar.Fullscreen" 
  26.               android:screenOrientation="landscape" 
  27.               > 
  28.               <intent-filter> 
  29.                   <action android:name="android.intent.action.MAIN" /> 
  30.                   <category android:name="android.intent.category.LAUNCHER" /> 
  31.               </intent-filter> 
  32.           </activity> 
  33.       </application> 
  34.   </manifest> 

 

责任编辑:闫佳明 来源: oschina
相关推荐

2022-07-19 20:25:54

鸿蒙MaskRCNN算法

2020-08-21 13:40:17

Python代码人体肤色

2013-05-10 17:13:00

2022-05-13 09:52:52

Google肤色研究开源

2011-07-20 17:29:12

iPhone 网络

2013-07-27 20:04:38

2018-05-08 14:47:38

虚拟机方法代码

2024-09-04 15:42:38

OpenCV开发Python

2017-02-16 08:25:35

2013-01-09 15:27:45

DOM XSS检测QtWebKitXSS

2022-10-26 15:41:38

深度学习Deepfake机器学习

2010-09-07 16:31:27

CSS

2021-05-19 10:10:11

人工智能AI谷歌

2018-07-18 11:51:17

人工智能阴影检测反射

2022-11-09 11:02:00

2024-07-04 09:22:24

2024-06-06 08:00:00

2013-10-22 10:27:59

2009-08-27 17:47:21

c#皮肤
点赞
收藏

51CTO技术栈公众号