В настоящее время я делаю программу python для преобразования изображения в шестнадцатеричную строку и наоборот. Мне нужны две функции: одна, которая берет изображение и возвращает шестнадцатеричную строку, соответствующую значениям RGB каждого пикселя, и другая функция, которая принимает шестнадцатеричную строку, два целых числа и создает видимое изображение этого размера, соответствующего этой шестнадцатеричной строке. .
В настоящее время я использую imageio, чтобы получить матрицу RGB из изображения, а затем преобразовать ее в шестнадцатеричный формат. Это быстро, около 2,5 секунд для изображения размером 442 КБ с разрешением 918 x 575 пикселей.
Чтобы получить изображение из строки, я конвертирую его в матрицу шестнадцатеричных значений, а затем конвертирую в RGB, чтобы использовать imageio для создания изображения. Здесь возникает проблема, так как обработка строки, соответствующей тому же изображению 918 x 575, занимает 36 секунд.
Как я мог сделать это быстрее?
Вот код:
def rgb2hex(rgb):
"""
convert a list or tuple of RGB values
to a string in hex
"""
r,g,b = rgb
return '{:02x}{:02x}{:02x}'.format(r, g, b)
def arrayToString(array):
"""
convert an array to a string
"""
string = ""
for element in array:
string += str(element)
return string
def sliceStr(string,sliceLenght):
"""
slice a string in chunks of sliceLenght lenght
"""
string = str(string)
array = np.array([string[i:i+sliceLenght] for i in range(0,len(string),sliceLenght)])
return array
def hexToRGB(hexadecimal):
"""
convert a hex string to an array of RGB values
"""
h = hexadecimal.lstrip('#')
if len(h)!=6:
return
return [int(h[i:i+2], 16) for i in (0, 2, 4)]
def ImageToBytes(image):
"""
Image to convert from image to bytes
"""
dataToEncrypt =imageio.imread(image)
if dataToEncrypt.shape[2] ==4:
dataToEncrypt = np.delete(dataToEncrypt,3,2)
originalRows, originalColumns,_ = dataToEncrypt.shape
#converting rgb to hex
hexVal = np.apply_along_axis(rgb2hex, 2, dataToEncrypt)
hexVal = np.apply_along_axis(arrayToString, 1, hexVal)
hexVal = str(np.apply_along_axis(arrayToString, 0, hexVal))
byteImage = bytes.fromhex(hexVal)
return (byteImage, [originalRows,originalColumns])
def BytesToImage(byteToConvert,originalRows,originalColumns,name):
"""
Convert from Bytes to Image
"""
Data = byteToConvert.hex()
stepOne = sliceStr(Data,originalColumns*6)
stepTwo = []
for i in stepOne:
step = sliceStr(i,6)
#Add lost pixels
while len(step) != originalColumns:
step = np.append(step,"ffffff")
stepTwo.append(step)
stepThree = []
for i in stepTwo:
d = []
for j in i:
d.append(hexToRGB(j))
if len(stepThree) < originalRows:
stepThree.append(d)
Img = np.asarray(stepThree)
imageio.imwrite(name,Img)
Удалить неправильный отступ в этой строке:
Img = np.asarray(stepThree)
Он находится внутри цикла for и не должен
Кроме того, код выполняет ненужное преобразование из байта в строку в int вместо того, чтобы делать это напрямую из байта в int, рассмотрите возможность перехода к следующему, который короче и быстрее
def BytesToImage2(byteToConvert,originalRows,originalColumns,name):
"""
Convert from Bytes to Image
"""
ia=[]
for i in range(0,len(byteToConvert),originalColumns*3):
row=[[y for y in x] for x in [byteToConvert[j:j+3] for j in range(i,i+originalColumns*3,3)]]
ia.append(row)
Img = np.asarray(ia)
imageio.imwrite(name,Img)
Простого исправления отступа было достаточно, чтобы значительно сократить время. Не знаю, о чем я думал, когда делал это. И эта модификация сокращает время до половины. Большое спасибо! Простите, что так много спрашиваю, но знаете ли вы, есть ли способ уменьшить время первой части (ImageToBytes) до менее 2,5 секунд?
Если ваша длина в байтах соответствует требованиям, следующий код должен быть самым быстрым методом, он в 500 000 раз быстрее, чем понимание списка на изображении 918 * 575 (игнорируйте время imwrite):
def BytesToImage(byteToConvert, originalRows, originalColumns, name):
img = np.frombuffer(byteToConvert, np.uint8).reshape(originalRows, originalColumns, 3)
imageio.imwrite(name, img)
Простите, а что вы подразумеваете под "соответствующим"? Это работает только с байтовыми строками определенной длины?
@Rararat Длина байтов равна originalRows * originalColumns * 3.
Каков формат вашего шестнадцатеричного изображения? это необработанные значения пикселей, то есть то, что вы получите от своей функции ImageToBytes?