OpenCV: imencode() — функция кодирует изображение в буфер памяти


Иногда возникает задача преобразовать картинку OpenCV из обычного формата в какой-нибудь сжатый формат (вроде jpeg) для последующей передачи в сокет или куда-нибудь ещё. Просто сохранять в файл и потом его считывать — явно не лучший вариант.

Здесь нам на выручку придёт функция cv::imencode().

С++:

bool cv::imencode (const String &ext, InputArray img, std::vector< uchar > &buf, const std::vector< int > &params=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() — функция декодирует изображение из буфера памяти

Ссылки

По теме


Добавить комментарий

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Android Arduino Bluetooth CraftDuino DIY IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд юмор

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение