#python #python-3.x #python-imaging-library #bitwise-operators
Вопрос:
Я пытаюсь выполнить задачу, в которой я использую уравнение для построения нового изображения (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])) amp; ~(int((21 * thea[0])) ^ int((3 * theb[0])) ^ int(~(41 * thec[0]))),
(int(they[1])) amp; ~(int((21 * thea[1])) ^ int((3 * theb[1])) ^ int(~(41 * thec[1]))),
(int(they[2])) amp; ~(int((21 * thea[2])) ^ int((3 * theb[2])) ^ int(~(41 * thec[2]))))
data[x, y] = new_color
new.save('final.png')
new.show()
Комментарии:
1. Я не понимаю. Ваша формула-простое умножение и сложение. Какое это имеет отношение к побитовым операциям?
2. если бы вы конвертировали
Pillow image
numpy array
или использовалиOpenCV
илиimageio
загружали изображение (и получали напрямуюnumpy array
), вы могли бы сделать это напрямуюimagey - 21*imagea - 3*imageb 41*imagec
Ответ №1:
Если бы вы конвертировали 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()
кстати:
Если я проверяю изображения в Linux с помощью программы file
, то это показывает, что 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
.