tutorial seguidor por objetos linea imagenes español deteccion colores color python opencv image-processing geometry detect

seguidor - Python y OpenCV. ¿Cómo detecto todos los círculos(rellenos)/objetos redondos en una imagen?



opencv y python (3)

Eche un vistazo a mi respuesta a esta pregunta para ver un código fuente que funciona (es C, pero utilicé un compilador de C ++ porque es más indulgente).

Primero, recorté su imagen (para obtener algo conveniente para trabajar) y apliqué un umbral a su imagen para separar el primer plano del fondo:

Luego apliqué directamente el código fuente a la imagen con umbral. Aquí está la salida de texto:

center x: 330 y: 507 A: 13 B: 4 center x: 78 y: 507 A: 22 B: 4 center x: 270 y: 503 A: 8 B: 8 center x: 222 y: 493 A: 21 B: 17 center x: 140 y: 484 A: 17 B: 18 center x: 394 y: 478 A: 17 B: 15 center x: 311 y: 468 A: 8 B: 8 center x: 107 y: 472 A: 12 B: 12 center x: 7 y: 472 A: 6 B: 19 center x: 337 y: 442 A: 10 B: 9 center x: 98 y: 432 A: 10 B: 10 center x: 357 y: 421 A: 7 B: 7 center x: 488 y: 429 A: 22 B: 23 center x: 411 y: 400 A: 13 B: 12 center x: 42 y: 400 A: 11 B: 12 center x: 365 y: 391 A: 14 B: 13 center x: 141 y: 396 A: 19 B: 19 center x: 9 y: 379 A: 8 B: 18 center x: 192 y: 365 A: 10 B: 9 center x: 347 y: 340 A: 20 B: 20 center x: 8 y: 305 A: 7 B: 13 center x: 95 y: 308 A: 23 B: 24 center x: 318 y: 297 A: 15 B: 15 center x: 159 y: 285 A: 10 B: 10 center x: 412 y: 291 A: 26 B: 27 center x: 504 y: 278 A: 6 B: 16 center x: 233 y: 277 A: 20 B: 20 center x: 459 y: 256 A: 15 B: 15 center x: 7 y: 239 A: 6 B: 9 center x: 377 y: 239 A: 14 B: 14 center x: 197 y: 228 A: 12 B: 12 center x: 302 y: 237 A: 12 B: 22 center x: 98 y: 224 A: 24 B: 23 center x: 265 y: 203 A: 18 B: 18 center x: 359 y: 202 A: 22 B: 22 center x: 149 y: 201 A: 20 B: 21 center x: 219 y: 169 A: 7 B: 9 center x: 458 y: 172 A: 20 B: 20 center x: 497 y: 157 A: 13 B: 21 center x: 151 y: 125 A: 18 B: 17 center x: 39 y: 109 A: 9 B: 10 center x: 81 y: 116 A: 20 B: 19 center x: 249 y: 104 A: 14 B: 13 center x: 429 y: 76 A: 23 B: 24 center x: 493 y: 33 A: 11 B: 10 center x: 334 y: 26 A: 12 B: 14

Y aquí está la imagen de salida:

El problema principal es que los círculos que se han fusionado no se han detectado en absoluto. El código se escribió originalmente solo para detectar puntos suspensivos rellenos, por lo que probablemente pueda resolver este problema al modificar el código.

Estoy tratando de hacer un programa que abra una imagen, la escanee en busca de círculos / formas redondas y devuelva las coordenadas para que pueda usar la función cv.Circle para dibujar círculos sobre el círculo detectado.

Mi pregunta es: ¿Cómo obtengo las coordenadas / radios de los círculos detectados en una imagen usando cv.HoughCircles() ?

Al usar this página, descubrí cómo detectar los círculos (lo cual me llevó mucho tiempo para averiguarlo, ya que no entiendo términos como umbral y la documentación de OpenCV para Python es realmente mala, casi ninguno). Desafortunadamente, en esa página no se muestra cómo extraer la información de cada círculo detectado desde el CvMat creado. ¿Cómo extraigo esa información / hay alguna otra forma (por ejemplo, con MemoryStorage() )?

Este es mi código hasta ahora:

import cv, opencv def main(): im = cv.LoadImageM("Proba.jpg") gray = cv.CreateImage(cv.GetSize(im), 8, 1) edges = cv.CreateImage(cv.GetSize(im), 8, 1) cv.CvtColor(im, gray, cv.CV_BGR2GRAY) cv.Canny(gray, edges, 50, 200, 3) cv.Smooth(gray, gray, cv.CV_GAUSSIAN, 9, 9) storage = cv.CreateMat(im.rows, 1, cv.CV_32FC3) cv.HoughCircles(edges, storage, cv.CV_HOUGH_GRADIENT, 2, gray.height/4, 200, 100) # Now, supposing it found circles, how do I extract the information? print storage.r if __name__ == ''__main__'': main()

