Content
Appendix: subjective quality analysis between JPEG and JPEG2000
Appendix: JPEG2000 encoding with ffmpeg
The open source (BSD 3-Clause license) OpenJPEG contains both ready binaries for Linux, MAC and Windows and code sources, OpenJPEG supports JPEG2000 and in this post i dwell on coding JPEG2000 only.
JPEG2000 is not an extension of ordinary JPEG, it’s another image coding standard (based on wavelet transforms). Some features of JPEG are supported also by JPEG2000:
- Lossy and lossless coding
- Progressive transmission by pixel accuracy and resolution
- New feature: Region-of-Interest Coding
- More robust to bit-errors
- Tiling
- Arithmetic Coding (supported by JPEG-LS, context dependent binary coding. JPEG2000 uses no more than 9 contexts for any given type of bit. This allows rapid probability
adaptation. - Multiple-component images – different components need not have the same bit-depths (e.g. luma pixels can be 10bpp while chroma pixels are 8bpp)
i take windows-x64.zip that contains two binaries in the bin-folder: opj_compress (jpeg encoder) and opj_decompress (jpeg decoder):
The list of input raw image formats recognized by opj_compress:
PBM, PGM, PPM, PNM, PAM, PGX, PNG, BMP, TIF, TIFF, RAW, YUV, RAWL, TGA
Lossless Encoding
RGB Input
To encode in JPEG2000 specify the output file extension as ‘j2k’ (by default encoding is lossless):
opj_compress -i flashes.png -o flashes.j2k
note: in the lossless mode the compression ratio from png to jpeg2000 is found ~2:1 (from 1.5MB to 0.7MB)
Checking
ffprobe -hide_banner -i flashes.j2k
Input #0, j2k_pipe, from ‘flashes.j2k’:
Duration: N/A, bitrate: N/A
Stream #0:0: Video: jpeg2000, rgb24, 1157×710, lossless, 25 tbr, 25 tbn, 25 tbc
To display JPEG200 image use ‘ffplay’
ffplay flashes.j2k
YUV420 Input
Note: The input format in OpenJpeg is specified by the input file extension, if you have an yuv file with the extension ‘yuv’, you are recommended to rename the extension to ‘raw’ (although not necessarily).
you need specify input image size (width,height), the number of component (in case of yuv420p three components are available), the bitdepth (in yuv420p the bit-depth = 8) and sub-sumbling of chroma – 4:2:0 . The parameter ‘-F’ is tailored to specify yuv-format:
-F width,height,number_components,8,u@1×1:2×2:2×2 , here 1×1 subsampling of the first Y-component, 2×2 subsampling of U and V components.
Example (lossless coding of yuv420p, 384×320):
opj_compress -i battlefield_384x320.raw -o batlefield.j2k -F 384,320,3,8,u@1x1:2x2:2x2
checking:
ffprobe -hide_banner -i batlefield.j2k
Input #0, j2k_pipe, from ‘batlefield.j2k’:
Duration: N/A, bitrate: N/A
Stream #0:0: Video: jpeg2000, yuv420p, 384×320, lossless, 25 tbr, 25 tbn, 25 tbc
Notes:
- if you get the error:
Error: invalid raw or yuv image parameters
Please use the Format option -F:
…
The reason is that you copied the F-parameters from the above, you need type them instead (the symbol ‘@’ is not always correctly translated).
- For 4:2:2 use 2×1 instead of 2×2:
-F 352,288,3,8,u@1x1:2x1:2x1
Lossless compression ratio for very non-trivial scene is 2.4x in JPEG2000:
If you have yuv-sequence in the format yuv420p and you wish to encode the very first frame apply opj_compress as follows:
opj_compress.exe -i battlefield_384x320.yuv -o batlefield.j2k -F 384,320,3,8,u@1x1:2x2:2x2
Warning. End of raw file not reached… processing anyway
[INFO] tile number 1 / 1
[INFO] Generated outfile batlefield.j2k
encode time: 63 ms
Note: The warning “End of raw file not reached… processing anyway” is printed because the input yuv-sequence (battlefield_384x320.yuv) has more than one frame.
Lossy Encoding
Lossy encoding is specified by ‘-q’ parameter, if you wish to get psnr around 40dB, use ‘-q 40’:
opj_compress -i battlefield_384x320.yuv -o batlefield_q40.j2k -F 384,320,3,8,u@1×1:2×2:2×2 -q 40
Warning. End of raw file not reached… processing anyway
[INFO] tile number 1 / 1
[INFO] Generated outfile batlefield_q40.j2k
encode time: 24 ms
for ‘-q 40’ the compression ratio is ~11.5x
note: there is a bug in ffprobe, despite the output j2k file is lossy (according to visual degradation), ffprobe mistakenly writes ‘lossless’:
ffprobe -hide_banner batlefield_q40.j2k
Input #0, j2k_pipe, from ‘batlefield_q40.j2k’:
Duration: N/A, bitrate: N/A
Stream #0:0: Video: jpeg2000, yuv420p, 384×320, lossless, 25 tbr, 25 tbn, 25 tbc
Tiling
You can divide input image to tiles (rectangular non-overlapping blocks), which are compressed independently. All tiles have exactly the same dimensions, except maybe those at the right and lower boundary of the image. The tiling parameters are specified in command line by ‘-t <tile_width>,<tile_height>’. Tiling is beneficial for high resolution images, especially for decoding such images, since each tile can be processed independently and in parallel.
Notice that tiling impacts on coding efficiency, so it’s better to avoid tiling on small resolution images.Due to non-overlapping tiling might make faintly visible tile boundaries. By default tiling is off.
For example the input image with the resolution 384×320 can be divided into 30 of 64×64 tiles:
opj_compress -i batlefield_384x320.png -o batllefield_tiles.j2k -t 64,64
[INFO] tile number 1 / 30
[INFO] tile number 2 / 30
[INFO] tile number 3 / 30
[INFO] tile number 4 / 30
[INFO] tile number 5 / 30
[INFO] tile number 6 / 30
[INFO] tile number 7 / 30
[INFO] tile number 8 / 30
[INFO] tile number 9 / 30
[INFO] tile number 10 / 30
[INFO] tile number 11 / 30
[INFO] tile number 12 / 30
[INFO] tile number 13 / 30
[INFO] tile number 14 / 30
[INFO] tile number 15 / 30
[INFO] tile number 16 / 30
[INFO] tile number 17 / 30
[INFO] tile number 18 / 30
[INFO] tile number 19 / 30
[INFO] tile number 20 / 30
[INFO] tile number 21 / 30
[INFO] tile number 22 / 30
[INFO] tile number 23 / 30
[INFO] tile number 24 / 30
[INFO] tile number 25 / 30
[INFO] tile number 26 / 30
[INFO] tile number 27 / 30
[INFO] tile number 28 / 30
[INFO] tile number 29 / 30
[INFO] tile number 30 / 30
[INFO] Generated outfile batllefield_tiles.j2k
encode time: 46 ms
Lazy Coding
JPEG2000 uses arithmetic coding and this sort of coding is serial in virtue and sometimes can be processing bottleneck. To facilitate arithmetic coding process JPEG2000 enables so called “lazy coding”, in Lazy Coding the number of symbols that are arithmetically coded is reduced. Consequently encoding/decoding times are reduced, although coding efficiency is compromised.
Lazy coding mode is activated by ‘-M 1’
opj_compress.exe -i battlefield_384x320.yuv -o batlefield_lazy.j2k -F 384,320,3,8,u@1×1:2×2:2×2 -M 1
the encoding times and the sizes in regular mode and in lazy coding one for battlefield_384x320.yuv:
File size (bytes) | Encoding times (ms) |
|
regular mode | 75,502 | 24 |
lazy mode | 76,595 | 21 |
Decoding
opj_decompress -i batlefield.j2k -o batlefield_decoded.png
Appendix: subjective quality analysis between JPEG and JPEG2000
In the overdetailed book “JPEG2000 Image Compression Fundamentals, Standards and Practice”, by DAVID S. TAUBMAN and MICHAEL W. MARCELLIN, 2002; the authors (as expected) provide a subjective quality comparison between JPEG and JPEG2000.
The bottom line of the comparison: JPEG2000 is much better than JPEG in subjective visual quality (ranging from 14% to 47%). Largest improvement occur in lower rates (presumably JPEG2000 smooths blocking artifacts which are significantly annoying at the lower rates).
The following images were taken for the video quality testing:
All the above images were encoded in JPEG with the following rates (bits per sample, bps):
0.3,0.4,0.5,…1.2 bps
in JPEG2000: 0.25,0.5,0.75 and 1 bps
Each observer was given JPEG2000 image and asked to find JPEG image of comparable quality, the results are summed up in the following graph:
Appendix: JPEG2000 encoding with ffmpeg
The ffmpeg supports two JPEG2000 encoders: libopenjpeg and jpeg2000, where libopenjpeg is plugin of OpenJPEG
The jpeg2000 can be configured to produce output image with a predefined quality from 2 (the best) to 31 (the worst) with the switch '-q:v':
ffmpeg -i ..\baboon.bmp -c:v jpeg2000 -q:v 10 -y baboon_q10.j2k
To check a relationship between the quality (specified by '-q:v'
) , PSNR and the image size in bytes I wrote the python script GetQualityJpeg2000.py
The script gets input image (bmp, png, jpeg etc.) and applies ffmpeg to encode the input image with the codec jpeg2000 with different qualities (from 2 to 31), for each quality PSNR is computed and saved as well as the output file size. At the end qualities, PSNRs and the file-sizes are printed in csv-format.
Usage:
-i input original image
-o output temporary j2k file
Example [output: quality,psnr, fsize]:
python GetQualityJpeg2000.py -i baboon.bmp -o test.j2k
2,39.38,331389
3,37.87,300033
4,36.57,278176
5,35.78,261494
6,34.73,240178
7,33.54,220829
8,32.85,207996
9,32.55,201124
10,32.36,196408
11,32.12,191385
12,31.85,186077
13,31.55,180674
14,31.23,175038
15,30.96,170003
16,30.66,163996
17,30.37,157682
18,30.13,151824
19,29.91,146682
20,29.72,142307
21,29.54,138567
22,29.37,135627
23,29.20,132833
24,29.02,130167
25,28.82,127159
26,28.62,124270
27,28.37,120506
28,28.14,117182
29,27.94,113917
30,27.75,110829
31,27.59,108144
The codec libopenjpeg does not recognize the quality (‘-q:v’), instead there is the parameter -compression_level
which specifies the compression factor.
Example [encoding with libopenjpeg with compression factor 10x)
ffmpeg -i baboon.bmp -c:v libopenjpeg -compression_level 10 -y baboon_10x.j2k
23+ years’ programming and theoretical experience in the computer science fields such as video compression, media streaming and artificial intelligence (co-author of several papers and patents).
the author is looking for new job, my resume
The very heart of your writing whilst sounding agreeable initially, did not really sit well with me personally after some time. Someplace within the paragraphs you were able to make me a believer unfortunately only for a very short while. I nevertheless have got a problem with your jumps in assumptions and you might do well to fill in all those breaks. If you can accomplish that, I would definitely end up being fascinated.
i’ve modified this post, it should be looked better
Outstanding post, I think blog owners should learn a lot from this web site its really user pleasant.
Outstanding post, I conceive people should learn a lot from this website its real user pleasant.
Can I simply say what a reduction to seek out someone who really is aware of what theyre speaking about on the internet. You definitely know easy methods to deliver a problem to mild and make it important. More individuals need to read this and understand this side of the story. I cant consider youre not more in style since you definitely have the gift.
I am very happy to read this. This is the type of manual that needs to be given and not the accidental misinformation that’s at the other blogs. Appreciate your sharing this greatest doc.
I dugg some of you post as I thought they were very useful handy
Thank you for sharing excellent informations. Your web-site is very cool. I am impressed by the details that you?¦ve on this blog. It reveals how nicely you understand this subject. Bookmarked this web page, will come back for extra articles. You, my pal, ROCK! I found simply the info I already searched all over the place and simply couldn’t come across. What a perfect site.
I view something genuinely interesting about your weblog so I saved to fav.
WONDERFUL Post.thanks for share..more wait .. …
Magnificent website. A lot of helpful info here. I’m sending it to some buddies ans additionally sharing in delicious. And naturally, thank you for your sweat!
Hey There. I found your blog using msn. This is a really well written article. I’ll be sure to bookmark it and return to read more of your useful information. Thanks for the post. I’ll definitely return.
I consider something genuinely interesting about your blog so I bookmarked.
Hey there, You have done a great job. I’ll definitely digg it and personally recommend to my friends. I’m sure they’ll be benefited from this site.
I couldn’t resist commenting