在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>