心跳数据采集及简单处理-黄

来源:互联网 发布:白城广逸网络地点 编辑:程序博客网 时间:2024/04/30 21:55

日期:2014年11月8日—2014年11月14日

1.本周已完成任务:心跳数据采集及简单处理

2.本周未完成任务:使用摄像头读出具体的心跳数

3.下周计划:使用FFT读出具体心跳

4.关键技术点说明:

由上一个博客里面的代码改编得来,基本上就是对读出来的波形进行了FIR滤波,滤除高频以及低频成分,以及一些简单的数据处理,获得幅度比较大的心跳信号。

              FIR的参数使用MATLAB计算,采样率5Hz 带通0.6-1.5Hz,而函数是DSP直接抄过来的。


以下 是代码以及注释

package com.example.heart;import android.app.Activity;import android.content.pm.ActivityInfo;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Rect;import android.hardware.Camera;import android.hardware.Camera.PreviewCallback;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.DisplayMetrics;import android.util.Log;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.widget.TextView;public class MainActivity extends Activity {TextView heart_display;SurfaceView showDataSurfaceView=null;SurfaceHolder mSurfaceHolder=null;SurfaceView data_view=null;SurfaceHolder mdataviewHolder = null;int centerY;//中心线    int oldX=0;    int oldY=200;//上一个XY 点    int newX=0;    int newY=200;    int currentX;//当前绘制到的X 轴上的点int ScreenWidth;int length=0;DisplayMetrics dm;private static String msg = "";int sigIn[] = null;//FIR输入数据int sigout[] = null;//FIR输出数据int FIR16_LPF_TEST[] = null;//FIR滤波系数,通过matlab计算获取int count = 0;private static Camera camera = null;private static SurfaceView preview = null;private static SurfaceHolder previewHolder = null;    @SuppressWarnings("deprecation")@Override    protected void onCreate(Bundle savedInstanceState) {    super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);                heart_display = (TextView)findViewById(R.id.textView2);        preview = (SurfaceView)findViewById(R.id.preview);previewHolder = preview.getHolder();//获得SurfaceHolder对象previewHolder.addCallback(surfaceCallback);//添加回调函数previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);        showDataSurfaceView=(SurfaceView)findViewById(R.id.showView);        mSurfaceHolder=showDataSurfaceView.getHolder();        dm = new DisplayMetrics();//DisplayMetrics用来获取屏幕的分辨率,打点打到结束后返回0        getWindowManager().getDefaultDisplay().getMetrics(dm);        ScreenWidth=dm.widthPixels;//屏幕的横向分辨率                sigIn = new int[128];        sigout = new int[128];         //FIR滤波系数 采样率5Hz 带通0.6-1.5HzFIR16_LPF_TEST = new int[] { 2304, 1589, -676, 1249, -501, -8175,-4413, 10240, 10240, -4413, -8175, -501, 1249, -676, 1589, 2304 };                data_view = (SurfaceView)findViewById(R.id.dataview);//数据处理后的数据显示        mdataviewHolder = data_view.getHolder();        //        handler.post(runnable);    }            void drawline()//画线(点)    {    //获取Canvas,锁定画布    Canvas canvas = mSurfaceHolder.lockCanvas(new Rect(oldX, 0, newX,dm.heightPixels));    Paint mPaint=new Paint();    mPaint.setColor(Color.GREEN);//设定为绿色    mPaint.setStrokeWidth(1);//线宽为1像素    canvas.drawLine(oldX, oldY, newX, newY, mPaint);//Canvas绘画    oldX=newX;    oldY=newY;    mSurfaceHolder.unlockCanvasAndPost(canvas);//结束锁定画图,并提交改变,将图形显示    }        //Handler handler = new Handler();//测试定时器,这个程序暂时用不到//Runnable runnable = new Runnable() {//@Override//public void run() {//heart_display.setText(String.valueOf("102"));//handler.postDelayed(runnable, 500);// 0.5秒刷新//}//};    int oldX1 = 0, oldY1 = 0;void drawline_fir()// 画线(点)用于显示数据{oldX1 = 0;Canvas canvas = mdataviewHolder.lockCanvas();canvas.drawColor(Color.BLACK);// 清除画布Paint mPaint = new Paint();mPaint.setColor(Color.RED);//设定为红色mPaint.setStrokeWidth(1);// 线宽为1像素int y;for (int i = 0; i < 128; i++) {y = sigout[i];canvas.drawLine(oldX1, oldY1, i, y, mPaint);// Canvas绘画oldX1 = i;oldY1 = y;}mdataviewHolder.unlockCanvasAndPost(canvas);// 结束锁定画图,并提交改变,将图形显示    }        void ClearDraw() //清除画布    {        Canvas canvas = mSurfaceHolder.lockCanvas();        canvas.drawColor(Color.BLACK);// 清除画布        mSurfaceHolder.unlockCanvasAndPost(canvas);    }    private Handler DrawHandler = new Handler() //画图Handler{public void handleMessage(Message m) {//画点drawline();currentX++;newX++;newY=Integer.valueOf(msg,10);//根据msg的值来确定当前的Y坐标Log.d("chenxuro", msg);if(newX==ScreenWidth-1)//当X坐标超过屏幕横向分辨率的时候清除屏幕,然后返回0{ClearDraw();currentX=0;oldX=0;newX=0;}}};private SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback() //SurfaceView回调函数{    @Overridepublic void surfaceCreated(SurfaceHolder holder) {try {camera.setPreviewDisplay(previewHolder);//将camera连接到一个SurfaceView,准备实时预览camera.setPreviewCallback(previewCallback);//添加回调函数} catch (Throwable t) {Log.e("PreviewDemo-surfaceCallback", "Exception in setPreviewDisplay()", t);}}    @SuppressWarnings("deprecation")@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {Camera.Parameters parameters = camera.getParameters();//获取camera界限parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);//打开闪光灯Camera.Size size = getSmallestPreviewSize(width, height, parameters);//得到最小尺寸预览if (size!=null) //设置预览大小{parameters.setPreviewSize(size.width, size.height);parameters.setPreviewFrameRate(5);//每秒5帧Log.d("parameters", "Using width="+size.width+" height="+size.height);}camera.setParameters(parameters);//设置camera界限camera.startPreview();//开始预览}    @Overridepublic void surfaceDestroyed(SurfaceHolder holder) {//Ignore???//android.os.Process.killProcess(android.os.Process.myPid());}};private PreviewCallback previewCallback = new PreviewCallback() //摄像头回调{@Overridepublic void onPreviewFrame(byte[] data, Camera cam) //摄像头帧预览{if (data == null) throw new NullPointerException();Camera.Size size = cam.getParameters().getPreviewSize();if (size == null) throw new NullPointerException();        //关闭摄像头预览回调        camera.setPreviewCallback(null);        int previewWidth=0;        int previewHeight=0;                if (data != null) //获取预览图片的信息        {            previewWidth = camera.getParameters().getPreviewSize().width;               previewHeight = camera.getParameters().getPreviewSize().height;           }                   int CurrentRedSum=decodeYUV420SPtoRedSum(data, previewWidth, previewHeight);           int CurrentRedAverage=CurrentRedSum/(previewWidth * previewHeight);        if (count == 128)//数据滑窗count = 0;//获得红色部分数据,进行缩小处理防止溢出sigIn[count++] = CurrentRedSum*10/(previewWidth * previewHeight);//sigIn[count++] = CurrentRedAverage;fir(sigIn,FIR16_LPF_TEST,sigout);//调用FIR滤波函数drawline_fir();//显示滤波后的数据msg  = String.valueOf(CurrentRedAverage);//获取红色部分平均的数据DrawHandler.sendEmptyMessage(0);//启动绘图        //打开摄像头预览回调        camera.setPreviewCallback(this);   }};private static Camera.Size getSmallestPreviewSize(int width, int height, Camera.Parameters parameters) {Camera.Size result=null;for (Camera.Size size : parameters.getSupportedPreviewSizes()) {if (size.width<=width && size.height<=height) {if (result==null) {result=size;} else {int resultArea=result.width*result.height;int newArea=size.width*size.height;if (newArea<resultArea) result=size;}}}return result;}@Overridepublic void onResume() {super.onResume();camera = Camera.open();//打开摄像头camera.setDisplayOrientation(90);}    @Overridepublic void onPause() {super.onPause();camera.setPreviewCallback(null);camera.stopPreview();//停止摄像头camera.release();camera = null;}//获得Red数据和private static int decodeYUV420SPtoRedSum(byte[] yuv420sp, int width, int height) {if (yuv420sp==null) return 0;final int frameSize = width * height;int sum = 0;    for (int j = 0, yp = 0; j < height; j++) {        int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;        for (int i = 0; i < width; i++, yp++) {            int y = (0xff & ((int) yuv420sp[yp])) - 16;            if (y < 0) y = 0;            if ((i & 1) == 0) {                v = (0xff & yuv420sp[uvp++]) - 128;                u = (0xff & yuv420sp[uvp++]) - 128;            }            int y1192 = 1192 * y;            int r = (y1192 + 1634 * v);            int g = (y1192 - 833 * v - 400 * u);            int b = (y1192 + 2066 * u);            if (r < 0) r = 0; else if (r > 262143) r = 262143;            if (g < 0) g = 0; else if (g > 262143) g = 262143;            if (b < 0) b = 0; else if (b > 262143) b = 262143;            int pixel = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);            int red = (pixel >> 16) & 0xff;            sum+=red;        }    }    return sum;}//FIR滤波函数public static final short SIGNAL_LENGTH = 128;//数组长度public static final short FIR_ORDER = 16;//FIR阶数private static void fir(int x[], int h[], int y[]) {int i, j, nNow = 0;long sum;for (j = 0; j < SIGNAL_LENGTH; j++) {sum = 0;for (i = 0; i < FIR_ORDER; i++) {nNow = j - i;if (nNow < 0)nNow = SIGNAL_LENGTH + nNow;sum += (long) x[nNow] * h[i];}y[j] = (int) (sum >> 15);////幅度限制//if(y[j]>200)y[j]=200;//if(y[j]<0)y[j]=0;}}}


效果


0 0
原创粉丝点击