Image.fromarray () делает каждый элемент в матричном моде 256 - PullRequest
0 голосов
/ 18 марта 2019

Я пишу скрипт для шифрования и дешифрования изображения в python3 с использованием PIL.Здесь я конвертирую изображение в массив numpy, а затем умножаю каждый элемент массива на 10. Теперь я заметил, что функция по умолчанию в PIL fromarray () конвертирует каждый элемент массива в мод 256, если он больше, чем255, поэтому, когда я пытаюсь получить исходное значение матрицы, я не получаю исходное значение.Например, если исходное значение равно 40, то его 10-кратное значение равно 400, поэтому функция fromarray () делает его равным 400 мод 256, что даст 144. Теперь, если я добавлю 256 к 144, у меня будет 400, а затем разделить на 10,дайте мне 40. Но если значение 54, то 10 раз равно 540, а 540 мод 256 равно 28. Теперь, чтобы вернуть исходное значение, мне нужно добавить 256 два раза, что даст мне 540. 540 не единственное число, которое будетдайте мне 28, когда я сделаю мод с 256. Поэтому я никогда не узнаю, когда добавить 256 один раз, а когда два или более.Можно ли как-нибудь остановить замену каждого элемента матрицы модом 256?

from PIL import Image
from numpy import * 
from pylab import * 

#encryption

img1 = (Image.open('image.jpeg').convert('L')) 
img1.show() #displaying the image

img = array(Image.open('image.jpeg').convert('L'))
a,b = img.shape
print(img)
print((a,b))
tup = a,b

for i in range (0, tup[0]):
   for j in range (0, tup[1]):
       img[i][j]= img[i][j]*10 #converting every element of the original array to its 10times

print(img)
imgOut = Image.fromarray(img)
imgOut.show()
imgOut.save('img.jpeg')

#decryption

img2 = (Image.open('img.jpeg'))
img2.show()

img3 = array(Image.open('img.jpeg'))
print(img3)
a1,b1 = img3.shape
print((a1,b1))
tup1 = a1,b1

for i1 in range (0, tup1[0]):
   for j1 in range (0, tup1[1]):
       img3[i1][j1]= ((img3[i1][j1])/10) #reverse of encryption
print(img3)
imgOut1 = Image.fromarray(img3)
imgOut1.show()

часть исходной матрицы перед умножением на 10: [41 42 45 ... 47 41 33]

[41 43 45 ... 44 38 30]

[41 42 46 ... 41 36 30]

[43 43 44 ... 56 56 55]

[45 44 45 ... 55 55 54]

[46 46 46 ... 53 54 54]

