python - learning - Convertir una imagen de OpenCV a blanco y negro
opencv python machine learning (6)
¿Cómo se convierte una imagen de OpenCV en escala de grises a blanco y negro? Veo que ya se ha formulado una pregunta similar , pero estoy usando OpenCV 2.3, y la solución propuesta ya no parece funcionar.
Intento convertir una imagen en escala de grises en blanco y negro, para que todo lo que no sea absolutamente negro sea blanco, y usar esto como una máscara para surf.detect() , para ignorar los puntos clave encontrados en el borde del área de la máscara negra .
El siguiente Python me lleva casi hasta allí, pero el valor de umbral enviado a Threshold () no parece tener ningún efecto. Si lo configuro en 0, 16, 128 o 255, el resultado es el mismo, todos los píxeles con un valor> 128 se vuelven blancos y todo lo demás se vuelve negro.
¿Qué estoy haciendo mal?
import cv, cv2
fn = ''myfile.jpg''
im_gray = cv2.imread(fn, cv.CV_LOAD_IMAGE_GRAYSCALE)
im_gray_mat = cv.fromarray(im_gray)
im_bw = cv.CreateImage(cv.GetSize(im_gray_mat), cv.IPL_DEPTH_8U, 1);
im_bw_mat = cv.GetMat(im_bw)
threshold = 0 # 128#255# HAS NO EFFECT!?!?
cv.Threshold(im_gray_mat, im_bw_mat, threshold, 255, cv.CV_THRESH_BINARY | cv.CV_THRESH_OTSU);
cv2.imshow('''', np.asarray(im_bw_mat))
cv2.waitKey()
Enfoque 1
Al convertir una imagen en escala de grises en una imagen binaria, normalmente usamos cv2.threshold()
y establecemos un valor de umbral manualmente. A veces, para obtener un resultado decente, optamos por la binarización de Otsu .
Tengo un pequeño truco que encontré al leer algunas publicaciones en el blog.
- Convierte tu imagen de color (RGB) a escala de grises.
- Obtenga la mediana de la imagen de la escala de grises.
- Elija un valor de umbral ya sea 33% por encima de la mediana
¿Por qué el 33%?
Esto se debe a que el 33% funciona para la mayoría de las imágenes / conjuntos de datos.
También puede calcular el mismo enfoque reemplazando la median
con la mean
.
Enfoque 2
Otro enfoque sería tomar un número x
de desviaciones estándar ( std
) de la media, ya sea en el lado positivo o negativo; y establecer un umbral Entonces podría ser uno de los siguientes:
-
th1 = mean - (x * std)
-
th2 = mean + (x * std)
Nota: Antes de aplicar el umbral, es recomendable mejorar el contraste de la imagen de escala de grises localmente (consulte CLAHE ).
Al especificar CV_THRESH_OTSU
, se CV_THRESH_OTSU
el valor de umbral. De la documentación :
Además, el valor especial THRESH_OTSU se puede combinar con uno de los valores anteriores. En este caso, la función determina el valor umbral óptimo utilizando el algoritmo de Otsu y lo utiliza en lugar del umbral especificado. La función devuelve el valor de umbral calculado. Actualmente, el método de Otsu se implementa solo para imágenes de 8 bits.
Este código lee fotogramas de la cámara y realiza el umbral binario en el valor 20.
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
int main(int argc, const char * argv[]) {
VideoCapture cap;
if(argc > 1)
cap.open(string(argv[1]));
else
cap.open(0);
Mat frame;
namedWindow("video", 1);
for(;;) {
cap >> frame;
if(!frame.data)
break;
cvtColor(frame, frame, CV_BGR2GRAY);
threshold(frame, frame, 20, 255, THRESH_BINARY);
imshow("video", frame);
if(waitKey(30) >= 0)
break;
}
return 0;
}
Aquí hay un código de dos líneas que encontré en línea que podría ser útil para un principiante
# Absolute value of the 32/64
abs_image_in32_64 = np.absolute(image_in32_64)
image_8U = np.uint8(abs_image_in32_64)
Preste atención, si usa cv.CV_THRESH_BINARY
significa que cada píxel mayor que el umbral se convierte en maxValue (en su caso 255), de lo contrario el valor es 0. Obviamente, si su umbral es 0, todo se vuelve blanco (maxValue = 255) y si el valor es 255 todo se vuelve negro (es decir, 0).
Si no quieres calcular un umbral, puedes usar el método de Otsu. Pero este algoritmo solo funciona con imágenes de 8 bits en la implementación de OpenCV. Si su imagen es de 8 bits, use el algoritmo de esta manera:
cv.Threshold(im_gray_mat, im_bw_mat, threshold, 255, cv.CV_THRESH_BINARY | cv.CV_THRESH_OTSU);
No importa el valor del umbral si tiene una imagen de 8 bits.
Respuesta paso a paso similar a la que se refiere, utilizando las nuevas vinculaciones de cv2 Python:
1. Leer una imagen en escala de grises
import cv2
im_gray = cv2.imread(''grayscale_image.png'', cv2.CV_LOAD_IMAGE_GRAYSCALE)
2. Convierta la imagen en escala de grises a binaria
(thresh, im_bw) = cv2.threshold(im_gray, 128, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
que determina el umbral automáticamente a partir de la imagen usando el método de Otsu, o si ya conoce el umbral que puede usar:
thresh = 127
im_bw = cv2.threshold(im_gray, thresh, 255, cv2.THRESH_BINARY)[1]
3. Guardar en el disco
cv2.imwrite(''bw_image.png'', im_bw)
Simplemente puede escribir el siguiente fragmento de código para convertir una imagen de OpenCV en una imagen de escala de grises
import cv2
image = cv2.imread(''image.jpg'',0)
cv2.imshow(''grey scale image'',image)
Observe que la imagen.jpg y el código deben guardarse en la misma carpeta.
Tenga en cuenta que:
-
(''image.jpg'')
da una imagen RGB -
(''image.jpg'',0)
da Grey Scale Image.