2012-06-29 10 views
11

Estoy escribiendo una aplicación de Android en OpenCV para detectar blobs. Una tarea es el umbral de la imagen para diferenciar los objetos de primer plano del fondo (ver imagen).¿Cómo obtener el valor de umbral del histograma?

Funciona bien siempre que se conozca la imagen y puedo pasar manualmente un valor de umbral a threshold() - en esta imagen concreta, digamos 200. Pero suponiendo que la imagen no se conoce con el único conocimiento de que existe sería un fondo sólido oscuro y objetos en primer plano más claros ¿cómo puedo calcular dinámicamente el valor umbral?

He encontrado el histograma donde puedo calcular la distribución de intensidad de la imagen en escala de grises. Pero no pude encontrar un método para analizar el histograma y elegir el valor donde se encuentran los objetos de interés (más claro). Es decir; Quiero diferenciar los picos de fondo obviamente oscuros de los picos más claros del primer plano, en este caso por encima de 200, pero en otro caso podría decirse, 100 si los objetos son grisáceos.

enter image description here

+4

Hay 'sa un montón de métodos para eso. Tal vez el Método de Otsu podría funcionar para ti. Si no, sigue siendo un buen punto de partida en mi humilde opinión. http://en.wikipedia.org/wiki/Otsu%27s_Method – Florian

+0

¿Se puede subir una imagen en la que 100 umbral es bueno? Porque en la imagen encima del umbral 50 también es aceptable ... – ArtemStorozhuk

Respuesta

9

Si todas sus imágenes son así, o pueden llevarse a este estilo, creo que cv2.THRESHOLD_OTSU, es decir, el algoritmo de tressin de otsu es una buena opción.

A continuación se muestra un ejemplo usando Python en el terminal de comandos:

>>> import cv2 
>>> import numpy as np 
>>> img2 = cv2.imread('D:\Abid_Rahman_K\work_space\sofeggs.jpg',0) 

>>> ret,thresh = cv2.threshold(img2,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) 

>>> ret 
122.0 

ret es el valor umbral que se calcula automáticamente. Acabamos de pasar '0' como valor de umbral para esto.

Recibí 124 en GIMP (que es comparable al resultado que obtuvimos). Y también elimina el ruido. Ver el resultado a continuación:

enter image description here

6

Si usted dice que el fondo es oscuro (negro) y el primer plano es más ligero, entonces me recomiendan usar el YUV color space (o cualquier otra YXX como YUV, etc.), porque el primer componente de dichos espacios de color es luminancia (o lightning).

light channel

Así que después de que se extrae el canal Y (a través de la función extractChennel), es necesario analizar el histograma de este canal (imagen):

histogram

Véase el primer (izquierda) joroba? Representa las áreas oscuras (el fondo en su situación) en su imagen. Entonces, nuestro objetivo ahora es encontrar un segmento (en abscisas, es parte roja en la imagen) que contenga esta joroba. Obviamente, el punto izquierdo de este segmento es cero. El punto adecuado es el primer punto en el que:

  • el (local) máximo de histograma es de la izquierda del punto
  • el valor del histograma es menor que algún pequeño épsilon (se puede establecer a 10)

Dibujé una línea vertical verde para mostrar la ubicación del punto derecho del segmento en este histograma.

¡Y eso es todo! Este punto correcto del segmento es el umbral necesario. Aquí está el resultado (épsilon es 10 y el umbral calculado es 50):

result

Creo que no es un problema para que elimine el ruido en la imagen de arriba.

0

La siguiente es una C aplicación de la respuesta de Abid ++ que trabaja con OpenCV 3.x:

// Convert the source image to a 1 channel grayscale: 
Mat gray; 
cvtColor(src, gray, CV_BGR2GRAY); 
// Apply the threshold function with the CV_THRESH_OTSU setting as well 
// You can skip having it return the value, but I include it for showing the 
// results from OTSU 
double thresholdValue = threshold(gray, gray, 0, 255, CV_THRESH_BINARY+CV_THRESH_OTSU); 
// Present the threshold value 
printf("Threshold value: %f\n", thresholdValue); 

La ejecución de este en contra de la imagen original, me sale el siguiente: enter image description here

OpenCV calculó un valor de umbral de 122 para él, cerca del valor Abid encontrado en su respuesta.

Sólo para verificar, alteré la imagen original como se ve aquí:

enter image description here

y produjo el siguiente, con un nuevo valor umbral de 178:

enter image description here

Cuestiones relacionadas