使用python PIL将RGB图像转换为纯黑白图像

问题描述:

我正在使用Python图像库进行一些非常简单的图像处理,但是我无法将灰度图像转换为单色(黑白) 图片。如果我在将图像更改为灰度(转换('L'))后保存,则图像将如您所期望的那样呈现。但是,如果我将图像转换为单色,单波段图像,就会发出噪音,如下图所示。有没有一种简单的方法使用PIL/python将纯色黑白图像的颜色PNG图像?使用python PIL将RGB图像转换为纯黑白图像

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

+0

从[PIL文档】(http://www.pythonware.com/library/pil/handbook/image.htm): “”“当转换为二值图像(模式 ”1“),首先将源图像转换为黑色和白色,然后将大于127的结果值设置为白色,并且图像抖动。要使用其他阈值,请使用点方法。“”“” 这听起来有关,但我'我不熟悉PIL和图像处理。 – Darthfett 2012-02-29 21:31:47

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

产量

enter image description here

+0

感谢你们,我从另一段代码中使用了imsave - 我没有意识到这将是一个问题的根源。 – user714852 2012-03-01 13:36:05

通过unutbu所获得的结果来看我断定SciPy的的imsave不理解单色(模式1)的图像。

+0

我怀疑你是对的 - 很奇怪。 – user714852 2012-03-01 13:35:21

另一种选择(这很有用。比如用于科学目的,当你需要与分割掩码工作)被简单地套用一个门槛:

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

它看起来像这样为./binarize.py -i convert_image.png -o result_bin.png --threshold 200

enter image description here

+3

'binarize_array'的一行代码(我猜的更快): 'numpy.where(numpy_array> threshold = 200,255,0)' – Jacquot 2016-06-03 14:40:08

+0

这对我的谷歌搜索只适用于将图像转换为黑白图像... 谢谢! – LampShade 2016-08-22 07:04:31

因为从PIL convert("1")返回值“True”或“False”。尝试打印它,将显示:[False, False, True]单支架。

虽然numpy数组使用双托架,例如[[False, False, True]][[0, 0, 1]],对吧?

正如Martin Thoma所说,你需要正常应用阈值。但是你可以使用简单的矢量化来实现这一点,该矢量化将比用于该答案的for循环快得多。

下面的代码将图像的像素转换为0(黑色)和1(白色)。

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