色彩空间转换(Color Space Conversion)是图像处理中的基础操作,用于在不同颜色表示系统之间进行转换。下面介绍常见的色彩空间及其转换方法,并提供Python实现示例。
常见色彩空间概述
| 色彩空间 | 主要用途 | 通道组成 | 特点 |
|---|---|---|---|
| RGB | 显示器显示 | 红(R)、绿(G)、蓝(B) | 设备相关,直观 |
| HSV/HSL | 颜色选择、分析 | 色调(H)、饱和度(S)、明度(V)/亮度(L) | 更符合人类感知 |
| LAB | 颜色差异测量 | 明度(L)、a(红绿轴)、b(黄蓝轴) | 设备无关,均匀色差 |
| YUV/YCbCr | 视频压缩 | 亮度(Y)、色度(UV/CbCr) | 分离亮度和色度 |
| CMYK | 印刷 | 青(C)、品红(M)、黄(Y)、黑(K) | 减色混合 |
Python基础转换方法
1. 使用OpenCV进行转换
import cv2
import numpy as np
# 读取图像(BGR格式)
img_bgr = cv2.imread('image.jpg')
# BGR转RGB
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
# BGR转HSV
img_hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV)
# BGR转LAB
img_lab = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2LAB)
# BGR转YCrCb
img_ycrcb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2YCrCb)
# 显示转换结果
def show_images(images, titles):
for i, (img, title) in enumerate(zip(images, titles)):
cv2.imshow(title, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
show_images(
[img_bgr, img_rgb, img_hsv[:,:,0], img_lab[:,:,0]],
['BGR', 'RGB', 'HSV-Hue', 'LAB-L']
)
2. 手动实现RGB转HSV
def rgb_to_hsv(rgb_img):
"""手动实现RGB到HSV转换"""
img = rgb_img.astype('float32') / 255.0
r, g, b = cv2.split(img)
# 计算值(Value)
v = np.maximum.reduce([r, g, b])
# 计算饱和度(Saturation)
min_val = np.minimum.reduce([r, g, b])
delta = v - min_val
s = np.where(v == 0, 0, delta / v)
# 计算色调(Hue)
h = np.zeros_like(v)
mask = delta != 0
# 红色为基准
idx = (v == r) & mask
h[idx] = (60 * ((g[idx] - b[idx]) / delta[idx]) + 360) % 360
# 绿色为基准
idx = (v == g) & mask
h[idx] = (60 * ((b[idx] - r[idx]) / delta[idx]) + 120) % 360
# 蓝色为基准
idx = (v == b) & mask
h[idx] = (60 * ((r[idx] - g[idx]) / delta[idx]) + 240) % 360
# 归一化到OpenCV标准范围
h = h / 2 # [0,180]
s = s * 255 # [0,255]
v = v * 255 # [0,255]
return cv2.merge([h, s, v]).astype('uint8')
# 使用示例
hsv_manual = rgb_to_hsv(img_rgb)
hsv_opencv = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2HSV)
# 比较手动实现与OpenCV结果
print("差异:", np.sum(np.abs(hsv_manual - hsv_opencv)))
高级色彩空间转换
1. RGB与LAB的精确转换
def rgb_to_lab(rgb_img):
"""
RGB转LAB色彩空间(精确实现)
参考: http://www.easyrgb.com/en/math.php
"""
# 转换为float32并归一化
rgb = rgb_img.astype('float32') / 255.0
# 线性化RGB(去除gamma校正)
mask = rgb <= 0.04045
rgb_linear = np.where(mask, rgb / 12.92, ((rgb + 0.055) / 1.055) ** 2.4)
# 转换为XYZ色彩空间
x = rgb_linear[...,0] * 0.4124 + rgb_linear[...,1] * 0.3576 + rgb_linear[...,2] * 0.1805
y = rgb_linear[...,0] * 0.2126 + rgb_linear[...,1] * 0.7152 + rgb_linear[...,2] * 0.0722
z = rgb_linear[...,0] * 0.0193 + rgb_linear[...,1] * 0.1192 + rgb_linear[...,2] * 0.9505
# 归一化到白点D65
x /= 0.95047
y /= 1.0
z /= 1.08883
# 非线性变换
epsilon = 216/24389
kappa = 24389/27
# 计算f(t)
def f(t):
return np.where(t > epsilon, t ** (1/3), (kappa * t + 16) / 116)
fx = f(x)
fy = f(y)
fz = f(z)
# 计算LAB
l = 116 * fy - 16
a = 500 * (fx - fy)
b = 200 * (fy - fz)
# 转换为OpenCV范围
l = l * 255 / 100
a = a + 128
b = b + 128
return cv2.merge([l, a, b]).astype('uint8')
# 使用示例
lab_manual = rgb_to_lab(img_rgb)
lab_opencv = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2LAB)
# 比较结果
print("L通道差异:", np.mean(np.abs(lab_manual[:,:,0] - lab_opencv[:,:,0])))
2. 色彩空间转换矩阵优化
def apply_color_matrix(img, matrix):
"""应用色彩转换矩阵"""
# 重塑为(像素数, 3)
orig_shape = img.shape
pixels = img.reshape(-1, 3).astype('float32')
# 添加齐次坐标
pixels = np.hstack([pixels, np.ones((pixels.shape[0], 1))])
# 应用矩阵变换
transformed = np.dot(pixels, matrix.T)

最低0.47元/天 解锁文章
1484

被折叠的 条评论
为什么被折叠?



