← 返回首页
图像灰度化
发表时间:2025-02-13 01:32:13
图像灰度化

在OpenCV中,将图像转换为灰度图像是一个非常常见的操作。灰度化处理是将彩色图像转换为灰度图像(即单通道黑白图像),这在很多图像处理任务中都非常有用,比如边缘检测、特征提取等。

1.灰度图

灰度图就是单通道图像,而单通道图是指维度数为2的图像。灰度图的每个像素点就只有一个值表示颜色,像素值的范围就是[0~255]。如使用RGB表示灰度为100的图像,三通道灰度图即RGB(100,100,100),而单通道灰度图只有其中一个有值。简而言之,灰度图就是黑白图。

2.RGB图灰度及通道理解

在彩色图像(或者说是RGB图像)中,可以用P(400,300,3)这样一个三维矩阵表示。其中,前面的400,300表示的是图像的空间信息,400表示行数,300表示列数。3表示的是有三种基本颜色(红R,绿G,蓝B)的通道,在其中一层矩阵如(400,300,1)红色通道矩阵,表示该颜色红色光的灰度值。

这里要解释一下灰度值概念,灰度值不是字面意义上的"黑白"值,而是指某颜色的亮度值,如上面(400,300,1)表示红色通道矩阵,红色的灰度值就储存在其中。每一个颜色通道都储存了其对应的灰度值,最后三层通道的灰度值像调色一样一调就可以根据三种原色中不同颜色的灰度值调出图片中想要的颜色。

总而言是,通道表示不同颜色的通道,(当然也有一些特殊通道,如alpha通道,存储图片透明度信息。)灰度值表示某颜色的亮度。

下面是使用opencv实现读取一张彩色图片,显示RGB三个通道上的灰度图。

import matplotlib.pyplot as plt
import cv2
import numpy as np

img = cv2.imread('./images/jpg/channel_demo.jpg')
b, g, r = cv2.split(img)
cv2.namedWindow("original_img", cv2.WINDOW_NORMAL)
cv2.imshow("original_img", img)
cv2.namedWindow("img_b", cv2.WINDOW_NORMAL)
cv2.imshow("img_b", b)
cv2.namedWindow("img_g", cv2.WINDOW_NORMAL)
cv2.imshow("img_g", g)
cv2.namedWindow("img_r", cv2.WINDOW_NORMAL)
cv2.imshow("img_r", r)
cv2.waitKey(0)

3.图像灰度的三种实现方法

3.1 加权平均法

在OpenCV中,实现加权平均法的图像灰度化可以通过手动计算灰度值来完成。加权平均法是一种常用的灰度化方法,其基本原理是根据人眼对不同颜色的敏感度,对RGB三个通道的像素值进行加权求和,得到灰度值。

加权平均法的公式为:

其中,R、G、B 分别是像素的红色、绿色和分蓝色量,权重分别为 0.299、0.587 和 0.114。这些权重是根据人眼对不同颜色的敏感度确定的,绿色权重最高,蓝色权重最低。OpenCV的BGR2GRAY就是使用了这个算法实现的。

使用NumPy的向量化操作来实现灰度化,避免显式循环。代码实现:

import cv2
import numpy as np

# 读取图像
image = cv2.imread('./images/png/test01.png')

# 检查图像是否读取成功
if image is None:
    print("Error: 图像加载失败,请检查路径是否正确!")
    exit()

# 使用NumPy的向量化操作计算灰度值
gray_image = (0.299 * image[:, :, 2] + 0.587 * image[:, :, 1] + 0.114 * image[:, :, 0]).astype(np.uint8)

# 显示原图和灰度图像
cv2.imshow('Original Image', image)
cv2.imshow('Gray Image', gray_image)

# 等待用户按键,然后关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()

在实际开发中,建议使用cv2.cvtColor函数直接将图像转换为灰度图像,因为它是经过优化的,效率更高且代码更简洁。

import cv2
import numpy as np

# 读取图像
image = cv2.imread('./images/png/test01.png')

# 检查图像是否读取成功
if image is None:
    print("Error: 图像加载失败,请检查路径是否正确!")
    exit()


gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 显示原图和灰度图像
cv2.imshow('Original Image', image)
cv2.imshow('Gray Image', gray_image)

# 等待用户按键,然后关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()

3.2 平均值法

平均值法是一种简单的图像灰度化方法,它通过取RGB三个通道像素值的平均值来计算灰度值。这种方法的公式为:

在实际开发中,我们通常使用向量化操作或cv2.transform,因为它们的效率更高且代码更简洁。 代码实现:

import cv2
import numpy as np

# 读取图像
image = cv2.imread('./images/png/test01.png')

# 检查图像是否读取成功
if image is None:
    print("Error: 图像加载失败,请检查路径是否正确!")
    exit()

# 定义平均值法的矩阵
average_matrix = np.array([[1 / 3, 1 / 3, 1 / 3]])

# 使用cv2.transform进行矩阵变换
gray_image = cv2.transform(image, average_matrix)

# 确保灰度图像的数据类型为uint8
gray_image = gray_image.astype(np.uint8)

# 显示原图和灰度图像
cv2.imshow('Original Image', image)
cv2.imshow('Gray Image', gray_image)

# 等待用户按键,然后关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()

3.3 最大值法

最大值法是一种图像灰度化方法,它通过取RGB三个通道中的最大值作为灰度值。这种方法的公式为:

在实际开发中,推荐使用向量化操作或cv2.reduce,因为它们的效率更高且代码更简洁。

代码实现:

import cv2
import numpy as np

if __name__ == "__main__":
    path = "./images/png/test01.png"
    image_np = cv2.imread(path)
    img_shape = image_np.shape
    image_np_gray = np.zeros((img_shape[0], img_shape[1]), dtype=np.uint8)  # image_np.copy()
    # 最大值灰度化
    for i in range(img_shape[0]):  # 按行读取图片的像素bgr
        for j in range(img_shape[1]):  # 对每一行按照列进行每一个像素格子进行读取
            image_np_gray[i, j] = max(image_np[i, j][0], image_np[i, j][1], image_np[i, j][2])  # 求灰度值
    cv2.imshow("image_np_gray", image_np_gray)
    cv2.waitKey(0)