展会信息港展会大全

在android上实现基于肤色的皮肤检测的几个技术要点
来源:互联网   发布日期:2016-01-19 12:04:07   浏览:2016次  

导读:以前,一直没明白yuv和YcbCr之间的差异,想必有些朋友也会有同样的疑惑。所以,我看完之后就记载下来了。在android上实现基于肤色的皮肤检测的几个技术要点:(1)android上使用相机预览,包括相机api的使用和su ...

以前,一直没明白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

源代码如下:

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 implementsSurfaceHolder.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

048protected void onCreate(Bundle savedInstanceState) {

049super.onCreate(savedInstanceState);

050setContentView(R.layout.activity_main);

051mView=(SurfaceView)findViewById(R.id.layer0);

052paint = new Paint();

053paint.setColor(Color.RED);

054paint.setAntiAlias(true);

055

056mPreviewWidth=320;

057mPreviewHeight=400;

058mHolder=mView.getHolder();

059mHolder.addCallback(this);

060mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

061

062mLayer=(SurfaceView)findViewById(R.id.layer1);

063mLayer.setZOrderOnTop(true);

064//mLayer.setEGLConfigChooser(8, 8, 8, 8, 16, 0);

065

066

067mLayerHolder=mLayer.getHolder();

068mLayerHolder.setFormat(PixelFormat.TRANSPARENT);

069mLayerHolder.addCallback(this);

070mLayerHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

071}

072 void drawlayer1()

073 {

074canvas=mLayerHolder.lockCanvas();

075// canvas.drawRGB(0, 0, 0);

076// canvas.save();

077Bitmap bmp=BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);

078//绘制

079// canvas.drawBitmap(bmp, null, paint);

080drawImage(canvas,bmp,facex,facex,72,72,0,0);

081canvas.restore();

082bmp=null;

083mLayerHolder.unlockCanvasAndPost(canvas);

084 }

085@Override

086public boolean onCreateOptionsMenu(Menu menu) {

087// Inflate the menu; this adds items to the action bar if it is present.

088getMenuInflater().inflate(R.menu.activity_main, menu);

089return true;

090}

091

092@Override

093public void surfaceChanged(SurfaceHolder arg0, int arg1, int width, int height) {

094// TODO Auto-generated method stub

095mPreviewWidth=width;

096mPreviewHeight=height;

097if(arg0.equals(mLayerHolder))

098{

099//drawlayer1();

100return;

101}

102

103RGBData= new int[mPreviewHeight* mPreviewWidth];

104mYUVData= new byte[mPreviewHeight* mPreviewWidth+(mPreviewHeight/2)* (mPreviewWidth/2)+(mPreviewHeight/2)* (mPreviewWidth/2)];

105initCamera();

106}

107

108@SuppressLint("NewApi")

109@Override

110public void surfaceCreated(SurfaceHolder arg0) {

111// TODO Auto-generated method stub

112// TODO Auto-generated method stub

113if(arg0.equals(mLayerHolder))

114return;

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 {

130mCamera = Camera.open();// 开启摄像头(2.3版本后支持多摄像头,需传入参数)

131bfront=false;

132 }

133try

134{

135

136mCamera.setPreviewDisplay(mHolder);//set the surface to be used for live preview

137

138Log("成功打开");

139} catch (Exception ex)

140{

141if(null != mCamera)

142{

143mCamera.release();

144mCamera = null;

145}

146canvas=mHolder.lockCanvas();

147canvas.drawRGB(0, 0, 0);

148canvas.save();

149Bitmap bmp=BitmapFactory.decodeResource(getResources(), R.drawable.bg);

150//绘制

151// canvas.drawBitmap(bmp, null, paint);

152drawImage(canvas,bmp,0,0,mPreviewWidth,mPreviewHeight,0,0);

153canvas.restore();

154bmp=null;

155 mHolder.unlockCanvasAndPost(canvas);

156Log("打开失败"+ex.getMessage());

157}

158}

159 //GameView.drawImage(canvas, mBitDestTop, miDTX, mBitQQ.getHeight(), mBitDestTop.getWidth(), mBitDestTop.getHeight()/2, 0, 0);

160public static void drawImage(Canvas canvas, Bitmap blt, int x, int y, int w, int h, int bx, int by)

