使用Python对图像进行不同级别量化QP,使用RLE计算压缩比,并计算对应的PSNR

2023-11-01

写这篇博客源于 博友的提问
在这里插入图片描述

1.效果图

原图 VS QP=2 VS QP=4 VS QP=8效果图如下:
QP量化是指把原始图像按像素级别划分取值。如QP=2,则<128 取0,>128取128.
QP=4,则<64取0,<128取64,<192取128,<256取192.
QP=8,则<32取0,<64取32,<96取64,<128取96,<160取128,<192取160,<224取192,<256取224.
在这里插入图片描述

可以看出QP越大,压缩率越大,同时psnr越大,这表示跟原图相似性越好,越接近原图像。
PSNR 最小值为 0,PSNR 越大,两张图像差异越小;PSNR 计算简单,物理意义清晰,但是这种基于 MSE 的评价指标并不能很好的按人眼的感受来衡量两张图像的相似度
在这里插入图片描述
原始灰度图像 VS 原始图像rle后再反解码回去效果图如下:
在这里插入图片描述
原始灰度图像 VS qp=2图像rle后再反解码回去效果图如下:
在这里插入图片描述

原始灰度图像 VS qp=4图像rle后再反解码回去效果图如下:
在这里插入图片描述
原始灰度图像 VS qp=8图像rle后再反解码回去效果图如下:
在这里插入图片描述

2. 原理

  • 量化(Quantization)旨在将图像像素点对应亮度的连续变化区间转换为单个特定值的过程,即将原始灰度图像的空间坐标幅度值离散化。量化等级越多,图像层次越丰富,灰度分辨率越高,图像的质量也越好;量化等级越少,图像层次欠丰富,灰度分辨率越低,会出现图像轮廓分层的现象,降低了图像的质量。
    QP量化是指把原始图像按像素级别划分取值。如QP=2,则<128 取0,>128取128.
    QP=4,则<64取0,<128取64,<192取128,<256取192.
    QP=8,则<32取0,<64取32,<96取64,<128取96,<160取128,<192取160,<224取192,<256取224.

  • 行程编码(RLE) 在图像压缩上,行程编码一般用于压缩二值化图像,因为它是基于重复的压缩算法,比如:
    二维图像降维后(压缩前):0 0 0 0 0 255 255 255 0 0 255
    行程编码压缩后:5 0 3 255 2 0 1 255
    (压缩格式为:数量+像素+数量+像素…)
    如果有大量的像素连续重复,那么压缩率会更高。

  • PSNR(峰值信噪比,Peak Signal-to-Noise Ratio),用于衡量两张图像之间差异,例如压缩图像与原始图像,评估压缩图像质量;复原图像与ground truth,评估复原算法性能等。
    在这里插入图片描述

    PSNR 最小值为 0,PSNR 越大,两张图像差异越小;
    PSNR 计算简单,物理意义清晰,但是这种基于 MSE 的评价指标并不能很好的按人眼的感受来衡量两张图像的相似度

3. 源码

# -*- coding: utf-8 -*-
# By:Eastmount
# 1. 对图像进行 QP=2,QP=4,QP=8的量化并展示
# 2. 采用行程编码(RLE),计算压缩比;
# 3. 进行解码(反量化),并计算不同量化级别的PSNR值。
# python ask_img_qa_rle_psnr.py
import cv2
import math
import matplotlib.pyplot as plt
import numpy as np

# 读取原始图像
img = cv2.imread('ml.jpg')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 获取图像高度和宽度
height = img.shape[0]
width = img.shape[1]

# 创建一幅图像
new_img1 = np.zeros((height, width, 3), np.uint8)
new_img2 = np.zeros((height, width, 3), np.uint8)
new_img3 = np.zeros((height, width, 3), np.uint8)

# 图像量化等级为2的量化处理
for i in range(height):
    for j in range(width):
        for k in range(3):  # 对应BGR三分量
            if img[i, j][k] < 128:
                gray = 0
            else:
                gray = 128
            new_img1[i, j][k] = np.uint8(gray)

# 图像量化等级为4的量化处理
for i in range(height):
    for j in range(width):
        for k in range(3):  # 对应BGR三分量
            if img[i, j][k] < 64:
                gray = 0
            elif img[i, j][k] < 128:
                gray = 64
            elif img[i, j][k] < 192:
                gray = 128
            else:
                gray = 192
            new_img2[i, j][k] = np.uint8(gray)

# 图像量化等级为8的量化处理
for i in range(height):
    for j in range(width):
        for k in range(3):  # 对应BGR三分量
            if img[i, j][k] < 32:
                gray = 0
            elif img[i, j][k] < 64:
                gray = 32
            elif img[i, j][k] < 96:
                gray = 64
            elif img[i, j][k] < 128:
                gray = 96
            elif img[i, j][k] < 160:
                gray = 128
            elif img[i, j][k] < 192:
                gray = 160
            elif img[i, j][k] < 224:
                gray = 192
            else:
                gray = 224
            new_img3[i, j][k] = np.uint8(gray)

# 用来正常显示中文标签
plt.rcParams['font.sans-serif'] = ['SimHei']

# 显示图像
titles = ['(a) 原始图像', '(b) 量化-QP=2', '(c) 量化-QP=4', '(d) 量化-QP=8']
images = [img, new_img1, new_img2, new_img3]
for i in range(4):
    plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray'),
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()


# 2. RLE计算压缩比
def rle(title, origin, img):
    grayorigin = cv2.cvtColor(origin, cv2.COLOR_RGB2GRAY)
    grayimg = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
    rows, cols = grayimg.shape

    img = grayimg.flatten()  # 把灰度化后的二维图像降维为一维列表

    data = []
    image3 = []
    count = 1
    # 行程压缩编码
    for i in range(len(img) - 1):
        if (count == 1):
            image3.append(img[i])
        if img[i] == img[i + 1]:
            count = count + 1
            if i == len(img) - 2:
                image3.append(img[i])
                data.append(count)
        else:
            data.append(count)
            count = 1

    if (img[len(img) - 1] != img[-1]):
        image3.append(img[len(img) - 1])
        data.append(1)

    # 压缩率
    ys_rate = len(image3) / len(img) * 100
    print(str(title) + ' 压缩率: %.2f%s' % (ys_rate, '%'))

    # 行程编码RLE解码
    rec_image = []
    for i in range(len(data)):
        for j in range(data[i]):
            rec_image.append(image3[i])

    rec_image = np.reshape(rec_image, (rows, cols))
    cv2.imshow('grayorigin VS ' + str(title) + 'res', np.hstack([grayorigin, rec_image]))  # 重新输出二值化图像
    cv2.waitKey(0)
    plt.subplot()
    plt.imshow(np.hstack([grayorigin, rec_image]), 'gray')
    plt.title('grayOrigin VS ' + str(title) + '')
    plt.xticks([]), plt.yticks([])
    plt.show()

    print(str(title) + ' psnr: ', psnr2(grayorigin, rec_image))


# 3. 计算psnr
# 计算灰度图的psnr
def psnr1(img1, img2):
    # compute mse
    # mse = np.mean((img1-img2)**2)
    mse = np.mean((img1 / 1.0 - img2 / 1.0) ** 2)
    # compute psnr
    if mse < 1e-10:
        return 100
    psnr1 = 20 * math.log10(255 / math.sqrt(mse))
    return psnr1


# 计算彩色图的psnr
def psnr2(img1, img2):
    mse = np.mean((img1 / 255.0 - img2 / 255.0) ** 2)
    if mse < 1e-10:
        return 100
    psnr2 = 20 * math.log10(1 / math.sqrt(mse))
    return psnr2


for i in range(0, 4):
    rle(titles[i], images[0], images[i])

参考

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用Python对图像进行不同级别量化QP,使用RLE计算压缩比,并计算对应的PSNR 的相关文章

  • 如何在flask中使用g.user全局

    据我了解 Flask 中的 g 变量 它应该为我提供一个全局位置来存储数据 例如登录后保存当前用户 它是否正确 我希望我的导航在登录后在整个网站上显示我的用户名 我的观点包含 from Flask import g among other
  • 使用 matplotlib 绘制时间序列数据并仅在年初显示年份

    rcParams date autoformatter month b n Y 我正在使用 matpltolib 来绘制时间序列 如果我按上述方式设置 rcParams 则生成的图会在每个刻度处标记月份名称和年份 我怎样才能将其设置为仅在每
  • Flask 会话变量

    我正在用 Flask 编写一个小型网络应用程序 当两个用户 在同一网络下 尝试使用应用程序时 我遇到会话变量问题 这是代码 import os from flask import Flask request render template
  • 根据列值突出显示数据框中的行?

    假设我有这样的数据框 col1 col2 col3 col4 0 A A 1 pass 2 1 A A 2 pass 4 2 A A 1 fail 4 3 A A 1 fail 5 4 A A 1 pass 3 5 A A 2 fail 2
  • SQLALchemy .query:类“Car”的未解析属性引用“query”

    我有一个这里已经提到的问题https youtrack jetbrains com issue PY 44557 https youtrack jetbrains com issue PY 44557 但我还没有找到解决方案 我使用 Pyt
  • Spark KMeans 无法处理大数据吗?

    KMeans 有几个参数training http spark apache org docs latest api python pyspark mllib html highlight kmeans pyspark mllib clus
  • 使用 Tkinter 显示 numpy 数组中的图像

    我对 Python 缺乏经验 第一次使用 Tkinter 制作一个 UI 显示我的数字分类程序与 mnist 数据集的结果 当图像来自 numpy 数组而不是我的 PC 上的文件路径时 我有一个关于在 Tkinter 中显示图像的问题 我为
  • Python pickle:腌制对象不等于源对象

    我认为这是预期的行为 但想检查一下 也许找出原因 因为我所做的研究结果是空白 我有一个函数可以提取数据 创建自定义类的新实例 然后将其附加到列表中 该类仅包含变量 然后 我使用协议 2 作为二进制文件将该列表腌制到文件中 稍后我重新运行脚本
  • OpenCV 无法从 MacBook Pro iSight 捕获

    几天后 我无法再从 opencv 应用程序内部打开我的 iSight 相机 cap cv2 VideoCapture 0 返回 并且cap isOpened 回报true 然而 cap grab 刚刚返回false 有任何想法吗 示例代码
  • 如何在ipywidget按钮中显示全文?

    我正在创建一个ipywidget带有一些文本的按钮 但按钮中未显示全文 我使用的代码如下 import ipywidgets as widgets from IPython display import display button wid
  • Python 的“zip”内置函数的 Ruby 等价物是什么?

    Ruby 是否有与 Python 内置函数等效的东西zip功能 如果不是 做同样事情的简洁方法是什么 一些背景信息 当我试图找到一种干净的方法来进行涉及两个数组的检查时 出现了这个问题 如果我有zip 我可以写这样的东西 zip a b a
  • 在f字符串中转义字符[重复]

    这个问题在这里已经有答案了 我遇到了以下问题f string gt gt gt a hello how to print hello gt gt gt f a a gt gt gt f a File
  • Pandas:merge_asof() 对多行求和/不重复

    我正在处理两个数据集 每个数据集具有不同的关联日期 我想合并它们 但因为日期不完全匹配 我相信merge asof 是最好的方法 然而 有两件事发生merge asof 不理想的 数字重复 数字丢失 以下代码是一个示例 df a pd Da
  • 将图像分割成多个网格

    我使用下面的代码将图像分割成网格的 20 个相等的部分 import cv2 im cv2 imread apple jpg im cv2 resize im 1000 500 imgwidth im shape 0 imgheight i
  • 向 Altair 图表添加背景实心填充

    I like Altair a lot for making graphs in Python As a tribute I wanted to regenerate the Economist graph s in Mistakes we
  • 有没有办法检测正在运行的代码是否正在上下文管理器内执行?

    正如标题所述 有没有办法做到这样的事情 def call back if called inside context print running in context else print called outside context 这将
  • 如何计算 pandas 数据帧上的连续有序值

    我试图从给定的数据帧中获取连续 0 值的最大计数 其中包含来自 pandas 数据帧的 id date value 列 如下所示 id date value 354 2019 03 01 0 354 2019 03 02 0 354 201
  • 使用其构造函数初始化 OrderedDict 以便保留初始数据的顺序的正确方法?

    初始化有序字典 OD 以使其保留初始数据的顺序的正确方法是什么 from collections import OrderedDict Obviously wrong because regular dict loses order d O
  • 导入错误:没有名为 site 的模块 - mac

    我已经有这个问题几个月了 每次我想获取一个新的 python 包并使用它时 我都会在终端中收到此错误 ImportError No module named site 我不知道为什么会出现这个错误 实际上 我无法使用任何新软件包 因为每次我
  • 如何将输入读取为数字?

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 Why are x and y下面的代码中使用字符串而不是整数 注意 在Python 2

