Сжатие / распаковка изображений, изменение размера файла - PullRequest
0 голосов
/ 16 ноября 2018

РЕДАКТИРОВАТЬ: решение в нижней части.

Я работаю над проектом, в котором мне нужно хранить десятки тысяч картинок каждую неделю в кластере hadoop для последующего анализа. Я хотел бы сохранить их в HBase и нашел для этого этот хороший конвейер . Прежде чем писать в HBase, я написал программу, которая преобразует изображения в байты и сохраняет их в кадре данных. Проблема в том, что когда я извлекаю изображения из кадра данных, размер файла больше, чем у оригиналов, и я не могу найти причину.

Изображения, с которыми я работаю, имеют размер около 50 КБ и сохраняются в формате jpg. Вот код для преобразования и сохранения данных в фрейм данных:

#list_files contain a list with all the files' paths
list_bytes=[] #list for images in bytes
for i in range (0, len(list_files)):
    image_original = cv2.imread(list_files[i]) #get the image i from the file list
    flatten = image_original.flatten() #flatten the array for compression
    compress = bz2.compress(flatten) #bzip into bytes
    image_64bytes = base64.b64encode(compress) #change it to 64bytes
    list_bytes.append(image_64bytes) 
df=pd.DataFrame({'file':list_files, 'bytes':list_bytes}) #write images into a dataframe along with their metadata

Теперь вот код для извлечения изображения из df:

decode = base64.b64decode(df.iloc[0,0])  #decode from 64bytes to bytes
unzip = bz2.decompress(decode) #unzip
conversion = np.frombuffer(unzip, dtype=np.uint8) #transform bytes into np.array
image_final = np.reshape(conversion, (650, 700,3)) #reshape image in its original format

Чтобы убедиться, что image_final идентичен image_original, следующее должно вернуть пустой массив:

print((np.where((image_original == image_final ) == False)))

(массив ([], dtype = int64), массив ([], dtype = int64), массив ([], DTYPE = int64))

Затем я сравнил размер изображения в байтах, хранящихся в кадре данных, и кажется, что он намного больше, чем исходный (50 КБ). Я предполагаю, что это ожидается, но это все еще большая разница.

sys.getsizeof(df.iloc[0,0])

382129

Аналогичным образом, если я сохраню image_final на диске с cv2.imwrite(file_path, image_final), файл будет размером 80 КБ в формате jpg и 550 КБ в формате png. Если image_original и image_final идентичны, почему они имеют разный размер на диске? Это может определенно стать проблемой позже, когда все изображения будут загружены для анализа.

Заранее благодарю за помощь

Примечание: я также пытался использовать cv2.imencode('.png', image_original)[1] / cv2.imdecode(conversion, cv2.IMREAD_COLOR) вместо image_original.flatten() / np.reshape(conversion, (650, 700,3)), но результаты очень похожи.

EDIT: Вместо загрузки изображения и его преобразования в байты можно просто прочитать файлы в байтах и ​​сохранить их в информационном кадре:

#list_files contain a list with all the files' paths
list_bytes=[]
for i in range (0, len(list_files)):
    in_file = open(list_files[i], "rb") # opening for [r]eading as [b]inary
    data = in_file.read() #insert bytes data into data
    compress = bz2.compress(data) #compress the data in bytes
    to_64bytes = base64.b64encode(compress) #change bytes to bytes64
    to_str = to_64bytes.decode() #transform as string for storage
    in_file.close()
    list_bytes.append(to_str) 
df=pd.DataFrame({'file':list_files, 'bytes':list_bytes}) #write it into a database with metadata

Затем прочитать изображения:

s= df.iloc[0,1] #cell containing the string of the data to retrieve

decode = base64.b64decode(s) #transforms to byte64
unzip = bz2.decompress(decode) #unzip
conversion = np.frombuffer(unzip, dtype=np.uint8) #transform into np.array
img = cv2.imdecode(conversion, cv2.IMREAD_COLOR) #transform into img

plt.imshow(img)
plt.show()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...