Android OpenCV Encuentra la plaza o rectángulo más grande
Esto pudo haber sido contestado pero desesperadamente necesito una respuesta para esto. Quiero encontrar el cuadrado o rectángulo más grande en una imagen usando OpenCV en Android. Todas las soluciones que he encontrado son C + + y he intentado convertirlo, pero no funciona y no sé dónde me equivoco.
private Mat findLargestRectangle(Mat original_image) { Mat imgSource = original_image; Imgproc.cvtColor(imgSource, imgSource, Imgproc.COLOR_BGR2GRAY); Imgproc.Canny(imgSource, imgSource, 100, 100); //I don't know what to do in here return imgSource; }
Lo que estoy tratando de lograr aquí es crear una nueva imagen que se basa en el cuadrado más grande que se encuentra en la imagen original (valor de retorno Mat imagen).
- Imagen umbral con opencv (Java)
- Detección de objetos Android OpenCV
- OpenCV FeatureDetector
- Diferencia entre NativeCameraView y JavaCameraView en OpenCV
- OpenCV se bloquea después de un corto período de tiempo en la aplicación para Android
Esto es lo que quiero que suceda:
1 http://img14.imageshack.us/img14/7855/s7zr.jpg
También está bien que acabo de obtener los cuatro puntos de la plaza más grande y creo que puedo tomar desde allí. Pero sería mejor si pudiera devolver la imagen recortada.
- Dilatación y erosión en Android
- Convertir el marco de vista previa de Android a OpenCV Mat
- SURF Feature Extraction con Android OpenCV SDK - Obtener algunos errores
- Android no puede cargar la imagen orientada correcta desde la galería
- Android JavaCV dilema, NoClassDefFoundError lanzado dentro del método 'dibujar' cuando se crea IplImage
- Ejecutar código nativo en segundo plano
- Pasos de convertir el proyecto C ++ opencv en la computadora a opencv android
- Programación Android Camera.PreviewCallback (con OpenGL y OpenCV)
Después de canny
1- es necesario reducir los ruidos con el desenfoque gaussiano y encontrar todos los contornos
2- encontrar y listar todas las áreas de los contornos .
3- el contorno más grande no será más que la pintura.
4- ahora usa la transformación perpective para transformar tu forma en un rectángulo.
Verifique los ejemplos de sudoku solver para ver el problema de procesamiento similar. (Mayor contorno + perspectiva)
Me tomó un tiempo para convertir el código C ++ a Java, pero aquí está 🙂
Advertencia ! Código crudo, totalmente no optimizado y todo.
Rechazo cualquier responsabilidad en caso de lesiones o accidentes letales
List<MatOfPoint> squares = new ArrayList<MatOfPoint>(); public Mat onCameraFrame(CvCameraViewFrame inputFrame) { if (Math.random()>0.80) { findSquares(inputFrame.rgba().clone(),squares); } Mat image = inputFrame.rgba(); Imgproc.drawContours(image, squares, -1, new Scalar(0,0,255)); return image; } int thresh = 50, N = 11; // helper function: // finds a cosine of angle between vectors // from pt0->pt1 and from pt0->pt2 double angle( Point pt1, Point pt2, Point pt0 ) { double dx1 = pt1.x - pt0.x; double dy1 = pt1.y - pt0.y; double dx2 = pt2.x - pt0.x; double dy2 = pt2.y - pt0.y; return (dx1*dx2 + dy1*dy2)/Math.sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10); } // returns sequence of squares detected on the image. // the sequence is stored in the specified memory storage void findSquares( Mat image, List<MatOfPoint> squares ) { squares.clear(); Mat smallerImg=new Mat(new Size(image.width()/2, image.height()/2),image.type()); Mat gray=new Mat(image.size(),image.type()); Mat gray0=new Mat(image.size(),CvType.CV_8U); // down-scale and upscale the image to filter out the noise Imgproc.pyrDown(image, smallerImg, smallerImg.size()); Imgproc.pyrUp(smallerImg, image, image.size()); // find squares in every color plane of the image for( int c = 0; c < 3; c++ ) { extractChannel(image, gray, c); // try several threshold levels for( int l = 1; l < N; l++ ) { //Cany removed... Didn't work so well Imgproc.threshold(gray, gray0, (l+1)*255/N, 255, Imgproc.THRESH_BINARY); List<MatOfPoint> contours=new ArrayList<MatOfPoint>(); // find contours and store them all as a list Imgproc.findContours(gray0, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE); MatOfPoint approx=new MatOfPoint(); // test each contour for( int i = 0; i < contours.size(); i++ ) { // approximate contour with accuracy proportional // to the contour perimeter approx = approxPolyDP(contours.get(i), Imgproc.arcLength(new MatOfPoint2f(contours.get(i).toArray()), true)*0.02, true); // square contours should have 4 vertices after approximation // relatively large area (to filter out noisy contours) // and be convex. // Note: absolute value of an area is used because // area may be positive or negative - in accordance with the // contour orientation if( approx.toArray().length == 4 && Math.abs(Imgproc.contourArea(approx)) > 1000 && Imgproc.isContourConvex(approx) ) { double maxCosine = 0; for( int j = 2; j < 5; j++ ) { // find the maximum cosine of the angle between joint edges double cosine = Math.abs(angle(approx.toArray()[j%4], approx.toArray()[j-2], approx.toArray()[j-1])); maxCosine = Math.max(maxCosine, cosine); } // if cosines of all angles are small // (all angles are ~90 degree) then write quandrange // vertices to resultant sequence if( maxCosine < 0.3 ) squares.add(approx); } } } } } void extractChannel(Mat source, Mat out, int channelNum) { List<Mat> sourceChannels=new ArrayList<Mat>(); List<Mat> outChannel=new ArrayList<Mat>(); Core.split(source, sourceChannels); outChannel.add(new Mat(sourceChannels.get(0).size(),sourceChannels.get(0).type())); Core.mixChannels(sourceChannels, outChannel, new MatOfInt(channelNum,0)); Core.merge(outChannel, out); } MatOfPoint approxPolyDP(MatOfPoint curve, double epsilon, boolean closed) { MatOfPoint2f tempMat=new MatOfPoint2f(); Imgproc.approxPolyDP(new MatOfPoint2f(curve.toArray()), tempMat, epsilon, closed); return new MatOfPoint(tempMat.toArray()); }
Hay algunas preguntas relacionadas aquí en SO. Compruébelo:
-
OpenCV C ++ / Obj-C: detección de una hoja de papel / detección cuadrada
-
¿Cómo reconozco los cuadrados en esta imagen?
También hay un ejemplo enviado con OpenCV:
Una vez que tenga el rectángulo, puede alinear la imagen calculando la homografía con las esquinas del rectángulo y aplicando una transformación de perspectiva.
- Convertir la cadena de color HEX a color?
- Lectura de código de barras con foto tomada con cámara de teléfono móvil