0

I have a png bgr24 image that is encoded to mp4 with x265 encoder in a lossless way. I am aware that bgr to yuv420p conversion is lossy. I am trying to get the bit-exact reconstruction of a encoded image compared to an image that went to the following process: bgr24 -> yuv -> bgr24. A difference image show massive reconstruction error, and it should be blank. Why is that ?

The code:

import cv2
import numpy as np
import subprocess as sp

#convert image to lossless h265 encoded video
sp.run("ffmpeg.exe -i test.png -c:v libx265 -pix_fmt yuv420p -x265-params loseless=1 out.mp4 -y")
sourceIm = cv2.imread("test.png")

#ensure that the source image goes to the same process because yuv420 is lossy
sourceIm = cv2.cvtColor(sourceIm, cv2.COLOR_BGR2YUV_I420)
sourceIm = cv2.cvtColor(sourceIm, cv2.COLOR_YUV2BGR_I420)

vr = cv2.VideoCapture("out.mp4")
ret, frame = vr.read()
vr.release()

diffIm = np.abs(sourceIm - frame)

cv2.imshow("-", diffIm)
cv2.waitKey()
cv2.destroyAllWindows()

Source image: source image

Diff image (output - which should be blank): output image

dajuric
  • 2,373
  • 2
  • 20
  • 43
  • 8 bit integer RGB <--> YUV roundtrip is not invertible. – Gyan Aug 13 '22 at 14:00
  • 1
    I suggest you to start with a more simple case: **1.** RGB->YUV444: `ffmpeg -y -i input.png -pix_fmt yuv444p input.yuv`. **2.** YUV444->RGB: `ffmpeg -y -video_size 1920x1080 -pixel_format yuv444p -i input.yuv output.png`. For your input image, the maximum absolute difference between `input.png` and `output.png` is `2` levels (due to rounding errors). The main cause for the differences in your case is the usage of 4:2:0 chroma subsampling. – Rotem Aug 13 '22 at 21:01
  • also, there seems to be a typo in your command. It reads 'loseless' instead of 'lossless'. Would not have been an issue if it was ChatGPT. I stopped correcting my typo's altogether now LOL – oneindelijk Apr 21 '23 at 10:40

0 Answers0