Я пытаюсь создать библиотеку, связанную с данными пикселей RGB, но не могу правильно сохранить данные изображения.
Это мое выходное изображение. Это мой код:
пиксельный менеджер.py
from PIL import Image
import numpy as np
class MakeImgFromPixelRGB:
def createIMG(PixelArray: list, ImgName: str, SaveImgAsFile: bool):
# Convert the pixels into an array using numpy
array = np.array(PixelArray, dtype=np.uint8)
if SaveImgAsFile == True:
new_image = Image.fromarray(array)
new_image.save(ImgName)
class getPixelsFromIMG:
def __init__(self, ImagePath):
im = Image.open(ImagePath, 'r')
width, height = im.size
pixel_values = list(im.getdata())
self.output = pixel_values
test.py
import pixelmanager
a = pixelmanager.getPixelsFromIMG(ImagePath = "download.jpg")
pixelmanager.MakeImgFromPixelRGB.createIMG(a.output, "output.png", True)
with open("output.txt", "w") as f:
for s in a.output:
f.write(str(s) + "," + "\n")
Я пытался уменьшить масштаб изображения в Paint.net, а также пытался изменить размер uint.
Линия — это выходное изображение. Я пытался установить данные советского флага, которые я получил от другой функции, которая получает данные пикселей.
Обрабатывать изображения как списки пикселей Python, как правило, не лучшая идея, поскольку это медленно и подвержено ошибкам. В общем, вы хотите использовать функции PIL, которые закодированы в C
и работают с типами PIL Image
, или Numpy или OpenCV, которые сильно векторизованы/оптимизированы и работают с массивами Numpy.
В любом случае, если вы действительно хотите иметь дело со списками (а это не так), вам нужно помнить, что когда вы вызываете Image.getdata()
для JPEG, вы получаете плоский список кортежей RGB. Итак, если ваше изображение имеет размер 640x480 пикселей и вы делаете это:
im = Image.open('image.jpg')
px = list(im.getdata())
вы получите список из 307 200 записей, каждая из которых представляет собой кортеж RGB. НО ваш список больше не знает высоту и ширину изображения. Итак, когда вы впоследствии сделаете:
array = np.array(PixelArray, dtype=np.uint8)
ваш массив теперь имеет форму (307200,3) вместо (480,640,3) - ооооо, вы получаете длинную строку пикселей в выходном изображении.
Если вы настаиваете на использовании списков, вам нужно будет сохранить высоту и ширину исходного изображения, поэтому вы можете сделать:
array = np.array(PixelArray, dtype=np.uint8).reshape(h,w,3)
Обратите внимание, что вы также должны запомнить режим изображения, т. е. был ли он RGB или RGBA, или P, или PA, или L, или LA, или HSV и т. д. И обратите внимание, что ваши кортежи также будут иметь длину 1, 2, 3 или 4 вместо того, чтобы всегда предполагать 3. Позже вы также поймете, что вам, возможно, придется иметь дело с 16/32/64 бит/образцами изображений, поэтому вам нужно будет помнить и об этом, в дополнение к вышесказанному.
Марк Сетчелл был ПОЧТИ прав. Его код помог мне получить изображение, но за одно оно повторилось 4 раза.
В строке кода Марка было переключение (с высотой h и шириной w):
array = np.array(PixelArray, dtype=np.uint8).reshape(h,w,3)
Это моя строка кода:
array = np.array(PixelArray, dtype=np.uint8).reshape(w, h, 3)
Это не правильно. Для массивов Numpy на первом месте стоит высота. Попробуйте это w, h = 640, 480
, затем сначала создайте массив Numpy с высотой na = np.zeros((h,w,3), np.uint8)
, затем создайте PIL Image
и отобразите его Image.fromarray(na).show()
, и вы увидите, что изображение PIL шире, чем высота, и соответствует форме (h,w,3)
.
Непонятно, почему этот результат оказался не таким, как вы ожидали. Что в этом неправильного?