Android+OpenCV实现轨迹识别

来源:互联网 发布:纳粹党卫军军服淘宝 编辑:程序博客网 时间:2024/05/16 08:18

    最近在帮朋友搞一个APP,实现:在屏幕上画一条轨迹,然后将各个坐标通过蓝牙发送到下位机。当然,这个坐标是有顺序的,难点也在这里。

    方法一:抓取屏幕点,并实时发送到下位机(已实现)。

public boolean onTouchEvent(MotionEvent event){// 获取触点位置float x = event.getX();float y = event.getY();
<span style="white-space:pre"></span>point[0]=x;<span style="white-space:pre"></span>point[1]=y;                ...                ...        }
当然了,在这个类里面得定义为public static 变量:
<pre name="code" class="java">public static float[] point=new float[2];
在Client里面,我们开启一个发送数据线程:
DeliveryThread = new Thread(this);// 连接上了就开始传输吧DeliveryThread.start();
重写Runnable接口:

@Overridepublic void run() {// TODO Auto-generated method stubwhile (true) {try {float[] p = DrawView.point;byte[] buf0 = intToByteArray((int) p[0]);byte[] buf1 = intToByteArray((int) p[1]);byte[] buf = new byte[8];for (int i = 0; i < 3; i++) {buf[i] = buf0[i];}for (int i = 0; i < 3; i++) {buf[i + 4] = buf1[i];}Log.i("tag", ".." + buf.length + " " + buf[0] + " " + buf[1]+ " " + buf[2] + " " + buf[3] + " " + buf[4] + " "+ buf[5] + " " + buf[6] + " " + buf[7]);mOutStream.write(buf, 0, 8);} catch (IOException e) {Log.e("tag", "传输错误!");break;}try {Thread.sleep(100);//100ms一次} catch (InterruptedException e1) {break;}}}
这里我们要注意:point数组是float型,首先,我们需强制转换为int型(应该问题不大吧),之后,将int转byte,一个int对应四个byte。一次发一个坐标,两个int,对应8个byte。

public byte[] intToByteArray(int i) {byte[] result = new byte[4];// 由高位到低位result[0] = (byte) ((i >> 24) & 0xFF);result[1] = (byte) ((i >> 16) & 0xFF);result[2] = (byte) ((i >> 8) & 0xFF);result[3] = (byte) (i & 0xFF);return result;}
方法二:等画完轨迹之后,对轨迹进行解析,找到关键点并向下位机发送多项式系数(发现不太靠谱!!!)。
这个方法的思想是:1.找轮廓;2.提取关键点;3.曲线拟合;4,将各项系数发送至下位机
关键代码:

处理完图片并开启发送数据的线程:

if (true == ImageProcess()) {DeliveryThread = new Thread(this);// 连接上了就开始传输吧DeliveryThread.start();}
图片处理:
public boolean ImageProcess() {Log.e("tag", "go into the picture analysis");Log.i("tag", "init the matrix");mRgba = new Mat();mGray = new Mat();Utils.bitmapToMat(mImage, mRgba);Imgproc.cvtColor(mRgba, mGray, Imgproc.COLOR_RGB2GRAY);// 图像二值化Mat thresholdImg = mGray;Imgproc.adaptiveThreshold(mGray, thresholdImg, 255,Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY_INV,7, 7);// 找轮廓List<MatOfPoint> contours = new ArrayList<MatOfPoint>();Mat hierarchy = new Mat();Imgproc.findContours(thresholdImg, contours, hierarchy,Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_NONE);List<Point> selectPoints = new ArrayList<Point>();// 存储精简后的关键点// 将点存入数组当中int SampleTime = 20;// 精简倍数if (contours != null && contours.size() > 0) {Log.i("tag", "轮廓个数=" + contours.size());Log.i("tag", "点个数=" + contours.get(0).size().height);// Log.i("tag","..="+contours.get(1).size().height);keyPoints = new byte[((int) (contours.get(0).size().height))/ SampleTime][8];// 两个int,相当于8个byteint num = 0;int count = 0;org.opencv.core.Point[] points = contours.get(0).toArray();//选择最大的轮廓try {// 在SD卡目录下创建.txt文件,true表示当文件存在时,信息追加在文件尾writeFile = new FileOutputStream("/sdcard/Pic.txt", true);writer = new OutputStreamWriter(writeFile, "gb2312");} catch (Exception e) {try {writeFile.close();writer.close();} catch (IOException e1) {}}for (org.opencv.core.Point point : points) {// 遍历每一个point// Log.i("tag", "x=" + point.x + ",y=" + point.y);count++;if (count == SampleTime) {// SampleTime个点采样一个点count = 0;Point selectPoint = new Point(point.x, point.y);selectPoints.add(selectPoint);byte[] temp_byte = new byte[4];temp_byte = intToByteArray((int) point.x);keyPoints[num][0] = temp_byte[0];keyPoints[num][1] = temp_byte[1];keyPoints[num][2] = temp_byte[2];keyPoints[num][3] = temp_byte[3];temp_byte = intToByteArray((int) point.y);keyPoints[num][4] = temp_byte[0];keyPoints[num][5] = temp_byte[1];keyPoints[num][6] = temp_byte[2];keyPoints[num][7] = temp_byte[3];num++;// 写入txt文档中try {writer.write(String.valueOf((int) point.x));writer.write(" ");//空格writer.write(String.valueOf((int) point.y));writer.write("\r\n");//回车换行writer.flush();} catch (IOException e) {try {writeFile.close();writer.close();} catch (IOException e1) {}}}}try {writer.close();writeFile.close();} catch (Exception e) {}Log.i("tag", "存储完毕!");}// 在原来的彩图中画出所有轮廓Imgproc.drawContours(mRgba, contours, -1, new Scalar(255, 0, 255));// 将关键点画出在原来的彩图中for (int i = 0; i < selectPoints.size(); i++) {Point center = new Point(selectPoints.get(i).x,selectPoints.get(i).y);Core.circle(mRgba, center, 4, new Scalar(0, 0, 255), 2);Core.putText(mRgba, String.valueOf(i+1), new Point(center.x,center.y), Core.FONT_HERSHEY_SIMPLEX, 0.5, new Scalar(0, 255, 0));}Core.putText(mRgba, "Key Points Number:"+selectPoints.size(), new Point(0,100), Core.FONT_HERSHEY_SIMPLEX, 1, new Scalar(255, 0, 255));Mat showMat = mRgba;// 要在MainActivity中显示的图像矩阵BmpDis = Bitmap.createBitmap(showMat.width(), showMat.height(),Config.RGB_565);Utils.matToBitmap(showMat, BmpDis);MainActivity.mImage = BmpDis;// 在MainActivity中显示mAnalysisState = ANALYSIS_OK;return true;}
发送线程和方法一差不多,这里就不说了。



上图为拟合曲线图与关键点图,红线为拟合后的曲线图。可以看出,效果不太好。换一个试试:


效果也不太好!!!图形太复杂,拟合不出。之后有待研究~

0 0
原创粉丝点击