Cómo detectar los bordes largos de la pared para preparar la máscara y recolorar

La idea principal es permitir al usuario recolorir a la pared específica basada en la selección del usuario. Actualmente he implementado esta característica usando cvFloodFill (ayuda a preparar la imagen de la máscara) que puede ayudarme a cambiar el valor relativo de HSV para la pared así que puedo conservar bordes. pero el problema con esta solución es que trabaja en color y todas las paredes se repintan en vez de la sola pared seleccionada por el usuario.

También he intentado la detección canny del borde pero apenas capaz de detectar el borde pero no capaz de convertirlo al área.

A continuación, encontrará el código que estoy utilizando actualmente para la función de repintado

  1. Preparar la máscara

    cvFloodFill(mask, new CvPoint(295, 75), new CvScalar(255, 255, 255,0), cvScalarAll(1), cvScalarAll(1), null, 4, null);

  2. canal dividido

    cvSplit(hsvImage, hChannel, sChannel, vChannel, null);

  3. cambiar color

    cvAddS(vChannel, new CvScalar(255*(0.76-0.40),0,0,0), vChannel, mask);

Cómo podemos detectar los bordes y el área correspondiente de la imagen.

Estoy buscando la solución que puede ser diferente de opencv pero debería ser posible para el iPhone y Android

Imagen de muestra

Editar

puedo alcanzar algo resultado como abajo imagen usando abajo pasos

 cvCvtColor(image, gray, CV_BGR2GRAY); cvSmooth(gray,smooth,CV_GAUSSIAN,7,7,0,0); cvCanny(smooth, canny, 10, 250, 5); 

hay dos problemas con esta salida no está seguro de cómo resolverlos 1. cerrar cerca de bordes 2. eliminar los bordes pequeños

Introduzca aquí la descripción de la imagen

Creo que podría tener la solución para usted! Hay un archivo de ejemplo llamado watershed.cpp en OpenCV, sólo ejecútelo y obtendrá este resultado:

Cuenca con sólo los puntos clave de línea corta

Puede hacer que su usuario dibuje en su pantalla para discriminar cada pared. Entonces, si desea algo más preciso, puede delinear las áreas (sin tocar otras líneas) de la siguiente manera:

Mejor esquema

¡Y TADA! :

Muy buen resultado;)

Con un poco de trabajo puede hacer que sea fácil de usar (cancelar la última línea, conectar áreas etc …)

¡Espero que ayude!

Usted podría intentar algo como:

  Mat imageOut = Mat::zeros(imageIn.rows, imageIn.cols, CV_8UC3); vector<vector<Point> > contours; vector<Vec4i> hierarchy; findContours( imageIn, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE ); for( int idx = 0; idx >= 0; idx = hierarchy[idx][0] ) { Scalar color( rand()&255, rand()&255, rand()&255 ); drawContours( imageOut, contours, idx, color, CV_FILLED, 8, hierarchy ); } 

Debe dibujar las paredes en diversos colores. Si funciona, eso significa que en "jerarquía" cada pared se identifica como un contorno, entonces usted tendrá que averiguar que el usuario seleccionó en su pantalla táctil y hacer su proceso de ajuste de color.

Puede que tenga que cambiar los diferentes parámetros en el enlace "findContours". También tendrá que suavizar la imagen de entrada antes de la detección de contorno para evitar ser molestado con los detalles o texturas.

Espero que ayude, Thomas

Creo que puedes usar el algoritmo Canny Edge Detection para encontrar la diferencia de bordes. Algunos enlaces

  1. Desbordamiento de pila
  2. Desbordamiento de pila
  3. OpenCV QA
  4. OpenCV
  5. Tutorial nativo

Espero que esto pueda ayudarte. Gracias.

Aquí está un código OpenCV4Android para encontrar el contorno más grande en una image llamada Mat , que asumiremos está en el espacio de color RGBA. Para encontrar contornos, primero es necesario limitar o binarizar la imagen (convertir a blanco y negro). El uso de un Gaussian Blur en la imagen antes del umbral reduce el número de pequeños contornos que se producen. Los parámetros de tamaño para el desenfoque y el umbral deben ser números impares; usted puede jugar alrededor para encontrar qué valor da los mejores resultados (aquí, he utilizado 7 para ambos).

 List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); Mat BW = new Mat(); Mat hierarchy = new Mat(); MatOfPoint largestContour; Imgproc.cvtColor(image, image, Imgproc.COLOR_RGBA2GRAY); // convert to grayscale Imgproc.GaussianBlur(image, BW, new Size(7,7), 0); Imgproc.adaptiveThreshold(BW, BW, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY_INV, 7, 2.0); Imgproc.findContours(BW, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); double maxArea = 0; for (MatOfPoint contour : contours) { double area = Imgproc.contourArea(contour); if (area > maxArea) { maxArea = area; largestContour = contour; } } 

hay dos problemas con esta salida no está seguro de cómo resolverlos 1. cerrar cerca de bordes 2. eliminar los bordes pequeños

  1. Puede utilizar operaciones morfológicas para cerrar los bordes. Busque los operadores de dilatación y cierre.

  2. Puede quitar los bordes pequeños haciendo etiquetas. Cuente el número de píxeles en cada región (píxeles blancos conectados). Elimine cualquier región con un número de píxeles inferior a algún umbral. No utilizo opencv, pero la mayoría de las bibliotecas tienen una función de etiquetado que creará una imagen en la que cada conjunto de píxeles conmovedores de un solo color recibirá un color único en la imagen de salida.

  • Cómo establecer un punto de inicio utilizando path () en onDraw () utilizando canvas ..?
  • Android rotar mapa de bits sin hacer una copia
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.