首页 > 编程问答 >为什么我似乎无法通过编程证明从 jpeg 创建的 png 对于任何给定像素都是相同的?

为什么我似乎无法通过编程证明从 jpeg 创建的 png 对于任何给定像素都是相同的?

时间:2024-07-26 11:02:21浏览次数:12  
标签:python image image-processing rust rgb

因此 png 是无损的 - 这意味着它们以某种方式压缩,因此它们代表的数据不会丢失。 因此,假设颜色深度和yadda yadda相同,从jpeg创建的png应该是像素相同的。 果然,这很容易证明,只需打开 Krita 或 GIMP,然后在像素级别手动检查 jpeg 与从 jpeg 创建的 png,读取相同任意像素的单独 RGB 值即可。


因此那么为什么我很难找到一种通过编程语言来证明这一点的方法呢? 我也在 Python 和 Go 中尝试了以下设置,结果相当 iirc。 所有这些都将显示从 jpeg 到 png 的单个 R、G 或 B 值的差异。

use image;
use std::env;

fn main() {
    println!("Hello, world!");

    let file1 = "image.png";
    let file2 = "image.jpeg";

    let img1 = image::open(file1).unwrap();
    let img2 = image::open(file2).unwrap();

    let img1_rgb = img1.to_rgb8();
    let img2_rgb = img2.to_rgb8();

    let mut img1_iter = img1_rgb.pixels();
    let mut img2_iter = img2_rgb.pixels();

    let mut i = 0;
    let length = img1_iter.len();

    while i < length {
        let pixel1 = img1_iter.next();
        let pixel2 = img2_iter.next();

        println!("Pixel 1: {:?} Pixel 2: {:?}", pixel1, pixel2);

        if pixel1 != pixel2 {
            println!("Difference found: {:?}, {:?}", pixel1, pixel2);
        }

        println!();
        i += 1;
    }
}

这应该将两个图像存储为 8 位 RGB 值。 然而,当我通过 Krita 和 Gimp 考虑 jpeg 和 png 图像中的样本图像输入大部分都是纯黄色(R 和 G 255,蓝色 0)时,我的程序将报告 jpeg 为 254, 254, 0对于黄色像素。 在我的图像中发现的其他颜色也将每个颜色值偏离一位 - 有时它仅限于单个颜色值,有时它是多个颜色值(就像纯黄色的情况一样)。

这里是一个快速的 python 示例演示了相同的事情:

from PIL import Image

png = Image.open("cat.png")
jpg = Image.open("cat.jpg")

pngPixels = png.load()
jpgPixels = jpg.load()


width, height = png.size

print("Width: ", width, "Height: ", height)

for x in range(width):
    for y in range(height):
        if pngPixels[x,y] != jpgPixels[x,y]:
            print("Discrepancy at: ", x, " y: ", y)
            print("png: ", pngPixels[x,y], "jpeg: ", jpgPixels[x,y])
            print()

我什至可以不做任何更改地添加这些行:

png = png.convert('RGB')
jpg = jpg.convert('RGB')

对我来说,我正在测试的所有三个编程库都不正确,这似乎很奇怪,但似乎更奇怪的是,Krita 和 GIMP 无法正确理解像素颜色之类的东西。 那么这里发生了什么?

我也尝试了从 jpeg 创建 png 的不同方法。 我尝试过从 GIMP、Krita 导出,使用不同的导出选项,甚至使用一两个命令行工具。 结果都是一样的,iirc。


我唯一的想法是,jpeg 中嵌入了一些颜色配置文件,这些库无法正确读取这些颜色配置文件,但 Krita/GIMP 仍在考虑这些颜色配置文件。 我该如何解决这个问题? 我可以采取哪些步骤来尝试解决此问题? 我知道这些图像在像素级别上确实是相同的,但我仍然想要一种通过编程问题“证明”这一点的方法。


你发现的区别是由于 JPEG 使用的有损压缩算法和用于表示颜色的不同色彩空间造成的。虽然你看到 Krita 和 GIMP 中的图像看起来相同,但这是因为这些应用程序处理颜色配置文件和在显示器上显示图像。

以下是分解发生的事情:

  1. JPEG 压缩: JPEG 使用有损压缩算法,这会在一定程度上降低图像质量以减小文件大小。此过程涉及丢弃一些图像数据,这会导致解压缩图像时颜色值略有不同。

  2. 色彩空间: JPEG 图像通常以 YCbCr 色彩空间存储,该色彩空间将颜色信息分离成亮度(Y)和两个色差分量(Cb 和 Cr)。另一方面,PNG 使用 RGB 色彩空间。从 JPEG 到 PNG 的转换需要色彩空间转换,这可能会导致由于舍入和不同的颜色表示方法而导致轻微的颜色差异。

你用来打开和比较图像的图像库可能没有以完全相同的方式处理 JPEG 解压缩和色彩空间转换。这可能导致像素值存在细微差异,即使差异对于人眼来说并不明显。

以下是解决该问题的可能方法:

  • 颜色容差: 与其比较像素的精确 RGB 值,不如使用颜色容差或阈值。这将允许颜色值存在较小的差异,考虑到由于压缩和色彩空间转换而产生的细微变化。
  • 色彩空间转换: 确保在比较之前将两个图像都转换为相同的色彩空间(例如 sRGB)。这将最大程度地减少由于不同的色彩空间表示而产生的差异。
  • 使用专门的图像比较库: 考虑使用专为图像比较而设计的库,例如 ImageMagick。这些库通常具有处理颜色容差、色彩空间和其他可能影响比较结果的因素的算法。

