2012-02-29 79 views
32

Estoy utilizando la biblioteca de imágenes de Python para una manipulación de imagen muy simple, sin embargo tengo problemas para convertir una imagen en escala de grises en monocromo (blanco y negro) imagen. Si guardo después de cambiar la imagen a escala de grises (convertir ('L')), la imagen se renderiza como era de esperar. Sin embargo, si convierto la imagen en monocromática, de banda única, solo me da ruido, como puede ver en las imágenes a continuación. ¿Hay una forma simple de tomar una imagen png de color a una imagen pura en blanco y negro usando PIL/python?Usando python PIL para convertir una imagen RGB en una imagen pura en blanco y negro

from PIL import Image 
import ImageEnhance 
import ImageFilter 
from scipy.misc import imsave 
image_file = Image.open("convert_image.png") # open colour image 
image_file= image_file.convert('L') # convert image to monochrome - this works 
image_file= image_file.convert('1') # convert image to black and white 
imsave('result_col.png', image_file) 

Original Image Converted Image

+0

Desde el [documentación PIL] (http://www.pythonware.com/library/pil/handbook/image.htm): "" "Al convertir una imagen de dos niveles en el modo ("1"), la imagen de origen se convierte primero en blanco y negro. Los valores resultantes mayores de 127 se configuran en blanco y la imagen se difumina Para usar otros umbrales, use el método de puntos. "" " Esto suena relacionado, pero yo ' m no estoy familiarizado con el PIL y la manipulación de la imagen. – Darthfett

Respuesta

48
from PIL import Image 
image_file = Image.open("convert_image.png") # open colour image 
image_file = image_file.convert('1') # convert image to black and white 
image_file.save('result.png') 

rendimientos

enter image description here

+0

Gracias por esto, estaba usando imsave de otro código: no me di cuenta de que sería la fuente de un problema. – user714852

3

a juzgar por los resultados obtenidos por unutbu que concluyen de que scipy imsave no entiende monocromática (modo 1) imágenes.

+0

Sospecho que tienes razón, muy extraño. – user714852

13

Otra opción (que es útil por ejemplo para fines científicos cuando se necesita trabajar con máscaras de segmentación) es simplemente aplicar un umbral:

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

"""Binarize (make it black and white) an image with Python.""" 

from PIL import Image 
from scipy.misc import imsave 
import numpy 


def binarize_image(img_path, target_path, threshold): 
    """Binarize an image.""" 
    image_file = Image.open(img_path) 
    image = image_file.convert('L') # convert image to monochrome 
    image = numpy.array(image) 
    image = binarize_array(image, threshold) 
    imsave(target_path, image) 


def binarize_array(numpy_array, threshold=200): 
    """Binarize a numpy array.""" 
    for i in range(len(numpy_array)): 
     for j in range(len(numpy_array[0])): 
      if numpy_array[i][j] > threshold: 
       numpy_array[i][j] = 255 
      else: 
       numpy_array[i][j] = 0 
    return numpy_array 


def get_parser(): 
    """Get parser object for script xy.py.""" 
    from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter 
    parser = ArgumentParser(description=__doc__, 
          formatter_class=ArgumentDefaultsHelpFormatter) 
    parser.add_argument("-i", "--input", 
         dest="input", 
         help="read this file", 
         metavar="FILE", 
         required=True) 
    parser.add_argument("-o", "--output", 
         dest="output", 
         help="write binarized file hre", 
         metavar="FILE", 
         required=True) 
    parser.add_argument("--threshold", 
         dest="threshold", 
         default=200, 
         type=int, 
         help="Threshold when to show white") 
    return parser 


if __name__ == "__main__": 
    args = get_parser().parse_args() 
    binarize_image(args.input, args.output, args.threshold) 

Parece que este para ./binarize.py -i convert_image.png -o result_bin.png --threshold 200:

enter image description here

+3

Una línea para 'binarize_array' (más rápido también, supongo): ' numpy.where (numpy_array> threshold = 200, 255, 0) ' – Jacquot

+0

Esto funciona perfectamente para mi búsqueda en Google de convertir una imagen a blanco y negro solamente ... ¡Gracias! – LampShade

0

Porque desde PIL convert("1") devuelve el valor "True" o "False". Intente imprimirlo, se mostrará: [False, False, True] con soporte individual.

Mientras que la matriz numpy utiliza doble soporte como este [[False, False, True]] o [[0, 0, 1]], ¿verdad?

2

Como ha dicho Martin Thoma, debe aplicar normalmente los umbrales. Pero puedes hacer esto usando una vectorización simple que se ejecutará mucho más rápido que el bucle for que se usa en esa respuesta.

El siguiente código convierte los píxeles de una imagen en 0 (negro) y 1 (blanco).

from PIL import Image 
import numpy as np 
import matplotlib.pyplot as plt 

#Pixels higher than this will be 1. Otherwise 0. 
THRESHOLD_VALUE = 200 

#Load image and convert to greyscale 
img = Image.open("photo.png") 
img = img.convert("L") 

imgData = np.asarray(img) 
thresholdedData = (imgData > THRESHOLD_VALUE) * 1.0 

plt.imshow(thresholdedData) 
plt.show() 
Cuestiones relacionadas