часть матрицы после умножения на 10: [[154 164 194 ... 214 154 74]

[154174 194 ... 184 124 44]

[154 164 204 ... 154 104 44]

[174 174 184 ... 48 48 38]

[194 184 194 ... 38 38 28]

[204 204 204 ... 18 28 28]

часть ожидаемой матрицы после деления на 10: [41 42 45 ...47 41 33]

[41 43 45 ... 44 38 30]

[41 42 46 ... 41 36 30]

[43 43 44 ..56 56 55]

[45 44 45 ... 55 55 54]

[46 46 46 ... 53 54 54]

часть выходного сигналаСценарий содержит: [[41 41 45 ... 48 40 33]

[41 43 44 ... 44 37 31]

[41 41 48 ... 41 35 30]

[44 42 43 ... 30 30 29]

[44 42 45 ... 29 29 29]

[45 47 44 ... 28 28 28]]

Ответы [ 3 ]

2 голосов
/ 18 марта 2019

Прежде всего, PIL поддерживает только 8-битные изображения на канал - хотя Подушка (вилка PIL) поддерживает множество других форматов , включая более высокую битовую глубину. Формат JPEG определяется как 8-битный на канал.

Вызов Image.open() для JPEG в PIL, следовательно, вернет 8-битный массив, поэтому любые операции над отдельными пикселями будут выполняться как эквивалент арифметики uint8_t в базовом представлении. Поскольку максимальное значение в uint8_t значении равно 256, все ваши арифметические значения обязательно должны быть по модулю 256.

Если вы хотите избежать этого, вам необходимо преобразовать представление в более высокую битовую глубину, такую ​​как 16bpp или 32bpp. Вы можете сделать это с помощью кода NumPy, например:

img16 = np.array(img, dtype=np.uint16)
# or
img32 = np.array(img, dtype=np.uint32)

Это даст вам расширенную точность, которую вы желаете.

Однако - ваш пример кода показывает, что вы пытаетесь зашифровать и расшифровать данные изображения. В этом случае вы do хотите использовать арифметику по модулю! Вам просто нужно больше изучить реальные алгоритмы шифрования.

2 голосов
/ 18 марта 2019

Есть несколько проблем с тем, что вы пытаетесь сделать здесь.

Изображения PIL либо 8-битные на канал, либо 16-битные на канал (насколько мне известно).Когда вы загружаете JPEG, он загружается как 8 бит на канал, поэтому базовый тип данных представляет собой 8-разрядное целое число без знака, то есть диапазон 0..255.Операции, которые будут переполнять или пропускать эту обертку диапазона, что похоже на поведение модуля, которое вы видите.

Вы можете преобразовать 8-битное изображение PIL в массив с плавающей запятой с помощью np.array(img).astype('float32') и затем нормализовать этодо 0..1 путем деления на 255.

В этот момент у вас есть неквантованные числа с плавающей запятой, которые вы можете свободно изменять по своему усмотрению.

Однако, вам все равно нужно сохранитьПолученное изображение, после чего у вас снова возникает проблема с форматированием.Я полагаю, что файлы TIFF и некоторые форматы изображений HDR поддерживают данные с плавающей запятой, но если вы хотите что-то, что будет широко читаемым, вы, вероятно, предпочтете PNG или JPEG.

Для случая использования шифрования JPEG не годитсявыбор, поскольку они всегда по своей природе с потерями, и вы, скорее всего, не получите обратно одни и те же данные.

PNG могут иметь 8 или 16 бит на канал, но тем не менее, вы получитепроблема сжатия практически бесконечного «динамического диапазона» пикселей (скажем, вы умножили все на тысячу!) до 0..255 или 0..65535.

Очевидный способ сделать эточтобы найти максимальное значение в изображении (np.max(...)), разделить все на него (так что теперь вы вернулись к 0..1), затем умножить на максимальное значение формата данных изображения ... так что спросто умножив «шифр», как вы описали, вы по сути получите то же изображение обратно.

Другим способом было бы обрезать бесконечный диапазон при допустимых значениях, то есть все, что ниже нуля, равно нулю, всескажем, это 65535. Хотя это была бы операция с потерями, и у вас не было бы возможности вернуть незафиксированные значения обратно.

1 голос
/ 21 марта 2019

Поскольку ни один из ответов не помог мне так сильно, и я решил проблему, я хотел бы дать ответ, надеясь, что однажды он кому-нибудь поможет.Здесь ключи (3, 25777) и (16971,25777).Рабочий код выглядит следующим образом:

from PIL import Image
import numpy as np 

#encryption
img1 = (Image.open('image.jpeg').convert('L')) 
img1.show()

img = array((Image.open('image.jpeg').convert('L'))) 
img16 = np.array(img, dtype=np.uint32)
a,b = img.shape
print('\n\nOriginal image: ')
print(img16)
print((a,b))
tup = a,b

for i in range (0, tup[0]):
    for j in range (0, tup[1]):
        x = img16[i][j] 
        x = (pow(x,3)%25777)
        img16[i][j] = x
print('\n\nEncrypted image: ')
print(img16)
imgOut = Image.fromarray(img16)
imgOut.show()

#decryption

img3_16 = img16
img3_16 = np.array(img, dtype=np.uint32)
print('\n\nEncrypted image: ')
print(img3_16)
a1,b1 = img3_16.shape
print((a1,b1))
tup1 = a1,b1

for i1 in range (0, tup1[0]):
     for j1 in range (0, tup1[1]):
         x1 = img3_16[i1][j1] 
         x1 = (pow(x,16971)%25777)  
         img3_16[i][j] = x1
print('\n\nDecrypted image: ')
print(img3_16)
imgOut1 = Image.fromarray(img3_16)y
imgOut1.show()

Не стесняйтесь указывать на неисправности.Спасибо.

...