python - 同一图像的 2 个灰度图像有何不同?

标签 python opencv image-processing

读取灰度图像和将 3 channel 图像转换为灰度图像有什么区别?

为了清楚起见,如果我按如下方式读取图像:

gray_1 = cv2.imread("model.jpg", 0)

colored = cv2.imread("model.jpg")

gray_2 = cv2.cvtColor(colored, cv2.COLOR_RGB2GRAY)

print(gray_1.shape) #(1152,1536)
print(gray2.shape)  #(1152, 1536)

现在,如果我检查两个 numpy 数组 gray_1gray_2 是否相等,则它们不相等。

np.array_equal(gray_1, gray_2)

以上语句返回False。这是为什么? gray_1gray_2 有什么区别?

最佳答案

请注意,这个答案没有说明,也从未说明,以灰度加载与以彩色加载并随后转换为灰度之间没有区别。它只是声明:

1) OP 需要使用 cv2.COLOR_BGR2GRAY 而不是 cv2.COLOR_RGB2GRAY 来进行正确的比较,并且

2) 对于准备使用有损 JPEG 存储图像的任何人来说,差异可能可以忽略不计。


OpenCV native 以 BGR 顺序存储,因此真正的比较实际上是:

gray_2 = cv2.cvtColor(colored, cv2.COLOR_BGR2GRAY)

相对于使用 cv2.COLOR_RGB2GRAY


量化两幅图像“有何不同”可能会有所帮助,因为它们是直接以灰度加载还是以彩色加载然后随后进行转换,所以我计算了以下统计数据:

  • 绝对误差 - 只是不同的像素数

  • Peak Absolute Error - 任意两个对应像素之间的最大绝对差值

  • Mean Absolute Error - 对应像素之间的平均绝对差值

  • 均方误差 - 对应像素之间的平均平方差

  • 均方根误差 - 以上的平方根

如果您使用标准的 512x512 Lena 图像,并将直接作为灰度加载的图像与作为彩色加载并随后进行转换的图像进行比较,您将得到以下结果:

AE: 139
PAE: 4
MAE: 0.00072479248046875
MSE: 0.001220703125
RMSE: 0.034938562148434216

因此,在 262,144 个像素中,只有 139 个像素不同,并且任何两个像素之间的最大差异仅为 4,范围为 0..255,即更少大于1.6%

相比之下,如果比较以 JPEG 质量 90 和质量 89 保存的 Lena 图像,您会发现以下差异:

AE: 158575
PAE: 13
MAE: 0.9766883850097656
MSE: 2.2438392639160156
RMSE: 1.4979450136490378

所以,我是说 JPEG 质量上 1% 的差异会导致 100 倍的像素差异高达 3 倍。因此,您选择将数据存储为 JPEG 的事实比两种灰度转换方法的差异具有更大的影响,如果您真的关心准确性,您应该使用 PNG/TIFF/PPM 或其他一些无损格式。


#!/usr/bin/env python3

import math
import numpy as np
from PIL import Image
import cv2

def compare(im1, im2, metric):
   """
   Compare two images in terms of given metric.
   'AE'   Absolute Error. Simply the number of pixels that are different.
   'PAE'  Peak Absolute Error. The largest absolute difference between two corresponding pixels.
   'MAE'  Mean Absolute Error. The average difference between correspondng pixels.
   'MSE'  Mean Squared Error.
   'RMSE' Root Mean Squared Error.
   """

   assert(im1.shape==im2.shape)

   im1 = np.ravel(im1).astype(np.int64)
   im2 = np.ravel(im2).astype(np.int64)

   if metric == 'AE':
      # Return count of pixels that differ
      res = (im1 != im2).sum()
      return res

   if metric == 'PAE':
      # Return largest absolute difference
      res = np.abs((im1-im2)).max()
      return res

   if metric == 'MAE':
      # Return average absolute difference between corresponding pixels
      res = np.abs((im1-im2)).mean()
      return res

   # Calculate mean squared difference between corresponding pixels
   res = ((im1-im2)*(im1-im2)).mean()

   if metric == 'MSE':
      return res

   if metric == 'RMSE':
      return math.sqrt(res)


# Uncomment any one of the three following blocks

# Create greyscale image 640x480 filled with mid-grey
#w,h = 640,480
#im1 = np.zeros([h,w,1], dtype=np.uint8) + 128
#im2 = im1.copy()
#im2[1,1]=7

# Load first image as greyscale, second as colour but then convert to greyscale afterwards
#gray_1   = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)
#coloured = cv2.imread('lena.jpg',cv2.IMREAD_COLOR)
#gray_2   = cv2.cvtColor(coloured, cv2.COLOR_BGR2GRAY)

# Load Lena in 89 and 90 JPEG quality
gray_1   = cv2.imread('lena89.jpg',cv2.IMREAD_GRAYSCALE)
gray_2   = cv2.imread('lena90.jpg',cv2.IMREAD_GRAYSCALE)

res = compare(gray_1, gray_2, 'AE')
print('AE: {}'.format(res))
res = compare(gray_1, gray_2, 'PAE')
print('PAE: {}'.format(res))
res = compare(gray_1, gray_2, 'MAE')
print('MAE: {}'.format(res))
res = compare(gray_1, gray_2, 'MSE')
print('MSE: {}'.format(res))
res = compare(gray_1, gray_2, 'RMSE')
print('RMSE: {}'.format(res))

关于python - 同一图像的 2 个灰度图像有何不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55287834/

相关文章:

python - 使用 minidom 读取和写入 XML 中的特殊字符

Python Fabric 不会传入变量

python - 查找形状内的像素索引 : Opencv and Python

python-2.7 - 如何在opencv python中获取背景图像

python - 私有(private)名称修改功能

python - 将 double 转换为 float

python - 无法访问 GetCaptureProperty 或 python opencv 中的任何类似函数

c++ - opencv中不扭曲的同心圆

c++ - 找不到 Mexopencv mex 文件

c++ - 图像处理库