161{//x,y表示绘画的起点,

162Rect src = new Rect();// 图片

163Rect dst = new Rect();// 屏幕位置及尺寸

164//src 这个是表示绘画图片的大小

165src.left = bx;//0,0

166src.top = by;

167src.right = bx + w;// mBitDestTop.getWidth();,这个是桌面图的宽度,

168src.bottom = by + h;//mBitDestTop.getHeight()/2;// 这个是桌面图的高度的一半

169// 下面的 dst 是表示 绘画这个图片的位置

170dst.left = x;//miDTX,//这个是可以改变的,也就是绘图的起点X位置

171dst.top = y;//mBitQQ.getHeight();//这个是QQ图片的高度。 也就相当于 桌面图片绘画起点的Y坐标

172dst.right = x + w;//miDTX + mBitDestTop.getWidth();// 表示需绘画的图片的右上角

173dst.bottom = y + h;// mBitQQ.getHeight() + mBitDestTop.getHeight();//表示需绘画的图片的右下角

174canvas.drawBitmap(blt, src, dst, null);//这个方法第一个参数是图片原来的大小,第二个参数是 绘画该图片需显示多少。也就是说你想绘画该图片的某一些地方,而不是全部图片,第三个参数表示该图片绘画的位置

175

176src = null;

177dst = null;

178}

179@Override

180public void surfaceDestroyed(SurfaceHolder arg0) {

181// TODO Auto-generated method stub

182if(arg0.equals(mLayerHolder))

183return;

184if(null != mCamera)

185{

186mCamera.setPreviewCallback(null); //!!这个必须在前,不然退出出错

187mCamera.stopPreview();

188bIfPreview = false;

189mCamera.release();

190mCamera = null;

191}

192}

193

194

195@Override

196public void onPreviewFrame(byte[] data, Camera camera) {

197// TODO Auto-generated method stub

198Log("going into onPreviewFrame"+data.length);

199

200int imageWidth = camera.getParameters().getPreviewSize().width;

201int imageHeight =camera.getParameters().getPreviewSize().height ;

202//int RGBData[] = new int[imageWidth* imageHeight];

203if(!bprocessing)

204{

205System.arraycopy(data, 0, mYUVData, 0, data.length);

206

207new 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/*

220FileOutputStream out;

221try {

222String path=String.format("/mnt/sdcard/%d.png", System.currentTimeMillis());

223out = new FileOutputStream(path);

224bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);

225out.close();

226} catch (FileNotFoundException e) {

227// TODO Auto-generated catch block

228e.printStackTrace();

229} catch (IOException e) {

230// TODO Auto-generated catch block

231e.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 /*

258for( i=0,yp = 0;i<mPreviewHeight;i++)

259{

260uvp=framesize+(i>>1)*mPreviewWidth;

261for( j=0;j<mPreviewWidth;j++)

262{

263int y = (0xff & ((int) mYUVData[yp])) - 16;

264if (y < 0) y = 0;

265if((j&1)==0)

266{

267v = (0xff & mYUVData[uvp++]) - 128;

268u = (0xff & mYUVData[uvp++]) - 128;

269}

270// if(133&le;Cr&le;173,77&le;Cb&le;127

271if(v>133&&v<173)

272canvas.drawPoint(j, i, paint);

273

274int y1192 = 1192 * y;

275

276int r = (y1192 + 1634 * v);

277

278int g = (y1192 - 833 * v - 400 * u);

279

280int b = (y1192 + 2066 * u);

281

282if (r < 0) r = 0; else if (r > 262143) r = 262143;

283

284if (g < 0) g = 0; else if (g > 262143) g = 262143;

285

286if (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

301canvas.restore();

302mLayerHolder.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}

327public void drawdetect()

328{

329canvas=mLayerHolder.lockCanvas();

330

331if(canvas==null)

332return;

333canvas.drawColor(Color.TRANSPARENT);

334Paint p = new Paint();

335//清屏

336p.setXfermode(new PorterDuffXfermode(Mode.CLEAR));

337canvas.drawPaint(p);

338p.setXfermode(new PorterDuffXfermode(Mode.SRC));

339canvas.save();

340canvas.drawBitmap(RGBData, 0, mPreviewWidth, 0, 0, mPreviewWidth, mPreviewHeight, true, p);

341

342canvas.restore();

343mLayerHolder.unlockCanvasAndPost(canvas);

344}

345public void detectwhite(byte[] yuv420sp, int width, int height)

346{

347//检测所有白色

348final int frameSize = width * height;

349

350for (int j = 0, yp = 0; j < height; j++) {

351int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;

352for (int i = 0; i < width; i++, yp++) {

353int y = (0xff & ((int) yuv420sp[yp]));

354if (y < 0) y = 0;

355if ((i & 1) == 0) {

356v = (0xff & yuv420sp[uvp++]);;

357u = (0xff & yuv420sp[uvp++]);

358}

359///133&le;Cr&le;173,77&le;Cb&le;127

360 if(y>250)

361 {

362RGBData[yp]=Color.RED;

363// canvas.drawPoint(i, j, paint);

364}else

365{

366RGBData[yp]=Color.TRANSPARENT;

367}

368

369}

370

371}

372

373}

374public void detectface(byte[] yuv420sp, int width, int height)

375{

376

377final int frameSize = width * height;

378

379for (int j = 0, yp = 0; j < height; j++) {

380int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;

381for (int i = 0; i < width; i++, yp++) {

382

383if ((i & 1) == 0) {

384v = (0xff & yuv420sp[uvp++]);;

385u = (0xff & yuv420sp[uvp++]);

386}

387///133&le;Cr&le;173,77&le;Cb&le;127

388 if((v)>133&&(v)<160&&(u>77)&&(u<127))

389 {

390RGBData[yp]=Color.RED;

391// canvas.drawPoint(i, j, paint);

392}else

393{

394RGBData[yp]=Color.TRANSPARENT;

395}

396

397}

398

399}

400

401}

402public void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width, int height) {

403final int frameSize = width * height;

404canvas=mLayerHolder.lockCanvas();

405Paint paint1 = new Paint();

406paint1.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

407canvas.drawPaint(paint1);

408canvas.save();

409for (int j = 0, yp = 0; j < height; j++) {

410int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;

411for (int i = 0; i < width; i++, yp++) {

412int y = (0xff & ((int) yuv420sp[yp])) - 16;

413if (y < 0) y = 0;

414if ((i & 1) == 0) {

415v = (0xff & yuv420sp[uvp++]) - 128;

416u = (0xff & yuv420sp[uvp++]) - 128;

417}

418///133&le;Cr&le;173,77&le;Cb&le;127

419 if((v)>133&&(v)<160&&(u>77)&&(u<127))

420 {

421canvas.drawPoint(i, j, paint);

422}

423 /*

424* 这个是yuv转RGB的处理

425**/

426int y1192 = 1192 * y;

427int r = (y1192 + 1634 * v);

428int g = (y1192 - 833 * v - 400 * u);

429int b = (y1192 + 2066 * u);

430

431if (r < 0) r = 0; else if (r > 262143) r = 262143;

432if (g < 0) g = 0; else if (g > 262143) g = 262143;

433if (b < 0) b = 0; else if (b > 262143) b = 262143;

434

435rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);

436

437r = (rgb[yp] >> 16)&0xff;

438g = (rgb[yp] >> 8) & 0xff;

439b = rgb[yp] & 0xff;

440//if(r==255&&g==255&&b==255)

441// canvas.drawPoint(i, j, paint);

442

443

444}

445

446}

447canvas.restore();

448mLayerHolder.unlockCanvasAndPost(canvas);

449 }

450

451

452private void initCamera()

