¿Cómo encontrar los contornos de un marco de una cámara Android y convertirlos en cuerpos box2d?
Utilizando OpenFrameworks, OpenCV y Box2D pude lograrlo con una buena velocidad de fotogramas. El uso de Android parece una tarea mucho más complicada (en parte porque soy un novato JAVA).
Así es como empecé:
- Detección de números y texto posible con opencv android mientras captura de video?
- Cómo detectar (contar) el cabello de la imagen con OpenCV?
- Cómo ejecutar openCV relacionados con la aplicación, sin utilizar OpenCV manager en android
- Cómo cambiar el tamaño de una imagen a la imagen de alta resolución sin perder píxeles?
- Mejorar el rendimiento de Tesseract con OpenCV en Android
-
Utilice "OpenCV Sample – manipulaciones de imagen" y elimine todo excepto el efecto "canny", que produce una bonita imagen en blanco y negro que es perfecta para encontrar los contornos.
public Mat onCameraFrame(CvCameraViewFrame inputFrame) { mRgba = inputFrame.rgba(); Imgproc.Canny(mRgbaInnerWindow, mIntermediateMat, 50, 100); Imgproc.cvtColor(mIntermediateMat, mRgbaInnerWindow, Imgproc.COLOR_GRAY2BGRA, 4); return mRgba; }
-
Desde el "OpenCV Sample – color-blob-detection" agarré la lógica para encontrar los contornos en un Mat:
// These two lines are actually in the function onCameraViewStarted mHierarchy = new Mat(); CONTOUR_COLOR = new Scalar(255,0,0,255); // These lines are in function onCameraFrame List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); Imgproc.findContours(mRgbaInnerWindow, contours, mHierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); Imgproc.drawContours(mIntermediateMat, contours, -1, CONTOUR_COLOR);
Por lo tanto, mi función actual se parece a esto y no funciona:
public Mat onCameraFrame(CvCameraViewFrame inputFrame) { mRgba = inputFrame.rgba(); if ((mRgbaInnerWindow == null) || (mGrayInnerWindow == null) || (mRgba.cols() != mSizeRgba.width) || (mRgba.height() != mSizeRgba.height)) CreateAuxiliaryMats(); Imgproc.Canny(mRgbaInnerWindow, mIntermediateMat, 50, 100); //Imgproc.cvtColor(mIntermediateMat, mRgbaInnerWindow, Imgproc.COLOR_GRAY2BGRA, 4); List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); Imgproc.findContours(mRgbaInnerWindow, contours, mHierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); //Imgproc.drawContours(mIntermediateMat, contours, -1, CONTOUR_COLOR); return mRgba; }
-
Ahora, aquí es donde estoy atrapado. Sigo recibiendo excepciones y creo que no estoy usando las dimensiones correctas o transformar el Mat en el espacio de color adecuado. Este post tiene alguna idea pero no sé si es correcto: OpenCV en Android findContours lanza Exception
- OpenCV enfoque diferente en la detección de ir bordo
- Resolver avisos NDK obsoletos en Android Studio
- Objeto perfecto para ser reconocido con OpenCV
- Construya un subconjunto de OpenCV solamente (en particular para Android)
- ¿Se puede utilizar un android.hardware.camera2.CaptureRequest con OpenCV?
- Error: el paquete android.hardware.camera2 no existe OpenCV
- configuración de vídeo opencv a pantalla completa android
- Android + OpenCV: Cómo configurar la resolución de la cámara cuando se utiliza CameraBridgeViewBase
Hola soy también un novato en openCV sin embargo este código podría ayudar,
import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.SurfaceView; import org.opencv.android.*; import org.opencv.core.*; import org.opencv.imgproc.Imgproc; import java.util.ArrayList; import java.util.List; public class MainActivity extends Activity implements CvCameraViewListener2{ private static final String TAG = MainActivity.class.getCanonicalName(); private CameraBridgeViewBase mOpenCvCameraView; private Mat mRgba; private Mat mIntermediateMat; private Mat mGray; Mat hierarchy; List<MatOfPoint> contours; private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) { @Override public void onManagerConnected(int status) { switch (status) { case LoaderCallbackInterface.SUCCESS: { Log.i(TAG, "OpenCV loaded successfully"); mOpenCvCameraView.enableView(); } break; default: { super.onManagerConnected(status); } break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.java_surface_view); mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE); mOpenCvCameraView.setCvCameraViewListener(this); } @Override public void onResume() { super.onResume(); OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback); } @Override public void onPause() { super.onPause(); if (mOpenCvCameraView != null) mOpenCvCameraView.disableView(); } @Override public void onCameraViewStarted(int width, int height) { mRgba = new Mat(height, width, CvType.CV_8UC4); mIntermediateMat = new Mat(height, width, CvType.CV_8UC4); mGray = new Mat(height, width, CvType.CV_8UC1); hierarchy = new Mat(); } @Override public void onCameraViewStopped() { mRgba.release(); mGray.release(); mIntermediateMat.release(); hierarchy.release(); } @Override public Mat onCameraFrame(CvCameraViewFrame inputFrame) { mRgba = inputFrame.gray(); contours = new ArrayList<MatOfPoint>(); hierarchy = new Mat(); Imgproc.Canny(mRgba, mIntermediateMat, 80, 100); Imgproc.findContours(mIntermediateMat, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE, new Point(0, 0)); /* Mat drawing = Mat.zeros( mIntermediateMat.size(), CvType.CV_8UC3 ); for( int i = 0; i< contours.size(); i++ ) { Scalar color =new Scalar(Math.random()*255, Math.random()*255, Math.random()*255); Imgproc.drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, new Point() ); }*/ hierarchy.release(); Imgproc.drawContours(mRgba, contours, -1, new Scalar(Math.random()*255, Math.random()*255, Math.random()*255));//, 2, 8, hierarchy, 0, new Point()); // Imgproc.cvtColor(mIntermediateMat, mRgba, Imgproc.COLOR_GRAY2RGBA, 4); return mRgba; } }
Sé que esto puede no ser la mejor manera de lograr esto, pero estamos todos aquí para aprender nuevas maneras 🙂
Respuesta corta: findContours
utilizar el resultado de Canny
como entrada (1er argumento) para findContours
, es decir
Imgproc.findContours(mIntermediateMat, ...);
- Pasando objeto personalizado al servicio android en diferentes procesos
- ¿Cómo invalidar / forzar la actualización de la ruta de caché en la próxima solicitud con Retrofit y OKHttp?