Как указать битрейт для сжатия JPEG? - PullRequest
8 голосов
/ 13 января 2011

Есть ли способ кодировать JPEG с определенным битрейтом?

В настоящее время я использую imagemagick's convert:

convert Lenna-gray-100.jpeg -quality 1.1111 test.jpeg

Битрейт увеличивается с качеством, но это нелинейно.Я хочу явно контролировать битрейт.Оно не должно быть точным, но я хочу, чтобы оно было достаточно близко (в пределах, скажем, 0,1 bpp от заданного значения).

Есть ли там какой-либо кодер, который позволяет кодировать изображения с определенной скоростью передачи данных??Это не обязательно должно быть imagemagick, я возьму все, что работает (желательно в Linux).

Глупый способ сделать это - поэкспериментировать с дробными значениями параметра -quality, пока что-то близкодо целевого битрейта выходит, но я надеюсь на более элегантное решение.

РЕДАКТИРОВАТЬ:

Так что мне стало скучно и я решил сделать вещи быстро (но глупо).

Во-первых, вот график -quality против битрейта imagemagick:

alt text

Кстати, вот изображение, которое я использовал:

alt text

Таким образом, изменение битрейта вполне подходит для более низких значений качества, но становится грубым примерно после 80.

Вот пример кода для кодирования изображения с некоторой целевой скоростью передачи битов,Я использовал OpenCV, потому что он допускает кодирование JPEG в памяти (ввод / вывод не требуется).Хотя я изначально собирался смоделировать это с помощью Python, к сожалению, обертки Python OpenCV не предоставляют возможности кодирования в памяти.Поэтому я написал это на C ++.

Наконец, я думал об использовании линейной интерполяции по качеству, чтобы приблизиться к целевому битрейту, но так как cv::imencode принимает только целочисленные параметры, невозможно установитьЦелое качество JPEG.Шкала качества между OpenCV и imagemagick, похоже, также несколько отличается, поэтому взятие интерполированного параметра качества из OpenCV и использование в convert imagemagick не сработало.

Это означает, что битрейт на выходе неравно целевому битрейту, особенно при более высоких битрейтах (> 1).Но это близко.

Кто-нибудь может предложить что-то лучше?

Код:

#include <stdio.h>
#include <cv.h>
#include <highgui.h>
#include <assert.h>
#include <vector>

using cv::Mat;
using std::vector;

#define IMENCODE_FMT   ".jpeg"
#define QUALITY_UBOUND 101
#define BITS_PER_BYTE  8

int
main(int argc, char **argv)
{
    if (argc != 4)
    {
        fprintf(stderr, "usage: %s in.png out.jpeg bpp\n", argv[0]);
        return 1;
    }

    char *fname_in = argv[1];
    char *fname_out = argv[2];
    float target;
    sscanf(argv[3], "%f", &target);

    Mat orig = cv::imread(fname_in);
    int pixels = orig.size().width * orig.size().height * orig.channels();

    vector<unsigned char> buf;
    vector<int> params = vector<int>(2);
    params[0] = CV_IMWRITE_JPEG_QUALITY;
    int q;
    double bpp = 0.0;

    for (q = 1; q < QUALITY_UBOUND; ++q)
    {
        params[1] = q;
        cv::imencode(IMENCODE_FMT, orig, buf, params);
        bpp = (double)buf.size() * BITS_PER_BYTE / pixels;
        if (bpp > target)
            break;
    }

    cv::imwrite(fname_out, orig, params);
    printf("wrote %s at %d%% quality, %.2fbpp\n", fname_out, q, bpp);

    return 0;
}

Скомпилируйте и запустите, используя:

g++ -c -Wall -ggdb -I../c -I../blur `pkg-config --cflags opencv` -Wno-write-strings jpeg-bitrate.cpp -o jpeg-bitrate.o
g++ -I../c `pkg-config --cflags opencv` `pkg-config --libs opencv` -lboost_filesystem jpeg-bitrate.o -o jpeg-bitrate.out
rm jpeg-bitrate.o
misha@misha-desktop:~/co/cpp$ ./jpeg-bitrate.out Lenna-gray.png test.jpeg 0.53
wrote test.jpeg at 88% quality, 0.55bpp

Ответы [ 2 ]

4 голосов
/ 13 января 2011

Я знаю, что проделана большая работа по управлению выходной скоростью передачи кодера JPEG (например, 1-я бумага ; 2-я бумага ), и что такие элементы управления существуют в JPEG2000.К сожалению, я не уверен, что какой-либо контроль битрейта стандартизирован для JPEG или реализован в общих библиотеках.Возможно, вам придется написать собственный метод, например, с помощью какого-то бинарного поиска ...

Но, опять же, я могу ошибаться - и если это так, я бы хотел услышать о такой библиотеке.

Просто из любопытства, какой язык вы используете?

2 голосов
/ 22 октября 2015

Соотношение битрейт-качество в JPG сильно зависит от контента.Если вы хотите кодировать с определенной скоростью передачи битов, я предлагаю вам сделать это в два этапа: 1. Кодировать с фиксированным коэффициентом качества (чем ближе ваш целевой битрейт, тем лучше, может быть основан на вашем графике) 2. Исходя из его размера, повторно кодируйтеоригинал с большим или меньшим качеством.Опять же, это может быть основано на вашем графике или чем-то подобном.

Вы также можете бесконечно повторять последний шаг, чтобы получить точный битрейт, который вам нужен.как очень шумное / занятое изображение, черный прямоугольник или плавный градиент.

...