453{

454if (bIfPreview)

455{

456mCamera.stopPreview();

457}

458if(null != mCamera)

459{

460try{

461Camera.Parameters parameters = mCamera.getParameters();

462// parameters.setFlashMode("off"); // 无闪光灯

463parameters.setPictureFormat(PixelFormat.JPEG); //Sets the image format for picture 设定相片格式为JPEG,默认为NV21

464parameters.setPreviewFormat(PixelFormat.YCbCr_420_SP); //Sets the image format for preview picture,默认为NV21

465

466mCamera.setPreviewCallback(this);

467// 【调试】获取caera支持的PictrueSize,看看能否设置??

468List pictureSizes = mCamera.getParameters().getSupportedPictureSizes();

469List previewSizes = mCamera.getParameters().getSupportedPreviewSizes();

470List previewFormats = mCamera.getParameters().getSupportedPreviewFormats();

471List previewFrameRates = mCamera.getParameters().getSupportedPreviewFrameRates();

472

473Size psize = null;

474for (int i = 0; i < pictureSizes.size(); i++)

475{

476psize = (Size) pictureSizes.get(i);

477

478}

479for (int i = 0; i < previewSizes.size(); i++)

480{

481psize = (Size) previewSizes.get(i);

482

483}

484Integer pf = null;

485for (int i = 0; i < previewFormats.size(); i++)

486{

487pf = (Integer) previewFormats.get(i);

488

489}

490

491// 设置拍照和预览图片大小

492parameters.setPictureSize(640, 480); //指定拍照图片的大小

493parameters.setPreviewSize(mPreviewWidth, mPreviewHeight); // 指定preview的大小

494//这两个属性 如果这两个属性设置的和真实手机的不一样时,就会报错

495if(bfront)

496{

497parameters.set("orientation", "landscape"); //

498parameters.set("rotation", 0); // 镜头角度转90度(默认摄像头是横拍)

499mCamera.setDisplayOrientation(0); // 在2.2以上可以使用

500}

501// 横竖屏镜头自动调整

502/*if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)

503{

504parameters.set("orientation", "portrait"); //

505parameters.set("rotation", 90); // 镜头角度转90度(默认摄像头是横拍)

506mCamera.setDisplayOrientation(90); // 在2.2以上可以使用

507} else// 如果是横屏

508{

509parameters.set("orientation", "landscape"); //

510mCamera.setDisplayOrientation(0); // 在2.2以上可以使用

511}

512*/

513//添加对视频流处理函数

514// 设定配置参数并开启预览

515mCamera.setParameters(parameters); // 将Camera.Parameters设定予Camera

516mCamera.startPreview(); // 打开预览画面

517bIfPreview = true;

518// 【调试】设置后的图片大小和预览大小以及帧率

519Camera.Size csize = mCamera.getParameters().getPreviewSize();

520mPreviewHeight = csize.height; //

521mPreviewWidth = csize.width;

522

523csize = mCamera.getParameters().getPictureSize();

524

525

526}catch(Exception e)

527{

528Log(e.getMessage());

529}

530

531}

532}

533void Log(String msg)

534{

535System.out.println("LOG:"+msg);

536}

537int[] g_v_table,g_u_table,y_table;

538int[][] r_yv_table,b_yu_table;

539int inited = 0;

540

541

542void initTable()

543{

544g_v_table=new int[256];

545g_u_table=new int[256];

546y_table=new int[256];

547r_yv_table=new int[256][256];

548b_yu_table=new int[256][256];

549if (inited == 0)

550{

551inited = 1;

552int m = 0,n=0;

553for (; m < 256; m++)

554{

555g_v_table[m] = 833 * (m - 128);

556g_u_table[m] = 400 * (m - 128);

557y_table[m] = 1192 * (m - 16);

558}

559int temp = 0;

560for (m = 0; m < 256; m++)

561for (n = 0; n < 256; n++)

562{

563temp = 1192 * (m - 16) + 1634 * (n - 128);

564if (temp < 0) temp = 0; else if (temp > 262143) temp = 262143;

565r_yv_table[m][n] = temp;

566

567temp = 1192 * (m - 16) + 2066 * (n - 128);

568if (temp < 0) temp = 0; else if (temp > 262143) temp = 262143;

569b_yu_table[m][n] = temp;

570}

571}

572}

573public class ProcessTask extends AsyncTask<byte[], Void, Void>

574{

575

576@Override

577protected void onPostExecute(Void result) {

578// TODO Auto-generated method stub

579super.onPostExecute(result);

580drawdetect();

581bprocessing=false;

582}

583

584@Override

585protected void onPreExecute() {

586// TODO Auto-generated method stub

587super.onPreExecute();

588if(bprocessing)

589this.cancel(true);

590

591}

592

593@Override

594protected Void doInBackground(byte[]... params) {

595// TODO Auto-generated method stub

596bprocessing=true;

597byte[] 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>

赞助本站

人工智能实验室

相关热词: 检测 技术要点

相关内容
AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港