简体   繁体   English

图像的Python灰度转换

[英]Python gray-scale conversion of an image

So I made this script that takes an image and turns it into a gray scale of itself. 因此,我制作了这个脚本,用于拍摄图像并将其转换为自身的灰度。

I know that a lot of modules can do this automatically like .convert('grey') but I want to do it manually by myself to learn more about python programming. 我知道很多模块都可以像.convert('grey')一样自动执行此操作,但我想自己手动执行此操作,以了解有关python编程的更多信息。

It works ok but its very slow, for a 200pX200p image it takes 10 seconds so, what can I modify for making it go faster? 它可以正常工作,但是非常慢,对于一张200pX200p的图像来说,它需要10秒钟,因此,我可以对其进行哪些修改以使其更快?

it works like this, it takes a pixel, calculates the averange of R, G and B values, set the three to the averange value, adds 40 to each one for more brightness and writes the pixel. 它像这样工作,它需要一个像素,计算R,G和B值的平均范围,将三个值设置为平均范围值,将每个值加40以得到更大的亮度并写入像素。 Here is the code: 这是代码:

import imageio
import os
from PIL import Image, ImageDraw
from random import randrange


img = '/storage/emulated/0/DCIM/Camera/IMG_20190714_105429.jpg'
f = open('network.csv', 'a+')
pic = imageio.imread(img)
picture = Image.open(img)
draw = ImageDraw.Draw(picture)
f.write('\n')

def por():
    cien = pic.shape[0] * pic.shape[1]
    prog = pic.shape[1] * (h - 1) + w
    porc = prog * 100 / cien
    porc = round(porc)
    porc = str(porc)
    print(porc + '%')
rh = int(pic.shape[0])
wh = int(pic.shape[1])
for h in range(rh):
    for w in range(wh):
        prom = int(pic[h , w][0]) + int(pic[h, w][1]) + int(pic[h, w][2])
        prom = prom / 3
        prom = round(prom)
        prom = int(prom)
        prom = prom + 40
        por()
        draw.point( (w,h), (prom,prom,prom))
picture.save('/storage/emulated/0/DCIM/Camera/Modificada.jpg')

PIL does this for you. PIL为您做到这一点。

from PIL import Image
img = Image.open('image.png').convert('grey')
img.save('modified.png')

The Method you are using for conversion of RGB to greyscale, is called Averaging. 用于将RGB转换为灰度的方法称为平均。

from PIL import Image

image = Image.open(r"image_path").convert("RGB")

mapping = list(map(lambda x: int(x[0]*.33 + x[1]*.33 + x[2]*.33), list(image.getdata())))

Greyscale_img = Image.new("L", (image.size[0], image.size[1]), 255)

Greyscale_img.putdata(mapping)

Greyscale_img.show()

The above method ( Averaging ) isn't recommended for conversion of an colored image into greyscale. 不建议使用上述方法( Averaging )将彩色图像转换为灰度。 As it treats each color channel equally, assuming human perceives all colors equally (which is not the truth). 假设人类平等地对待每个颜色通道,就假设人类平等地感知所有颜色(这不是事实)。

You should rather use something like ITU-R 601-2 luma transform (method used by PIL for converting RGB to L ) for the conversion. 您应该使用类似于ITU-R 601-2亮度转换PIL用于将RGB转换为L的方法 )之类的转换方法。 As it uses perceptual luminance-preserving conversion to grayscale. 由于它使用可感知的亮度保留转换为灰度。

For that Just replace the line 为此,只需替换行

mapping = list(map(lambda x: int(x[0]*.33 + x[1]*.33 + x[2]*.33), list(image.getdata())))

with

mapping = list(map(lambda x: int(x[0]*(299/1000) + x[1]*(587/1000) + x[2]*(114/1000)), list(image.getdata())))

PS:- I didn't add 40 to each pixel value, as it doesn't really makes any sense in the conversion of the image to greyscale. PS:-我没有在每个像素值上加上40,因为在将图像转换为灰度时并没有任何意义。

Python is an interpreted language and not really fast enough for pixel loops. Python是一种解释性语言,并且对于像素循环而言还不够快。 cython is a sister project that can compile Python into an executable and can be faster than plain Python for code like this. cython是一个姊妹项目,可以将Python编译成可执行文件,并且对于像这样的代码,可以比普通Python更快。

You could also try using a Python math library like numpy or pyvips . 您也可以尝试使用Python数学库,例如numpypyvips These add array operations to Python: you can write lines like a += 12 * b where a and b are whole images and they'll operate on every pixel at the same time. 这些将数组操作添加到Python:您可以编写a += 12 * b ,其中ab是完整图像,它们将同时对每个像素进行操作。 You get the control of being able to specify every detail of the operation yourself combined with the speed of something like C. 你得到的是能够指定自己用类似C的速度相结合的操作的每一个细节的控制

For example, in pyvips you could write: 例如,在pyvips中,您可以编写:

import sys
import pyvips

x = pyvips.Image.new_from_file(sys.argv[1], access="sequential")
x = 299 / 1000 * x[0] + 587 / 1000 * x[1] + 114 / 1000 * x[2]
x.write_to_file(sys.argv[2])

Copying the equation from Vasu Deo.S's excellent answer, then run with something like: 复制Vasu Deo.S的出色答案中的等式,然后执行以下操作:

./grey2.py ~/pics/k2.jpg x.png

To read the JPG image k2.jpg and write a greyscale PNG called x.png . 要读取JPG图像k2.jpg并编写名为x.png的灰度PNG。

You can approximate conversion in linear space with a pow before and after, assuming your source image is sRGB: 您可以在近似线性空间转换之前和之后战俘,假设你的源图像的sRGB:

x = x ** 2.2
x = 299 / 1000 * x[0] + 587 / 1000 * x[1] + 114 / 1000 * x[2]
x = x ** (1 / 2.2)

Though that's not exactly correct since it's missing the linear part of the sRGB power function. 尽管这并不完全正确,因为它缺少sRGB幂函数的线性部分。

You could also simply use x = x.colourspace('b-w') , pyvips's built-in greyscale operation. 您还可以简单地使用pyvips的内置灰度操作x = x.colourspace('b-w')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM