No se puede obtener el warpPerspective de OpenCV para trabajar en Android
He estado luchando para implementar un sistema de cuatro a cuatro en mi aplicación de Android. El objetivo es dejar que el usuario tome una imagen, añadir 4 puntos de esquina y tener ese quad extraído de la imagen como un rectángulo.
He echado un vistazo a este método y esta pregunta para usar OpenCV para esto. El código resultante es el siguiente:
- Convertir mapa de bits de Android a OpenCV Mat y hacia atrás
- Decodificación de flujo de vídeo en Android de DJI drone
- OpenCV: detección de puntos / discos circulares de dominó
- Android - openCV, obtener parte de la imagen - comportamiento extraño
- Construya un subconjunto de OpenCV solamente (en particular para Android)
public static Bitmap warp(Bitmap image, MyPoint p1, MyPoint p2, MyPoint p3, MyPoint p4) { int resultWidth = 500; int resultHeight = 500; Mat inputMat = new Mat(image.getHeight(), image.getHeight(), CvType.CV_8UC4); Utils.bitmapToMat(image, inputMat); Mat outputMat = new Mat(resultWidth, resultHeight, CvType.CV_8UC4); Point ocvPIn1 = new Point(p1.getX(), p1.getY()); Point ocvPIn2 = new Point(p2.getX(), p2.getY()); Point ocvPIn3 = new Point(p3.getX(), p3.getY()); Point ocvPIn4 = new Point(p4.getX(), p4.getY()); List<Point> source = new ArrayList<Point>(); source.add(ocvPIn1); source.add(ocvPIn2); source.add(ocvPIn3); source.add(ocvPIn4); Mat startM = Converters.vector_Point2f_to_Mat(source); Point ocvPOut1 = new Point(0, 0); Point ocvPOut2 = new Point(0, resultHeight); Point ocvPOut3 = new Point(resultWidth, resultHeight); Point ocvPOut4 = new Point(resultWidth, 0); List<Point> dest = new ArrayList<Point>(); dest.add(ocvPOut1); dest.add(ocvPOut2); dest.add(ocvPOut3); dest.add(ocvPOut4); Mat endM = Converters.vector_Point2f_to_Mat(dest); Mat perspectiveTransform = new Mat(3, 3, CvType.CV_32FC1); Core.perspectiveTransform(startM, endM, perspectiveTransform); Imgproc.warpPerspective(inputMat, outputMat, perspectiveTransform, new Size(resultWidth, resultHeight), Imgproc.INTER_CUBIC); Bitmap output = Bitmap.createBitmap(resultWidth, resultHeight, Bitmap.Config.RGB_565); Utils.matToBitmap(outputMat, output); return output; }
Durante la prueba, me aseguro de que el orden de los puntos de esquina sea superior izquierda, inferior izquierda, inferior derecha, superior derecha.
Lo extraño es que el resultado no es siempre el mismo. La mayoría de las veces muestra un cuadrado de un solo color, a veces un cuadrado negro, a veces una línea diagonal con diferentes colores en él. Incluso la experimentación con startM = endM
da lugar a un comportamiento no determinista.
¿Que me estoy perdiendo aqui?
- Detección de objetos con OpenCV SVM
- OpenCV se bloquea después de un corto período de tiempo en la aplicación para Android
- No se puede importar las clases import android.hardware.camera2
- Guardar los vectores de características de ORB usando OpenCV4Android (java API)
- Cómo agregar punto a MatOfPoint2f?
- OpenCV obtiene píxeles negros dentro del límite del contorno
- Android 4.2 ndk: error de carga de la biblioteca: load_library (linker.cpp: 750) || soinfo_link_image || libhoudini.so || opencv
- UnsatisfiedLinkError: n_Mat mientras se usa opencv2.4.3 con android 4.0
Lo encontré, el problema estaba en estas líneas:
Mat perspectiveTransform = new Mat(3, 3, CvType.CV_32FC1); Core.perspectiveTransform(startM, endM, perspectiveTransform);
Cuál debe ser substituido por esto:
Mat perspectiveTransform = Imgproc.getPerspectiveTransform(startM, endM);
Tuve algunos problemas con su código, así que hice cambios hasta que obtuve una versión de trabajo, aquí está mi código si alguien tenía problemas con el código de la pregunta:
Bitmap warp(Bitmap image, Point topLeft, Point topRight, Point bottomLeft, Point bottomRight) { int resultWidth = (int)(topRight.x - topLeft.x); int bottomWidth = (int)(bottomRight.x - bottomLeft.x); if(bottomWidth > resultWidth) resultWidth = bottomWidth; int resultHeight = (int)(bottomLeft.y - topLeft.y); int bottomHeight = (int)(bottomRight.y - topRight.y); if(bottomHeight > resultHeight) resultHeight = bottomHeight; Mat inputMat = new Mat(image.getHeight(), image.getHeight(), CvType.CV_8UC1); Utils.bitmapToMat(image, inputMat); Mat outputMat = new Mat(resultWidth, resultHeight, CvType.CV_8UC1); List<Point> source = new ArrayList<>(); source.add(topLeft); source.add(topRight); source.add(bottomLeft); source.add(bottomRight); Mat startM = Converters.vector_Point2f_to_Mat(source); Point ocvPOut1 = new Point(0, 0); Point ocvPOut2 = new Point(resultWidth, 0); Point ocvPOut3 = new Point(0, resultHeight); Point ocvPOut4 = new Point(resultWidth, resultHeight); List<Point> dest = new ArrayList<>(); dest.add(ocvPOut1); dest.add(ocvPOut2); dest.add(ocvPOut3); dest.add(ocvPOut4); Mat endM = Converters.vector_Point2f_to_Mat(dest); Mat perspectiveTransform = Imgproc.getPerspectiveTransform(startM, endM); Imgproc.warpPerspective(inputMat, outputMat, perspectiveTransform, new Size(resultWidth, resultHeight)); Bitmap output = Bitmap.createBitmap(resultWidth, resultHeight, Bitmap.Config.ARGB_8888); Utils.matToBitmap(outputMat, output); return output; }
- ObservableInt causa bloqueo en DataBinding Library
- Cómo utilizar el compilador arm-linux-androideabi