Я хочу использовать маркер Aruco для определения местоположения Якоря объекта в Arcore в Android, поскольку обнаружение плоскости Arcore примерно неустойчиво.
Однако я не знаю, как преобразовать позиция маркера Aruco, обнаруженная opencv на основе результатов эстимейла оценки PoseSingleMarkers ().
Не могли бы вы мне ответить, чтобы исправить код в [Как выполнить следующий код] или дать некоторую информацию о преобразовании из от Aruco до ARCore?
- Настройка разработки:
Модуль Opencv:
Добавлено ниже строки в сборке. gradle (Модуль)
реализация 'com.quickbirdstud ios: opencv: 3.4.4-contrib'
Исходный код формы:
Пример проекта hellosceneform в Sceneform SDK 1.14.0
Результат:
После выполнения следующего кода 3D-модель Andy может быть показана и перемещена маркером Aruco. Но Энди не находится в маркере Аруко.
Youtube:
https://www.youtube.com/watch?v=WAW6JgH52UA
Github:
https://github.com/qaplqq/hellosceneformaruco
- Код:
Befor OnCreate Event:
private Node node=new Node();
private CameraBridgeViewBase javaCameraView;
Mat cameraMatrix = new Mat(3,3,CvType.CV_32FC1);
MatOfDouble distorsionMatrix= new MatOfDouble();
BaseLoaderCallback baseLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
super.onManagerConnected(status);
switch (status) {
case BaseLoaderCallback.SUCCESS: {
javaCameraView.enableView();
break;
}
default: {
super.onManagerConnected(status);
break;
}
}
}
};
static {
if (OpenCVLoader.initDebug()) {
Log.i(TAG, "opencv loaded");
} else {
Log.i(TAG, "opencv not loaded");
}
}
In OnCreate Event:
// disable plane detect
arFragment.getPlaneDiscoveryController().hide();
arFragment.getPlaneDiscoveryController().setInstructionView(null);
arFragment.getArSceneView().getPlaneRenderer().setEnabled(false);
cameraMatrix.put(0,0, 469.7718, 0, 259.0107,
0, 469.5324, 251.2255,
0, 0, 1.0000);
double[] distArray = { -0.1007,
0.2118,
0,
0,
-0.6476};
distorsionMatrix.fromArray(distArray);
ModelRenderable.builder()
.setSource(this, R.raw.andy)
.build()
.thenAccept(renderable -> {
andyRenderable = renderable;
Scene sce = arFragment.getArSceneView().getScene();
if(andyRenderable!= null){
node.setParent(sce);
node.setLocalPosition(new Vector3(0f, -2f, -7f));
node.setLocalScale(new Vector3(3f, 3f, 3f));
node.setRenderable(andyRenderable);
sce.addChild(node);
}
})
.exceptionally(
throwable -> {
Toast toast =
Toast.makeText(this, "Unable to load andy renderable", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
return null;
});
arFragment.getArSceneView().getScene().addOnUpdateListener(frameTime -> {
arFragment.onUpdate(frameTime);
onUpdate();
});
// end of OnCreate Event
private void onUpdate() {
Frame frame = arFragment.getArSceneView().getArFrame();
if (frame == null) {
return;
}
try (Image image = frame.acquireCameraImage()) {
if (image.getFormat() != ImageFormat.YUV_420_888) {
throw new IllegalArgumentException(
"Expected image in YUV_420_888 format, got format " + image.getFormat());
}
Mat mat1 = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC1);
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
mat1.put(0, 0, bytes);
Dictionary dictionary = Aruco.getPredefinedDictionary(Aruco.DICT_4X4_50);
Mat ids = new Mat();
List<Mat> corners = new ArrayList<>();
Aruco.detectMarkers(mat1, dictionary, corners, ids);
if (corners.size()>0) {
Mat rvecs = new Mat();
Mat tvecs = new Mat();
Aruco.estimatePoseSingleMarkers(corners, 100f, cameraMatrix, distorsionMatrix, rvecs, tvecs);
double[] mvalr1 = rvecs.row(0).get(0, 0);
double[] mvalt1 = tvecs.row(0).get(0, 0);
String strl1 = String.format("%.1f",mvalt1[0]) + "," + String.format("%.1f",mvalt1[1]) ;
float x1 = (float) mvalt1[0];
float y1 = (float) mvalt1[1];
float z1 = (float) mvalt1[2];
Log.d(TAG, "Aruco: "+strl1 +":"+x1+","+y1+","+z1 );
// How to How to transform positions to x1, y1, z1 in arcore's coordination?
node.setLocalPosition(new Vector3(x1/10, y1/10, -7f));
// I fix z in -7f, since it is an easy way to find Andy in testing