示例 Python 代码(使用颜色容差):

from PIL import Image

def compare_images(image1_path, image2_path, tolerance=3):
    """
    使用给定的容差比较两个图像的像素。

    Args:
        image1_path (str):第一个图像的路径。
        image2_path (str):第二个图像的路径。
        tolerance (int):允许的颜色值差异(默认值为 3)。

    Returns:
        bool:如果图像在给定的容差范围内被认为相同,则为 True,否则为 False。
    """

    image1 = Image.open(image1_path).convert('RGB')
    image2 = Image.open(image2_path).convert('RGB')

    if image1.size != image2.size:
        return False

    width, height = image1.size
    for y in range(height):
        for x in range(width):
            pixel1 = image1.getpixel((x, y))
            pixel2 = image2.getpixel((x, y))
            for i in range(3):  # 比较 RGB 值
                if abs(pixel1[i] - pixel2[i]) > tolerance:
                    return False
    return True

# 示例用法:
image1_path = "image.png"
image2_path = "image.jpeg"

if compare_images(image1_path, image2_path):
    print("图像在容差范围内相同。")
else:
    print("图像不同。")

这将比较两个图像的像素,允许每个 RGB 值之间存在小的差异(由 tolerance 参数定义)。通过调整容差,你可以控制比较的严格程度。

标签:python,image,image-processing,rust,rgb
From: 78796072

相关文章

  • python安装第三方库的国内镜像
    直接:pipconfigsetglobal.index-urlhttps://pypi.doubanio.com/simple设置了全局的第三方库的下载文件镜像请求网址。安装第三方库:pipinstallscrapy--scrapy第三方库名称 pip从国内镜像安装的命令使用中国大陆地区的Python包镜像服务时,可以通过修改p......
  • 如何将Python嵌入.Net?
    我尝试基于文档此处和此处使用pythonnet将Python嵌入到.Net中。这是我的代码Runtime.PythonDLL=@"D:\Dev\Console\.conda\python311.dll";PythonEngine.Initialize();dynamicsys=Py.Import("sys");Console.WriteLine("Pythonversion:&quo......
  • 使用pybind11封装c++的dll,供python调用
    用pip安装好pybind11 文件清单,都写在一个目录里//文件名:add.cppextern"C"doubleadd(doublein1,doublein2){returnin1+in2;}//文件名:sub.cppextern"C"doublesub(doublein1,doublein2){returnin1-in2;}//文件名:mul.cppextern"......
  • python-myStudyList
     1  下载软件1.1下载python最新版本并安装下载地址:百度搜索python官网。WelcometoPython.org。 1.2官网学习网页:PythonTutorials–RealPython   1.3也可以下载集成环境软件Anaconda。 Anaconda软件商城官方正版免费下载(msc23.cn) 2 ......
  • Python语法基础
    基本语句输入input() eg:输出print(内容)注释单行注释:#注释内容多行注释:"""注释内容"""数据类型: 字面量:整型、浮点数、字符串......intfloatstring查看数据类型:type(数据)查看数据类型 转换函数int(x):将x转换成整数类型float(x):将x转......
  • PyTesseract 不提取文本?我是所有这些Python的新手,请需要h3lp
    它不想从图像中提取文本,就像终端保持黑色并带有空格,就像它实际上试图提取文本一样,这是我的代码和图像从PIL导入图像导入pytesseract导入CV2“C:\用户\埃米利亚诺\下载\practic.png”pytesseract.pytesseract.tesseract_cmd="C:\ProgramFiles\Tesseract-OCR\tesseract.exe......
  • Python安装第三方库
    Python安装PILPIL(PythonImagingLibrary)是一个旧的Python库,用于处理图像。然而,PIL已经不再维护,并被一个名为Pillow的库所取代。Pillow是PIL的一个分支,并且完全兼容PIL。建议使用Pillow而不是PIL。pipinstallpillowPython安装moviepymoviepy是一个用于视频编辑的Python库,......
  • 优化Python中图像中的OCR文本检测
    我目前正在用python编写一个程序,该程序获取包含大量文本的图像,将其提取到.txt文件,然后将找到的单词与另一个文件中的单词列表进行比较,并创建一些坐标(根据像素)在图像中找到的单词中,如果找到图像,则会在图像中绘制红色方块。到目前为止,我已经正确处理了坐标部分,在单词周围绘制了......
  • Python保存字典类型数据到文件的三种方法
    1、在Python中使用pickle模块的dump函数将字典保存到文件中importpicklemy_dict={'Apple':4,'Banana':2,'Orange':6,'Grapes':11}#保存文件withopen("myDictionary.pkl","wb")astf:pickle.dump(my_dict,tf)......
  • 《最新出炉》系列入门篇-Python+Playwright自动化测试-53- 处理面包屑(详细教程)
    1.简介面包屑(Breadcrumb),又称面包屑导航(BreadcrumbNavigation)这个概念来自童话故事“汉赛尔和格莱特”,当汉赛尔和格莱特穿过森林时,不小心迷路了,但是他们发现沿途走过的地方都撒下了面包屑,让这些面包屑来帮助他们找到回家的路。所以,面包屑导航的作用是告诉访问者他们在网站中......