001packagecom.example.hearrate;
002
003importjava.io.FileNotFoundException;
004importjava.io.FileOutputStream;
005importjava.io.IOException;
006importjava.util.List;
007
008importandroid.graphics.Bitmap;
009importandroid.graphics.BitmapFactory;
010importandroid.graphics.Canvas;
011importandroid.graphics.Color;
012importandroid.graphics.Paint;
013importandroid.graphics.PixelFormat;
014importandroid.graphics.PorterDuffXfermode;
015importandroid.graphics.Rect;
016importandroid.hardware.Camera;
017importandroid.hardware.Camera.CameraInfo;
018importandroid.hardware.Camera.Size;
019importandroid.os.AsyncTask;
020importandroid.os.Build;
021importandroid.os.Bundle;
022importandroid.annotation.SuppressLint;
023importandroid.app.Activity;
024importandroid.content.res.Configuration;
025importandroid.util.Log;
026importandroid.view.Menu;
027importandroid.view.SurfaceHolder;
028importandroid.view.SurfaceView;
029importandroid.graphics.PorterDuff;
030importandroid.graphics.PorterDuff.Mode;
031publicclassMainActivityextendsActivityimplementsSurfaceHolder.Callback ,Camera.PreviewCallback{
032SurfaceHolder mHolder;
033SurfaceView mView;
034SurfaceView mLayer;
035SurfaceHolder mLayerHolder;
036privateCamera mCamera =null;
037privatebooleanbIfPreview =false;
038privateintmPreviewHeight;
039privateintmPreviewWidth;
040privateCanvas canvas;
041privatePaint paint;
042privateintfacex=0,facey=0;
043privatebooleanbprocessing=false;
044privateint[] RGBData;
045privatebyte[] mYUVData;
046privatebooleanbfront=false;
047@Override
048protectedvoidonCreate(Bundle savedInstanceState) {
049super.onCreate(savedInstanceState);
050setContentView(R.layout.activity_main);
051mView=(SurfaceView)findViewById(R.id.layer0);
052paint =newPaint();
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}
072voiddrawlayer1()
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
086publicbooleanonCreateOptionsMenu(Menu menu) {
087// Inflate the menu; this adds items to the action bar if it is present.
088getMenuInflater().inflate(R.menu.activity_main, menu);
089returntrue;
090}
091
092@Override
093publicvoidsurfaceChanged(SurfaceHolder arg0,intarg1,intwidth,intheight) {
094// TODO Auto-generated method stub
095mPreviewWidth=width;
096mPreviewHeight=height;
097if(arg0.equals(mLayerHolder))
098{
099//drawlayer1();
100return;
101}
102
103RGBData=newint[mPreviewHeight* mPreviewWidth];
104mYUVData=newbyte[mPreviewHeight* mPreviewWidth+(mPreviewHeight/2)* (mPreviewWidth/2)+(mPreviewHeight/2)* (mPreviewWidth/2)];
105initCamera();
106}
107
108@SuppressLint("NewApi")
109@Override
110publicvoidsurfaceCreated(SurfaceHolder arg0) {
111// TODO Auto-generated method stub
112// TODO Auto-generated method stub
113if(arg0.equals(mLayerHolder))
114return;
115if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.GINGERBREAD)
116{
117for(inti=0;i
118{
119CameraInfo info=newCameraInfo();
120Camera.getCameraInfo(i, info);
121if(info.facing==CameraInfo.CAMERA_FACING_FRONT)
122{
123//mCamera = Camera.open(i);
124//bfront=true;
125}
126}
127}
128if(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;
155mHolder.unlockCanvasAndPost(canvas);
156Log("打开失败"+ex.getMessage());
157}
158}
159// GameView.drawImage(canvas, mBitDestTop, miDTX, mBitQQ.getHeight(), mBitDestTop.getWidth(), mBitDestTop.getHeight()/2, 0, 0);
160publicstaticvoiddrawImage(Canvas canvas, Bitmap blt,intx,inty,intw,inth,intbx,intby)
161{//x,y表示绘画的起点,
162Rect src =newRect();// 图片
163Rect dst =newRect();// 屏幕位置及尺寸
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
180publicvoidsurfaceDestroyed(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
196publicvoidonPreviewFrame(byte[] data, Camera camera) {
197// TODO Auto-generated method stub
198Log("going into onPreviewFrame"+data.length);
199
200intimageWidth = camera.getParameters().getPreviewSize().width ;
201intimageHeight =camera.getParameters().getPreviewSize().height ;
202// int RGBData[] = new int[imageWidth* imageHeight];
203if(!bprocessing)
204{
205System.arraycopy(data,0, mYUVData,0, data.length);
206
207newProcessTask().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
259 {
260 uvp=framesize+(i>>1)*mPreviewWidth;
261 for( j=0;j
262 {
263 int y = (0xff & ((int) mYUVData[yp])) - 16;
264 if (y
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 262143) r = 262143;
283
284 if (g 262143) g = 262143;
285
286 if (b 262143) b = 262143;
287 // int rgb=0xff000000 | ((r <> 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 <> 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
308 * {
309 * uvp=framesize+(i>>1)*w;
310 * for(int j=0;j
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}
327publicvoiddrawdetect()
328{
329canvas=mLayerHolder.lockCanvas();
330
331if(canvas==null)
332return;
333canvas.drawColor(Color.TRANSPARENT);
334Paint p =newPaint();
335//清屏
336p.setXfermode(newPorterDuffXfermode(Mode.CLEAR));
337canvas.drawPaint(p);
338p.setXfermode(newPorterDuffXfermode(Mode.SRC));
339canvas.save();
340canvas.drawBitmap(RGBData,0, mPreviewWidth,0,0, mPreviewWidth, mPreviewHeight,true, p);
341
342canvas.restore();
343mLayerHolder.unlockCanvasAndPost(canvas);
344}
345publicvoiddetectwhite(byte[] yuv420sp,intwidth,intheight)
346{
347//检测所有白色
348finalintframeSize = width * height;
349
350for(intj =0, yp =0; j
351intuvp = frameSize + (j >>1) * width, u =0, v =0;
352for(inti =0; i
353inty = (0xff& ((int) yuv420sp[yp]));
354if(y <0) y =0;
355if((i &1) ==0) {
356v = (0xff& yuv420sp[uvp++]);;
357u = (0xff& yuv420sp[uvp++]);
358}
359///133≤Cr≤173,77≤Cb≤127
360if(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}
374publicvoiddetectface(byte[] yuv420sp,intwidth,intheight)
375{
376
377finalintframeSize = width * height;
378
379for(intj =0, yp =0; j
380intuvp = frameSize + (j >>1) * width, u =0, v =0;
381for(inti =0; i
382
383if((i &1) ==0) {
384v = (0xff& yuv420sp[uvp++]);;
385u = (0xff& yuv420sp[uvp++]);
386}
387///133≤Cr≤173,77≤Cb≤127
388if((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}
402publicvoiddecodeYUV420SP(int[] rgb,byte[] yuv420sp,intwidth,intheight) {
403finalintframeSize = width * height;
404canvas=mLayerHolder.lockCanvas();
405Paint paint1 =newPaint();
406paint1.setXfermode(newPorterDuffXfermode(PorterDuff.Mode.CLEAR));
407canvas.drawPaint(paint1);
408canvas.save();
409for(intj =0, yp =0; j
410intuvp = frameSize + (j >>1) * width, u =0, v =0;
411for(inti =0; i
412inty = (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≤Cr≤173,77≤Cb≤127
419if((v)>133&&(v)<160&&(u>77)&&(u<127))
420{
421canvas.drawPoint(i, j, paint);
422}
423/*
424 * 这个是yuv转RGB的处理
425 * */
426inty1192 =1192* y;
427intr = (y1192 +1634* v);
428intg = (y1192 -833* v -400* u);
429intb = (y1192 +2066* u);
430
431if(r <0) r =0;elseif(r >262143) r =262143;
432if(g <0) g =0;elseif(g >262143) g =262143;
433if(b <0) b =0;elseif(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
452privatevoidinitCamera()
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(inti =0; i
475{
476psize = (Size) pictureSizes.get(i);
477
478}
479for(inti =0; i
480{
481psize = (Size) previewSizes.get(i);
482
483}
484Integer pf =null;
485for(inti =0; 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 {
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// 设定配置参数并开启预览
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}
533voidLog(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;
539intinited =0;
540
541
542voidinitTable()
543{
544g_v_table=newint[256];
545g_u_table=newint[256];
546y_table=newint[256];
547r_yv_table=newint[256][256];
548b_yu_table=newint[256][256];
549if(inited ==0)
550{
551inited =1;
552intm =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}
559inttemp =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;elseif(temp >262143) temp =262143;
565r_yv_table[m][n] = temp;
566
567temp =1192* (m -16) +2066* (n -128);
568if(temp <0) temp =0;elseif(temp >262143) temp =262143;
569b_yu_table[m][n] = temp;
570}
571}
572}
573publicclassProcessTaskextendsAsyncTask
574{
575
576@Override
577protectedvoidonPostExecute(Void result) {
578// TODO Auto-generated method stub
579super.onPostExecute(result);
580drawdetect();
581bprocessing=false;
582}
583
584@Override
585protectedvoidonPreExecute() {
586// TODO Auto-generated method stub
587super.onPreExecute();
588if(bprocessing)
589this.cancel(true);
590
591}
592
593@Override
594protectedVoid 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);
returnnull;
}
}
}