如何对 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
或者您将使用 OpenCV
或 imageio
加载图像(并直接获取 numpy array
),那么您能做
直接
new = imagey - 21*imagea - 3*imageb + 41*imagec
结果:
不理想,但比你的代码好得多。
overflow
可能有问题。它可以创建具有 8bits
值的数组,并且计算可以给出 16bits
或 32bits
值,这些值可以在每次计算中减少到 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.png
和 c.png
是 JPEG
,而不是 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
。
我正在尝试完成一项挑战,我使用方程从其他图像构建新图像 (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
或者您将使用 OpenCV
或 imageio
加载图像(并直接获取 numpy array
),那么您能做
直接
new = imagey - 21*imagea - 3*imageb + 41*imagec
结果:
不理想,但比你的代码好得多。
overflow
可能有问题。它可以创建具有 8bits
值的数组,并且计算可以给出 16bits
或 32bits
值,这些值可以在每次计算中减少到 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.png
和 c.png
是 JPEG
,而不是 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
。