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