Video Compression

VideoNerd

Content

Lossless Encoding

RGB Input

YUV420 Input

Lossy Encoding

Tiling

Lazy Coding

Decoding

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

15 Responses

  1. 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.

  2. 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.

  3. 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.

  4. 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.

Leave a Reply

Your email address will not be published. Required fields are marked *