Иногда возникает задача преобразовать картинку OpenCV из обычного формата в какой-нибудь сжатый формат (вроде jpeg) для последующей передачи в сокет или куда-нибудь ещё. Просто сохранять в файл и потом его считывать — явно не лучший вариант.
Здесь нам на выручку придёт функция cv::imencode().
С++:
bool cv::imencode (const String &ext, InputArray img, std::vector< uchar > &buf, const std::vector< int > ¶ms=std::vector< int >())
Python:
cv.imencode(ext, img[, params]) -> retval, buf
Кодирует изображение в буфер памяти.
Функция imencode сжимает изображение и сохраняет его в буфере памяти, размер которого изменяется в соответствии с результатом.
Параметры
ext — Расширение файла, определяющее выходной формат.
img — исходное изображение для преобразования.
buf — буфер для хранения результата.
params — параметры, зависящие от формата (см. cv::ImwriteFlags).
Таким образом, чтобы просто получить сжатую картинку формата jpeg достаточно выполнить:
# set encode param
encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 90]
# compress image into buffer
result, imgencode = cv2.imencode(".jpg", img, encode_param)
На выходе — флаг успешности операции и буфер с результатом сжатия изображения.
Рассмотрим как можно использовать эту функцию для сжатия изображения и последующей кодировки в base64 (что-то подобное использует labelme для хранения картинок в json-файлах).
#!/usr/bin/env python3
import numpy as np
import cv2
import base64
def get_base64_from_image(img):
# return base64 data from compressed to JPEG image
if img is None:
return None
# set encode param
encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 90]
# compress image into buffer
result, imgencode = cv2.imencode(".jpg", img, encode_param)
print(result, type(imgencode))
data = np.array(imgencode)
print(data.shape, data.dtype)
# base64 encode
img_data = base64.b64encode(data)
print(len(img_data), type(img_data))
res = img_data.decode("ascii")
return res
def main():
print("cv2 v.", cv2.__version__)
filename = "0022.jpg"
img = cv2.imread(filename)
if img is None:
print("Error read image:", filename)
exit(0)
print(img.shape, img.dtype)
img_data = get_base64_from_image(img)
print(len(img_data), type(img_data))
#print(img_data)
if __name__ == "__main__":
main()
Результат работы:
cv2 v. 4.5.5 (1080, 1920, 3) uint8 True <class 'numpy.ndarray'> (708049,) uint8 944068 <class 'bytes'> 944068 <class 'str'>
далее: OpenCV: imdecode() — функция декодирует изображение из буфера памяти
Ссылки
По теме

