如何对 python 中的图像执行操作

How to perform operations on images in python

我正在尝试完成一项挑战,我使用方程从其他图像构建新图像 (d)。然后我必须得到图像 (d) 中的标志。给定的图像是 a.png、b.png、c.png 和 y.png,它们可以在这里找到:https://drive.google.com/drive/folders/1bZOm_0apr5ZmaRNf9R5UVIEmtMuYSphn?usp=sharing

等式:d = y - 21a - 3b + 41c

我当前的代码

from PIL import Image

imagey = Image.open('y.png')
imagea = Image.open('a.png')
imageb = Image.open('b.png')
imagec = Image.open('c.png')
size = width, height = imagey.size

new = Image.new('RGB', size)

imgy = imagey.load()
imga = imagea.load()
imgb = imageb.load()
imgc = imagec.load()
data = new.load()

for x in range(width):
    for y in range(height):
        they = imgy[x, y]
        thea = imga[x, y]
        theb = imgb[x, y]
        thec = imgc[x, y]

        new_color = ((int(they[0])) & ~(int((21 * thea[0])) ^ int((3 * theb[0])) ^ int(~(41 * thec[0]))),
                     (int(they[1])) & ~(int((21 * thea[1])) ^ int((3 * theb[1])) ^ int(~(41 * thec[1]))),
                     (int(they[2])) & ~(int((21 * thea[2])) ^ int((3 * theb[2])) ^ int(~(41 * thec[2]))))
        data[x, y] = new_color

new.save('final.png')
new.show()

如果您将 Pillow image 转换为 numpy array 或者您将使用 OpenCVimageio 加载图像(并直接获取 numpy array),那么您能做 直接

new = imagey - 21*imagea - 3*imageb + 41*imagec

结果:

不理想,但比你的代码好得多。

overflow 可能有问题。它可以创建具有 8bits 值的数组,并且计算可以给出 16bits32bits 值,这些值可以在每次计算中减少到 8bits

完整的工作代码:

import imageio

imagey = imageio.imread('y.png')
imagea = imageio.imread('a.png')
imageb = imageio.imread('b.png')
imagec = imageio.imread('c.png')

new = imagey - 21*imagea - 3*imageb + 41*imagec

imageio.imwrite('final.png', new)

# --- imageio doesn't have function to display it ---

import matplotlib.pyplot as plt

plt.imshow(new)
plt.show()

编辑:

如果我使用 OpenCV 那么我会得到理想的结果

完整的工作代码:

import cv2

imagey = cv2.imread('y.png')
imagea = cv2.imread('a.png')
imageb = cv2.imread('b.png')
imagec = cv2.imread('c.png')

new = imagey - 21*imagea - 3*imageb + 41*imagec

cv2.imwrite('final.png', new)

# --- show window with image and wait for press any key ---

cv2.imshow('Image', new)
cv2.waitKey(0)
cv2.destroyAllWindows()

编辑:

顺便说一句: 版本将 PIL Image 转换为 numpy array,稍后又转换回 PIL Image - 但它给出的结果相同结果为 imageio.

from PIL import Image
import numpy as np

imagey = Image.open('y.png')
imagea = Image.open('a.png')
imageb = Image.open('b.png')
imagec = Image.open('c.png')

arr_y = np.array(imagey)
arr_a = np.array(imagea)
arr_b = np.array(imageb)
arr_c = np.array(imagec)

arr_new = arr_y - 21*arr_a - 3*arr_b + 41*arr_c

new = Image.fromarray(arr_new)

new.save('final.png')
new.show()

顺便说一句:

如果我使用程序 file 检查 Linux 上的图像,那么它显示 b.pngc.pngJPEG,而不是 PNG .

$ file b.png

b.png: JPEG image data, JFIF standard 1.01, resolution (DPI), 
density 300x300, segment length 16, 
Exif Standard: [TIFF image data, big-endian, direntries=0], baseline, 
precision 8, 960x640, components 3

我发现 cv2.imread()c.png(即 JPG 文件)提供的值与其他模块几乎没有不同 - 我并不是说 cv2 提供BGR 中的颜色而不是 RGB - 后来这给出了正确的结果。可能 cv2 使用不同的 C 库来读取 JPG