随机推荐

  • 从CSV文件导入Hive出现中文乱码问题解决

    关于HIVE中文乱码问题的解决办法 网上有很多帖子 然而很多都是基于LINUX终端显示字符的修改 其实上对于一些条件下的HIVE中文乱码问题是无法解决的 如从CSV文件导入到HIVE中出现的中文乱码问题 大家都知道 HIVE原生的字符编码是
  • 区块链密码学之对称加密

    前言 对称加密 顾名思义就是公钥和私钥都是同一个 只有一把密钥 那么密钥的共享就需要特别注意 容易泄露 但是由于它的加密效率高 速度快 占用空间小 主要用在大量数据的加密 往往需要提前分发密钥 对称密码从实现上可以分为两种 分组密码和序列密
  • 查询Windows默认编码格式

    开始 gt cmd gt chcp 然后显示一个数字 如936 则代表是GBK简体中文
  • unity生成透明背景的截图,截图背景图透明,UGUI scrollview滑动的时候不能遮罩3d模型

    转载 Unity3D Unity3D 摄像机带透明截图 静茹 鱼 博客园 using System using UnityEngine using System IO public class CropPicture MonoBehavio
  • Sonarqube安装插件报错An error has occurred. Please contact your administrator

    报错信息 Sonarqube安装插件时提示 An error has occurred Please contact your administrator 解决方法 1 查询报错日志 使用docker logs查询Sonarqube日志 插
  • jpress代码审计分享

    声明 出品 先知社区 ID 1871162774168111 以下内容 来自先知社区的1871162774168111作者原创 由于传播 利用此文所提供的信息而造成的任何直接或间接的后果和损失 均由使用者本人负责 长白山攻防实验室以及文章作
  • 【转载】一些比较好的电子资源网站

    SkyEye Project SkyEye是一个开源软件 opensource software 项目 中文名字是 天目 SkyEye的目标是在通用的Linux和Windows平台实现一个模拟集成开发环境 模拟基于ARM的嵌入式计算机系统
  • 《Linux C++》线程池

    为什么使用线程池 线程池的出现正是着眼于减少线程本身带来的开销 避免 即时创建 即时销毁 线程池应用场合 像大多数网络服务器 包括Web服务器 Email服务器以及数据库服务器处理数目巨大的连接请求 但处理时间却相对较短 并且实时性要求比较
  • 硬见小百科」这些PCB布局布线规则,你了解多少?

    元器件布局的10条规则 遵照 先大后小 先难后易 的布置原则 即重要的单元电路 核心元器件应当优先布局 布局中应参考原理框图 根据单板的主信号流向规律安排主要元器件 元器件的排列要便于调试和维修 亦即小元件周围不能放置大元件 需调试的元 器
  • Java中的sort()

    sort的第一种格式 sort的第二种格式 sort函数中cmp函数的使用方法 自定义排序基本方法 sort的第一种格式 sort函数的基本格式 默认排序为升序排序 Arrays sort 数组名 起始下标 终止下标 例 import ja
  • 【机器学习】机器学习建模调参方法总结

    文章目录 一 前言 1 1 数据来源 1 2 理论简介 二 知识总结 2 1 回归分析 2 2 长尾分布 2 3 欠拟合与过拟合 2 4 正则化 2 5 调参方法 2 5 1 贪心调参 坐标下降 2 5 2 网格调参GridSearchCV
  • JavaScript高手进阶:详解Eval加密

    在JavaScript编程中 涉及到代码加密 在混淆加密时代之前 用的最多的应该是种Eval加密 加密后的特征是以 eval function p a c k e r 为代码开始 相信很多人都见过这种代码 Eval加密效果例程 这是一种非常
  • MFC 解决中文乱码问题

    新的编译工具默认的是unicode编码方式 许多在多字节下面显示中文的方法已经不再适用了按照道理说设置为unicode编码后应该会很好的支持中文 但是实际情况很悲惨 显示的都是乱码 看到网上的很多方法都是把CSTRING转来转去 很头疼 感
  • powershell 删除指定文件夹及文件

    删除指定的文件夹 Get ChildItem C ccccc Recurse Where Object PsIsContainer Where Object FullName like test Remove Item Force Recu
  • SpringBoot配置多数据源

    项目框架 SpringBoot MyBatis Mysql 项目连接两个数据库源 1 application yml配置 使用DruidDataSource 主数据库为primary 副数据库为secondary 名称可以自己定义 只要和后
  • 如何使用Git进行版本控制

    在软件开发过程中 版本控制是一个非常重要的部分 它可以让开发人员更轻松地管理代码 集成代码 以及跟踪代码的变更历史 Git是一个广泛使用的版本控制工具 它的易用性和可扩展性使得它成为了开源社区的首选 在本文中 我们将介绍如何使用Git进行版
  • 转载 -- 按位异或的性质及其妙用

    https www jianshu com p 86a7cf855e51 文章摘要 1 按位异或 可以简单理解成 不进位加法 即 1 1 0 0 0 0 1 0 1 2 任何数和自己异或结果为零 3 按位异或的自反性 两次运算操作 可以将最
  • vs code下载慢的解决方法

    1 在官网Visual Studio Code Code Editing Redefined下载 大概率会出现如下情况 2 复制以上下载的链接地址 把以上截图红框标注的部分换成vscode cdn azure cn 这样会变成采用国内的镜像
  • canvas中的save和restore方法的作用

    save方法可以理解为暂存当前画笔的状态 接下来对画笔的操作都不会被保存下来 直到restore方法被调用 讲得通俗一点 就是说 调用save方法 就是把当前的笔放笔架上 换一支笔 调用restore方法时 再把刚才放到笔架上的笔再拿下来用
  • 使用Python对图像进行不同级别量化QP,使用RLE计算压缩比,并计算对应的PSNR

    写这篇博客源于 博友的提问 1 效果图 原图 VS QP 2 VS QP 4 VS QP 8效果图如下 QP量化是指把原始图像按像素级别划分取值 如QP 2 则 lt 128 取0 gt 128取128 QP 4 则 lt 64取0 lt