Además, ¿qué valor deben tener los últimos dos parámetros de HoughCircles para que pueda detectar círculos realmente pequeños (como 3 mm en la pantalla)?

¡Gracias a todos por su tiempo y esfuerzo tratando de ayudarme!

La imagen con la que estoy trabajando es la siguiente:


Los dos últimos parámetros son los que parecen pasarse a cv.Canny() , lo que implica que se llama a cv.HoughCircles() desde dentro de cv.HoughCircles() . No estoy muy seguro de eso.

En cuanto a los tamaños, parece que los dos parámetros siguientes (después de 200, 100) ponen por defecto en 0 , lo que podría significar que se detectan todos los tamaños.

De la fuente del ejemplo de C ++, también puedo suponer que no es necesario hacer una detección de borde de Canny:

#include <cv.h> #include <highgui.h> #include <math.h> using namespace cv; int main(int argc, char** argv) { Mat img, gray; if( argc != 2 && !(img=imread(argv[1], 1)).data) return -1; cvtColor(img, gray, CV_BGR2GRAY); // smooth it, otherwise a lot of false circles may be detected GaussianBlur( gray, gray, Size(9, 9), 2, 2 ); vector<Vec3f> circles; HoughCircles(gray, circles, CV_HOUGH_GRADIENT, 2, gray->rows/4, 200, 100 ); for( size_t i = 0; i < circles.size(); i++ ) { Point center(cvRound(circles[i][0]), cvRound(circles[i][1])); int radius = cvRound(circles[i][2]); // draw the circle center circle( img, center, 3, Scalar(0,255,0), -1, 8, 0 ); // draw the circle outline circle( img, center, radius, Scalar(0,0,255), 3, 8, 0 ); } namedWindow( "circles", 1 ); imshow( "circles", img ); return 0; }

Estás tratando de convertir este código C ++ en Python, supongo?

for( size_t i = 0; i < circles.size(); i++ ) { Point center(cvRound(circles[i][0]), cvRound(circles[i][1])); int radius = cvRound(circles[i][2]); // draw the circle center circle( img, center, 3, Scalar(0,255,0), -1, 8, 0 ); // draw the circle outline circle( img, center, radius, Scalar(0,0,255), 3, 8, 0 ); }

Por lo que puedo decir, los objetos CvMat son iterables, como una lista:

for circle in storage: radius = circle[2] center = (circle[0], circle[1]) cv.Circle(im, center, radius, (0, 0, 255), 3, 8, 0)

No tengo ninguna imagen de prueba, así que no tome mi palabra de que esto funciona. Su código completo podría ser:

import cv def main(): im = cv.LoadImage(''Proba.jpg'') gray = cv.CreateImage(cv.GetSize(im), 8, 1) edges = cv.CreateImage(cv.GetSize(im), 8, 1) cv.CvtColor(im, gray, cv.CV_BGR2GRAY) #cv.Canny(gray, edges, 20, 55, 3) storage = cv.CreateMat(im.width, 1, cv.CV_32FC3) cv.HoughCircles(edges, storage, cv.CV_HOUGH_GRADIENT, 5, 25, 200, 10) for i in xrange(storage.width - 1): radius = storage[i, 2] center = (storage[i, 0], storage[i, 1]) print (radius, center) cv.Circle(im, center, radius, (0, 0, 255), 3, 8, 0) cv.NamedWindow(''Circles'') cv.ShowImage(''Circles'', im) cv.WaitKey(0) if __name__ == ''__main__'': main()


Una solución similar en python. Originalmente intenté ejecutar una detección de contorno descrita here , pero no funcionó bien. Así que primero fue necesario un cierto umbral. El código para el umbral está aquí:

fimg = misc.imread("boubles.jpg") gimg = color.colorconv.rgb2grey(fimg) vimg = [] for l in gimg: l2 = sign(l - 0.50) / 2 + 0.5 vimg.append(l2) img = array(vimg) imshow(img)

Con esto me sale una imagen como esta:

Y después de la detección de bordes descrita en el enlace anterior, obtuve esto:

Si verifica el código, encontrará que es realmente fácil contar los objetos. El único problema es que algunas de las burbujas se cuentan dos veces. Y supongo que la función de umbral también se puede mejorar. Pero sugiero usar skimage, es fácil de usar y tiene buenas muestras en su página web.