目前,我正在对单个图像应用 h.264 压缩。
如下图所示,我想基于 h.264 压缩该图像,并进行 40 个恒定量化。
但是,任何地方都没有相关功能,例如基于 Python 的库(opencv、ffmpeg)。
此外,还没有适用于单图像和结构良好的h.264算法的github。
那么,有没有 github 实现或库可以做到这一点?
提前致谢。
在某些情况下(例如学术目的)对单帧视频进行编码确实有意义。
有一种名为 HEIF 的现有图像格式基于 HEVC (H.265) 编解码器,但对于 H.264,您必须对视频文件进行编码。
您可以使用FFmpeg命令行工具来创建单帧视频文件:
ffmpeg -i input.png -vcodec libx264 -qp 40 -pix_fmt yuv420p single_frame.mp4
(假设您的输入图像是
input.png
)。
-qp 40
参数应用恒定量化 40。
qp(qp)
设置恒定量化率控制方法参数
请参阅:libx264 文档
注:
由于它是单个框架,因此框架类型将是
I-Frame
。
如果您更喜欢基本 H.264 流(没有 MP4 容器),您可以使用:
ffmpeg -i input.png -vcodec libx264 -qp 40 -pix_fmt yuv420p single_frame.264
FFmpeg 有 Python 绑定,例如 ffmpeg-python。
您可以使用它来编码表示原始视频帧的 NumPy 数组。
您还可以使用 FFmpeg 子进程的管道作为以下示例。
您可以在 GitHub 中找到 H.264 编码器的源代码(例如这里)。
据我所知,源代码是用 C 实现的。
在不查看来源的情况下,我认为您不会将它们视为“结构良好”。
您想要对单个图像进行 H.264 编码的原因很少。 Jpeg 可能就是您想要的。但我有一个项目,我正在为视频构建超分辨率模型,并且视频压缩伪影不断增强,就好像它们是实际边缘一样。因此,我必须想出一种方法来对单个图像进行 H.264 视频编码,以训练它修复伪影而不是增强伪影。
compress_image_h264 采用 numpy 数组图像(h、w、c)和压缩量(建议 25-50)并输出压缩版本。
结果在返回之前被复制,因为我遇到了返回“不可写”数组的问题,并且复制修复了它。
def compress_image_h264(image, amount):
# Encode the image to PNG format
_, png_data = cv2.imencode('.png', image)
# Use ffmpeg to compress the image using H.264 codec and MKV container
ffmpeg_command = [
'ffmpeg',
'-y', # Overwrite output files without asking
'-i', 'pipe:0', # Input from stdin
'-vcodec', 'libx264', # Use H.264 codec
'-qp', str(amount), # Quality parameter
'-pix_fmt', 'yuv420p', # Pixel format
'-f', 'matroska', # Use MKV container
'pipe:1' # Output to stdout
]
result = subprocess.run(
ffmpeg_command,
input=png_data.tobytes(), # Pass PNG data to stdin
stdout=subprocess.PIPE, # Capture stdout
stderr=subprocess.PIPE # Capture stderr for debugging
)
if result.returncode != 0:
print("FFmpeg error during compression:", result.stderr.decode())
raise RuntimeError("FFmpeg compression failed")
# Get the compressed data from stdout
compressed_data = result.stdout
return np.copy(decompress_image_h264(compressed_data, image.shape[1], image.shape[0]))
def decompress_image_h264(compressed_data, width, height):
# Use ffmpeg to decompress the image from H.264 to raw format
ffmpeg_command = [
'ffmpeg',
'-i', 'pipe:0', # Input from stdin
'-f', 'rawvideo', # Output raw video format
'-pix_fmt', 'bgr24', # Pixel format
'pipe:1' # Output to stdout
]
result = subprocess.run(
ffmpeg_command,
input=compressed_data, # Pass compressed data to stdin
stdout=subprocess.PIPE, # Capture stdout
stderr=subprocess.PIPE # Capture stderr for debugging
)
if result.returncode != 0:
print("FFmpeg error during decompression:", result.stderr.decode())
raise RuntimeError("FFmpeg decompression failed")
# Get the raw image data from stdout
raw_image_data = result.stdout
# Ensure we have enough data to reshape into the desired format
expected_size = width * height * 3
if len(raw_image_data) != expected_size:
print("Unexpected raw image data size:", len(raw_image_data))
raise ValueError(f"Cannot reshape array of size {len(raw_image_data)} into shape ({height},{width},3)")
# Convert the raw data to a numpy array
frame = np.frombuffer(raw_image_data, dtype=np.uint8).reshape((height, width, 3))
return frame