背景:需要識別物體,並且測量物體的尺寸
思路:
識別物體
1、百度雲,阿里雲等有很多識別,如果有API識別,就用吧,比較容易,具體接入可以看官方文檔
2、另外一種方式就是opencv分析了。這一點我也在研究,我現在識別的代碼就不貼了。
物體尺寸測量
由於我們是根據圖片識別物體,所以返回的是某一幀的圖片上的像素點A(x1,y1)到B(x2,y2)。要轉換成空間座標系的點。再計算距離。這裏我用的基於安卓的Arcore來實現的。
好吧,廢話不多說,上代碼,獲取某一幀圖,然後發送給識別檢測的服務器
在Activity中
arFragment.getArSceneView().getScene().addOnUpdateListener(this::onUpdateFrame);
onUpdataFrame:
發送請求用的是okhttputil,在github上面搜一下就知道了 第一步:frame.acquireCameraImage();獲得某一幀圖片 第二步:OkHttpUtils.post()發送請求 第三步:List<HitResult> hitResults1 = arFragment.getArSceneView().getArFrame().hitTest(positionResults.getPositionResults().get(0).getX(), positionResults.getPositionResults().get(0).getY()); 根據返回的像素點得到空間碰撞的HitResults 第四步: showDistance(hitResults1.get(0), hitResults2.get(0));展示距離吧 private void onUpdateFrame(FrameTime frameTime) { Frame frame = arFragment.getArSceneView().getArFrame(); // If there is no frame, just return. if (frame == null) { return; }
Image image = null; try { image = frame.acquireCameraImage(); Bitmap bitmap = imageToBitmap(image); if (bitmap != null) { File file = getFile(bitmap); OkHttpUtils.post() .addFile("file", "pic" + imageIndex + ".png", file)// .url("xxxxx") .build() .execute(new Callback() { @Override public Object parseNetworkResponse(Response response, int id) throws Exception { try { String str = response.body().string(); positionResults = new Gson().fromJson(str, PositionResults.class); return positionResults; } catch (Exception e) { e.printStackTrace(); } return null; } @Override public void onError(Call call, Exception e, int id) { System.out.println("error!!!!!"); } @Override public void onResponse(Object response, int id) { System.out.println("response"); } }); List<HitResult> hitResults1 = arFragment.getArSceneView().getArFrame().hitTest(positionResults.getPositionResults().get(0).getX(), positionResults.getPositionResults().get(0).getY()); List<HitResult> hitResults2 = arFragment.getArSceneView().getArFrame().hitTest(positionResults.getPositionResults().get(1).getX(), positionResults.getPositionResults().get(1).getY()); if (hitResults1.size() > 0 && hitResults2.size() > 0) { showDistance(hitResults1.get(0), hitResults2.get(0)); } } } } catch (Exception e) { e.printStackTrace(); } finally { // sendFlag=true; if (null != image) { image.close(); } }
showDistance:
private void showDistance(HitResult hitResult1, HitResult hitResult2) { Anchor anchor1 = hitResult1.createAnchor(); AnchorNode firstAnchorNode = new AnchorNode(anchor1); Anchor anchor2 = hitResult2.createAnchor(); AnchorNode secondAnchorNode = new AnchorNode(anchor2); secondAnchorNode.setParent(arFragment.getArSceneView().getScene()); double ddx = (firstAnchorNode.getWorldPosition().x - secondAnchorNode.getWorldPosition().x); double ddy = (firstAnchorNode.getWorldPosition().y - secondAnchorNode.getWorldPosition().y); double ddz = (firstAnchorNode.getWorldPosition().z - secondAnchorNode.getWorldPosition().z); float ndl = (float) Math.sqrt(ddx * ddx + ddy * ddy + ddz * ddz);
Toast toast1 = Toast.makeText(this, "dl is" + dl + "M,firstV:(" + firstV.x + "," + firstV.y + "," + firstV.z + "),secendV:(" + secondV.x + "," + secondV.y + "," + secondV.z + ")", Toast.LENGTH_LONG); toast1.setGravity(Gravity.CENTER, 0, 0); toast1.show();
」
但是這樣還是不夠直觀,所以在兩點之間畫根直線吧
private void addLineBetweenPoints(Scene scene, Vector3 from, Vector3 to) { // prepare an anchor position Quaternion camQ = scene.getCamera().getWorldRotation(); float[] f1 = new float[]{to.x, to.y, to.z}; float[] f2 = new float[]{camQ.x, camQ.y, camQ.z, camQ.w}; Pose anchorPose = new Pose(f1, f2); // make an ARCore Anchor Anchor anchor = arFragment.getArSceneView().getSession().createAnchor(anchorPose); // Node that is automatically positioned in world space based on the ARCore Anchor. AnchorNode anchorNode = new AnchorNode(anchor); anchorNode.setParent(scene); // Compute a line's length float lineLength = Vector3.subtract(from, to).length(); // Prepare a color Color colorOrange = new Color(android.graphics.Color.parseColor("#ffa71c")); // 1. make a material by the color MaterialFactory.makeOpaqueWithColor(this, colorOrange) .thenAccept(material -> { // 2. make a model by the material ModelRenderable model = ShapeFactory.makeCylinder(0.0025f, lineLength, new Vector3(0f, lineLength / 2, 0f), material); model.setShadowReceiver(false); model.setShadowCaster(false); // 3. make node Node node = new Node(); node.setRenderable(model); node.setParent(anchorNode); // 4. set rotation final Vector3 difference = Vector3.subtract(to, from); final Vector3 directionFromTopToBottom = difference.normalized(); final Quaternion rotationFromAToB = Quaternion.lookRotation(directionFromTopToBottom, Vector3.up()); node.setWorldRotation(Quaternion.multiply(rotationFromAToB, Quaternion.axisAngle(new Vector3(1.0f, 0.0f, 0.0f), 90))); }); }
完成!