有沒有辦法以特定比特率對JPEG進行編碼?如何指定JPEG壓縮的比特率?
目前,我使用ImageMagick的convert
:
convert Lenna-gray-100.jpeg -quality 1.1111 test.jpeg
與質量的比特率的增加,但它是非線性的。我想明確控制比特率。它不一定是確切的,但我希望它合理地接近(在指定設置的0.1 bpp內)。
那裏有任何編碼器允許圖像以特定比特率編碼嗎?它不一定是imagemagick,我會採取任何作品(最好在Linux上)。
一個愚蠢的做法是將參數-quality
的小數部分放在一起,直到接近目標比特率的東西出來,但我希望得到更優雅的解決方案。
編輯:
所以我覺得無聊,並決定做事情快(但愚蠢的)的方式。
首先,這裏ImageMagick的-quality
的VS碼率圖:
順便說一句,這是我所使用的圖像:
所以在比特率的變化是相當精細較低的質量值,但在約80後變得粗糙。
以下是一些示例代碼,以某種目標比特率對圖像進行編碼。我使用了OpenCV,因爲它允許內存中的JPEG編碼(不需要I/O)。雖然我原本打算用Python進行模擬,但不幸的是,Python OpenCV包裝程序不公開內存編碼功能。所以我用C++寫了它。
最後,我在考慮在質量上使用線性插值以接近目標比特率,但由於cv::imencode
只接受整數參數,因此無法設置非整數JPEG質量。 OpenCV和imagemagick之間的質量規模似乎也有所不同,所以從OpenCV獲取內插質量參數並在imagemagick的convert
中使用效果不理想。
這意味着輸出比特率不等於目標比特率,特別是在較高比特率(> 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
[email protected]:~/co/cpp$ ./jpeg-bitrate.out Lenna-gray.png test.jpeg 0.53
wrote test.jpeg at 88% quality, 0.55bpp
建議:刪除for循環,用搜索替換。我無法相信任何人都會想要一個質量因子編碼的JPEG,編碼範圍爲1->〜30或〜99-> 100。您還可以爲各種不同的圖像類型創建圖形,併爲搜索找到更好的初始起點。這是非常天真的,因爲你甚至不考慮質量(例如PSNR)。選擇一個不同的量化表可能會讓你想要的比特率,但質量更高。 – koan 2011-01-14 10:11:58
感謝您的建議。搜索可以提高代碼的效率,但目前它並不是真正的問題,因爲它的速度足夠快。你的質量是正確的 - 大多數普通人不需要質量低下的JPEG,因爲他們看起來像垃圾。但是,我自己*對這些圖像感興趣,因爲我正在研究圖像降級。關於量化表的觀點很有趣 - 我想我會研究它。它可能需要離開OpenCV並使用像ijg這樣的東西,因爲OpenCV似乎沒有公開量化表。 – misha 2011-01-14 13:17:19