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

使用python PIL将RGB图像转换为纯黑白图像,python,python-imaging-library,python-2.7,Python,Python Imaging Library,Python 2.7,我正在使用Python图像库进行一些非常简单的图像处理,但是在将灰度图像转换为单色(黑白)图像时遇到了问题。如果我在将图像更改为灰度(convert('L')后保存,则图像将按预期进行渲染。但是,如果我将图像转换为单色、单波段图像,它只会给我带来噪音,如下图所示。有没有一种简单的方法可以使用PIL/python将彩色png图像转换为纯黑白图像 from PIL import Image import ImageEnhance import ImageFilter from scipy.misc

我正在使用Python图像库进行一些非常简单的图像处理,但是在将灰度图像转换为单色(黑白)图像时遇到了问题。如果我在将图像更改为灰度(convert('L')后保存,则图像将按预期进行渲染。但是,如果我将图像转换为单色、单波段图像,它只会给我带来噪音,如下图所示。有没有一种简单的方法可以使用PIL/python将彩色png图像转换为纯黑白图像

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)

屈服

另一个选项(当您需要使用分段遮罩时,它非常有用,例如用于科学目的)是简单地应用阈值:

#!/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)
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')
对于
/binarize.py-i convert\u image.png-o result\u bin.png--threshold 200,它看起来是这样的:


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

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


用于创建具有自定义阈值的双层(黑白)图像的纯PIL解决方案:

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

r = img.convert('1')
r.save('foo.png')
你会得到一个抖动的图像

从左到右输入图像、黑白转换结果和抖动结果:


您可以单击图像查看未缩放的版本。

使用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


我就是这样做的它有更好的效果像一个灰色过滤器

from PIL import Image
img = Image.open("profile.png")
BaW = img.convert("L")
BaW.save("profileBaW.png")
BaW.show()

从:“转换为二层图像(模式“1”)时,源图像首先转换为黑白。然后将大于127的结果值设置为白色,并抖动图像。若要使用其他阈值,请使用点方法。”“这听起来相关,但是我不熟悉PIL和图像处理。一个用于
二值化数组
的一行代码(我猜也更快):
numpy。其中(numpy\u数组>阈值=200255,0)
这非常适合我在谷歌搜索中将图像转换为黑白图像的功能。。。谢谢二值化不需要numpy,输出非常糟糕。文本不可识别(这是灰度图像,不是bw图像。@Progyamer它绝对是黑白的。抖动与灰度不同;图像是使用每像素1位创建的。灰度通常使用每像素8位在白色(关闭)和黑色(打开)之间进行着色@MartijnPieters你说得对!这是一幅BW图像。没有注意到,因为缩小后它看起来是灰色的:p这可能是公认的答案——它在不增加库的情况下经济地实现了所需的结果。如果我们希望它们是透明的而不是白色像素呢?@ShanerM13黑白图像每像素有一位的颜色值:它可以是1或0。这就为黑白留出了空间,但没有第三个选项,如透明(除非您负责如何处理图像,并且可以在应用程序中定义其中一个选项表示透明)。