2011-01-13 24 views
8

¿Hay alguna manera de codificar JPEG a una tasa de bits específica?¿Cómo especificar la tasa de bits para la compresión JPEG?

Actualmente, estoy usando ImageMagick de convert:

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

aumenta la velocidad de bits con calidad, pero es no lineal. Quiero controlar la velocidad de bits de forma explícita. No tiene que ser exacto, pero lo quiero razonablemente cerca (dentro de, por ejemplo, 0.1 bpp de la configuración especificada).

¿Hay algún codificador allí que permita codificar las imágenes a una velocidad de bits determinada? No tiene que ser imagemagick, tomaré lo que funcione (preferiblemente en Linux).

Una forma estúpida de hacer esto sería jugar con los valores fraccionarios del parámetro -quality hasta que salga algo cercano a la tasa de bits objetivo, pero estoy esperando una solución más elegante.

EDIT:

Así que me aburría y decidió hacer las cosas de manera rápida (pero estúpida).

En primer lugar, aquí hay un gráfico de la -quality ImageMagick vs tasa de bits:

alt text

Por cierto, aquí está la imagen que utilicé:

alt text

lo tanto, el cambio en la tasa de bits es bastante bien para valores de calidad más bajos, pero se vuelve grueso después de aproximadamente 80.

Aquí hay un código de muestra para codificar una imagen a una tasa de bits objetivo. Utilicé OpenCV porque permite la codificación JPEG en la memoria (no es necesaria la E/S). Aunque originalmente iba a simular esto con Python, desafortunadamente los envoltorios Python OpenCV no exponen la funcionalidad de codificación en memoria. Así que lo escribí en C++.

Por último, estaba pensando en utilizar la interpolación lineal en la calidad para acercarme a la tasa de bits objetivo, pero como cv::imencode solo acepta parámetros enteros, no es posible establecer una calidad JPEG no entera. La escala de calidad entre OpenCV y imagemagick también parece diferir, así que tomar el parámetro de calidad interpolado de OpenCV y usar en imagemagick's convert no funcionó bien.

Esto significa que la tasa de bits de salida no es igual a la tasa de bits objetivo, especialmente a tasas de bits más altas (> 1). Pero está cerca.

¿Alguien puede sugerir algo mejor?

Código:

#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; 
} 

compilar y ejecutar usando:

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 
[email protected]:~/co/cpp$ ./jpeg-bitrate.out Lenna-gray.png test.jpeg 0.53 
wrote test.jpeg at 88% quality, 0.55bpp 
+1

Sugerencia: elimine el bucle for, reemplace con la búsqueda. No puedo creer que alguien quiera un JPEG codificado con factores de calidad en los rangos de 1-> ~ 30 o ~ 99-> 100. También puede crear su gráfico para una variedad de tipos de imágenes diferentes y encontrar un mejor punto de inicio inicial para la búsqueda. Todo esto es muy ingenuo porque ni siquiera considera la calidad (por ejemplo, PSNR); elegir una tabla de cuantificación diferente puede obtener la tasa de bits que desea pero una calidad mucho más alta. – koan

+0

Gracias por la sugerencia. La búsqueda mejorará la eficiencia del código, pero en este momento no es realmente una preocupación porque es lo suficientemente rápido como es. Tiene razón sobre la calidad: la mayoría de las personas normales no necesitan archivos JPEG de esa baja calidad porque parecen basura. Sin embargo, yo mismo * estoy * interesado en tales imágenes, ya que estoy estudiando las degradaciones de la imagen. El punto sobre las tablas de cuantificación es interesante, creo que lo investigaré. Probablemente requerirá alejarse de OpenCV y usar algo como ijg, porque OpenCV no parece exponer las tablas de cuantificación. – misha

Respuesta

4

Conozco a un montón de trabajo existe en el control de la tasa de bits de salida de un codificador JPEG (por ejemplo 1st paper; 2nd paper), y que tales controles existen en JPEG2000. Desafortunadamente, no estoy seguro de que algún tipo de control de velocidad de bits esté estandarizado para JPEG, o implementado en bibliotecas comunes.Puede que tenga que codificar su propio método, utilizando algún tipo de búsqueda binaria, por ejemplo ...

Pero, de nuevo, puedo estar equivocado, y si es así, me gustaría saber acerca de dicha biblioteca.

Solo por curiosidad, ¿qué idioma estás usando?

+0

Gracias por la respuesta y los enlaces. Mi uni no se suscribe a SpringerLink, desafortunadamente, pero ya leí el segundo artículo. Para responder a su pregunta: para un trabajo de imagen serio utilizo C/C++, pero si termino codificando mi propio método para esto, probablemente solo usaré Python/Bash porque soy flojo. – misha

+0

Y eso sería mucho más simple también. De todos modos, díganos si encuentra una buena solución para este problema en particular :) – BlueCookie

+0

He actualizado la pregunta con el código de muestra. No lo llamaría una * buena * solución, pero es la única que tengo en este momento. – misha

2

La relación de calidad de bitrate en JPG depende bastante del contenido. Si desea codificar a una tasa de bits específica, le sugiero que lo haga en dos pasadas: 1. Codifique con un factor de calidad fijo (más cercano a su tasa de bits objetivo es mejor, podría basarse en su gráfico) 2. Según su tamaño , vuelva a codificar el original en una calidad mayor o menor. De nuevo, esto puede basarse en su gráfico o algo similar.

También podría repetir el último paso indefinidamente para obtener la velocidad de bits EXACTA que necesita.

Probaría esto con varios casos extremos, como una imagen muy ruidosa/ocupada, un rectángulo negro o un degradado suave.

Cuestiones relacionadas