最近在帮朋友搞一个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接口:
@Override public void run() { // TODO Auto-generated method stub while (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; }方法二:等画完轨迹之后,对轨迹进行解析,找到关键点并向下位机发送多项式系数(发现不太靠谱!!!)。
处理完图片并开启发送数据的线程:
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个byte int 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; }发送线程和方法一差不多,这里就不说了。
上图为拟合曲线图与关键点图,红线为拟合后的曲线图。可以看出,效果不太好。换一个试试:
效果也不太好!!!图形太复杂,拟合不出。之后有待研究~