web-dev-qa-db-fra.com

Utilisation de python PIL pour transformer une image RVB 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 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)

Original ImageConverted Image

48
user714852
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

70
unutbu

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:

enter image description here

23
Martin Thoma

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:

Input ImageBlack and White ResultDithered Result

Vous pouvez cliquer sur les images pour voir les versions non mises à l'échelle.

13
maxschlepzig

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()
8
RajV

A en juger par les résultats obtenus par nutb , je conclus que imsave de Scipy ne comprend pas les images monochromes (mode 1).

5
Mark Ransom

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

0
M.Bore