Utiliser python PIL pour transformer une image RGB en une image en noir et blanc pur

j'utilise la bibliothèque D'imagerie Python pour une manipulation d'image très simple, mais j'ai de la difficulté à convertir une image à l'échelle de gris en une image monochrome (en noir et blanc). Si je sauve après avoir changé l'image en greyscale (convert ('L')), alors l'image rend ce que vous attendez. Cependant, si je convertis l'image en une image monochrome à bande simple, cela me donne juste du bruit comme vous pouvez le voir dans les images ci-dessous. Existe-t-il un moyen simple de transformer une image png en une image en noir et blanc pur? utiliser PIL / python?

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 ImageConverted Image

38
demandé sur user714852 2012-03-01 01:23:25

6 réponses

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')

les rendements

enter image description here

56
répondu unutbu 2015-12-14 12:44:50

une autre option (qui est utile par exemple à des fins scientifiques lorsque vous devez travailler avec des masques de segmentation) est simplement d'appliquer un seuil:

#!/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)

ça ressemble à Ça pour ./binarize.py -i convert_image.png -o result_bin.png --threshold 200:

enter image description here

17
répondu Martin Thoma 2017-11-28 17:28:23

comme Martin Thoma l'a dit, vous devez normalement appliquer le seuil. Mais vous pouvez le faire en utilisant la vectorisation simple qui fonctionnera beaucoup plus vite que la boucle for qui est utilisée dans cette réponse.

Le code ci-dessous convertit les pixels d'une image en 0 (noir) et 1 (blanc).

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()
6
répondu RajV 2017-03-08 15:22:07

en Juger par les résultats obtenus par unutbu je conclus que scipy est imsave ne comprend pas les images monochromes (mode 1).

5
répondu Mark Ransom 2017-05-23 12:10:26

une solution PIL only pour créer une image bi-niveau (en noir et blanc) avec un seuil personnalisé:

from PIL import Image
img = Image.open('mB96s.png')
thresh = 200
fn = lambda x : 255 if x > thresh else 0
r = img.convert('L').point(fn, mode='1')
r.save('foo.png')

Avec

r = img.convert('1')
r.save('foo.png')

vous obtenez une image tramée.

4
répondu maxschlepzig 2018-04-29 19:47:10

parce que de PIL convert("1") retourner la valeur "True" ou "False". Essayez d'imprimer, sera afficher: [False, False, True] avec un seul support.

alors que le tableau nummpy utilise un double bracket comme ceci [[False, False, True]] ou [[0, 0, 1]], droit?

-2
répondu Alam Katon 2016-06-10 10:20:20