Как выполнять операции с изображениями в python

#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 .