J'utilise la bibliothèque d'imagerie Python) pour une manipulation d'image très simple, mais je ne parviens pas à convertir une image en niveaux de gris en image monochrome (noir et blanc). image en niveaux de gris (convertir ('L')), l'image sera alors rendue comme il se doit. Toutefois, si je convertis l'image en une image monochrome monobande, elle me donne simplement du bruit, comme vous pouvez le voir dans les images ci-dessous. existe-t-il un moyen simple de transformer une image png couleur en une image noir et blanc pure à l’aide de 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)
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
Une autre option (utile par exemple à des fins scientifiques lorsque vous devez utiliser des masques de segmentation) consiste simplement à 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 __== "__main__":
args = get_parser().parse_args()
binarize_image(args.input, args.output, args.threshold)
Cela ressemble à ceci pour ./binarize.py -i convert_image.png -o result_bin.png --threshold 200
:
Une solution PIL uniquement pour créer une image à deux niveaux (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 juste
r = img.convert('1')
r.save('foo.png')
vous obtenez une image tramée.
De gauche à droite, l'image d'entrée, le résultat de la conversion en noir et blanc et le résultat du tramage:
Vous pouvez cliquer sur les images pour voir les versions non mises à l'échelle.
Comme l'a dit Martin Thoma, vous devez normalement appliquer le seuillage. Mais vous pouvez le faire en utilisant une vectorisation simple qui fonctionnera beaucoup plus rapidement que la boucle for 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()
A en juger par les résultats obtenus par nutb , je conclus que imsave
de Scipy ne comprend pas les images monochromes (mode 1).
Un moyen simple de le faire en utilisant python:
Python
import numpy as np
import imageio
image = imageio.imread(r'[image-path]', as_gray=True)
# getting the threshold value
thresholdValue = np.mean(image)
# getting the dimensions of the image
xDim, yDim = image.shape
# turn the image into a black and white image
for i in range(xDim):
for j in range(yDim):
if (image[i][j] > thresholdValue):
image[i][j] = 255
else:
image[i][j] = 0