
色彩是图像处理的灵魂------无论是图像增强、目标分割还是内容检索,色彩特征的有效利用都能让算法效果事半功倍。本文将深入拆解图像处理中色彩空间转换、直方图均衡化、色彩聚类、白平衡四大经典色彩算法,结合Python+OpenCV实战代码,带你从原理到落地掌握色彩处理的核心技巧。
一、色彩空间转换:从RGB到"更聪明"的表示
1.1 RGB的局限性
RGB是最直观的色彩模型(红、绿、蓝三通道叠加),但它存在两个致命问题:
- 与人眼感知脱节:RGB的数值差异不等于人眼感知的差异(比如RGB(255,0,0)和RGB(0,255,0)的欧氏距离等于RGB(255,0,0)和RGB(255,255,0),但人眼觉得前者差异更大);
- 亮度与色彩耦合:调整亮度会同时改变色彩,不利于色彩分割等任务。
因此,实际应用中我们更常用HSV(色相-饱和度-明度)或Lab(明度-红绿-蓝黄) 空间。
1.2 HSV转换原理
HSV将色彩分解为:
- Hue(色相):0-180(OpenCV中),表示颜色种类(如红、绿、蓝);
- Saturation(饱和度):0-255,表示颜色鲜艳程度;
- Value(明度):0-255,表示亮度。
转换公式(以OpenCV的RGB范围0-255为例):
- 归一化:
r = R/255, g = G/255, b = B/255 - 计算最大值/最小值:
c_max = max(r,g,b), c_min = min(r,g,b), delta = c_max - c_min - 色相H:
- 若
delta=0,H=0; - 若
c_max=r,H=60*((g-b)/delta mod 6); - 若
c_max=g,H=60*((b-r)/delta + 2); - 若
c_max=b,H=60*((r-g)/delta + 4);
- 若
- 饱和度S:
S = delta/c_max(若c_max=0则S=0); - 明度V:
V = c_max。
OpenCV中cvtColor函数已封装转换逻辑,无需手动计算。
1.3 实战:RGB↔HSV/Lab转换
python
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 读取图像
img = cv2.imread("test.jpg")
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # OpenCV默认BGR,转RGB用于Matplotlib显示
# 转换色彩空间
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
img_lab = cv2.cvtColor(img, cv2.COLOR_BGR2Lab)
# 可视化对比
plt.figure(figsize=(15,5))
plt.subplot(131), plt.imshow(img_rgb), plt.title("RGB")
plt.subplot(132), plt.imshow(img_hsv), plt.title("HSV")
plt.subplot(133), plt.imshow(img_lab), plt.title("Lab")
plt.show()
# 提取HSV的V通道(明度)
v_channel = img_hsv[:,:,2]
plt.imshow(v_channel, cmap="gray"), plt.title("HSV-V通道")
plt.show()
效果分析:HSV的V通道直接对应亮度,Lab的L通道更贴合人眼对亮度的感知------这也是后续直方图均衡化选择V/L通道的原因。
二、彩色图像直方图均衡化:让色彩更"通透"
直方图均衡化的核心是拉伸像素值分布 ,提升图像对比度。但直接对RGB三通道均衡化会导致色彩失真(比如红色通道单独均衡化可能让红色过饱和),因此需在亮度通道操作。
2.1 原理:累积分布函数(CDF)映射
灰度直方图均衡化的公式:
- 计算灰度级
i的像素数n_i,总像素数N; - 计算概率密度:
p_i = n_i/N; - 计算累积分布:
CDF(i) = sum_{j=0}^i p_j; - 映射新灰度值:
s_i = 255 * CDF(i)。
彩色图像需先转换到HSV/Lab,对V/L通道均衡化后再转回RGB。
2.2 实战:HSV-V通道均衡化
python
# 对HSV的V通道进行直方图均衡化
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(img_hsv)
# 均衡化V通道
v_eq = cv2.equalizeHist(v)
# 合并通道并转回RGB
img_hsv_eq = cv2.merge([h, s, v_eq])
img_eq = cv2.cvtColor(img_hsv_eq, cv2.COLOR_HSV2RGB)
# 对比原图与均衡化结果
plt.figure(figsize=(10,5))
plt.subplot(121), plt.imshow(img_rgb), plt.title("原图")
plt.subplot(122), plt.imshow(img_eq), plt.title("HSV-V均衡化后")
plt.show()
# 对比V通道直方图
plt.figure(figsize=(10,5))
plt.subplot(121), plt.hist(v.ravel(), 256, [0,256]), plt.title("均衡化前V通道直方图")
plt.subplot(122), plt.hist(v_eq.ravel(), 256, [0,256]), plt.title("均衡化后V通道直方图")
plt.show()
效果分析:均衡化后图像对比度显著提升,暗部细节更清晰,且色彩未失真------这是直接RGB均衡化无法实现的。
三、色彩聚类:用K-Means提取主色调
色彩聚类是图像分割、风格迁移的基础,核心是利用K-Means算法将像素的色彩特征聚为K类,提取图像主色调或分割色彩相近的区域。
3.1 原理:Lab空间的K-Means聚类
由于Lab空间更贴合人眼感知,我们选择在Lab空间进行聚类:
- 将图像从RGB转为Lab,重塑为
(N,3)的像素矩阵(N为总像素数); - 用K-Means将像素分为K类,每个类的中心即代表一种主色调;
- 将像素替换为对应类的中心色,实现色彩分割。
3.2 实战:K-Means色彩聚类与主色调提取
python
from sklearn.cluster import KMeans
# 预处理:转换Lab并重塑
img_lab = cv2.cvtColor(img, cv2.COLOR_BGR2Lab)
pixels = img_lab.reshape((-1,3)) # 形状:(height*width, 3)
# K-Means聚类(K=5,提取5种主色调)
k = 5
kmeans = KMeans(n_clusters=k, random_state=42)
labels = kmeans.fit_predict(pixels)
centers = kmeans.cluster_centers_ # 聚类中心(Lab值)
# 将聚类结果映射回图像
centers = np.uint8(centers)
img_clustered = centers[labels].reshape(img_lab.shape)
img_clustered_rgb = cv2.cvtColor(img_clustered, cv2.COLOR_Lab2RGB)
# 可视化聚类结果
plt.figure(figsize=(10,5))
plt.subplot(121), plt.imshow(img_rgb), plt.title("原图")
plt.subplot(122), plt.imshow(img_clustered_rgb), plt.title(f"K={k}色彩聚类结果")
plt.show()
# 提取主色调并可视化
def lab2rgb(lab):
"""Lab转RGB(单像素)"""
lab = np.uint8([[lab]])
rgb = cv2.cvtColor(lab, cv2.COLOR_Lab2RGB)
return rgb[0,0]
# 计算各主色调占比
counts = np.bincount(labels)
proportions = counts / counts.sum()
# 绘制主色调饼图
colors = [lab2rgb(center) / 255 for center in centers]
plt.pie(proportions, colors=colors, labels=[f"{p:.2%}" for p in proportions], autopct="")
plt.title("图像主色调占比")
plt.show()
效果分析:聚类后图像被简化为5种主色调,主色调饼图直观展示了色彩分布------这在电商商品色彩分析、UI配色提取中广泛应用。
四、白平衡:消除色彩偏色的"灰度世界"算法
白平衡的目标是让白色物体在图像中呈现为白色,解决因光源(如白炽灯、荧光灯)导致的色彩偏色问题。经典的"灰度世界假设"是最常用的白平衡算法。
4.1 原理:灰度世界假设
假设:图像中RGB三通道的均值相等(即平均灰度为中性色) 。
校正公式:
- 计算RGB三通道的均值:
avg_r = mean(R), avg_g = mean(G), avg_b = mean(B); - 计算增益系数:
gain_r = avg_g / avg_r, gain_b = avg_g / avg_b(以绿色通道为基准); - 校正像素:
R' = R * gain_r, G' = G, B' = B * gain_b; - 截断超出0-255的像素值。
4.2 实战:灰度世界白平衡
python
# 读取偏色图像(比如白炽灯照明的图像)
img_tinted = cv2.imread("tinted.jpg")
img_tinted_rgb = cv2.cvtColor(img_tinted, cv2.COLOR_BGR2RGB)
# 灰度世界白平衡
b, g, r = cv2.split(img_tinted)
avg_b = np.mean(b)
avg_g = np.mean(g)
avg_r = np.mean(r)
# 计算增益
gain_b = avg_g / avg_b
gain_r = avg_g / avg_r
# 校正并截断
b_corrected = np.clip(b * gain_b, 0, 255).astype(np.uint8)
r_corrected = np.clip(r * gain_r, 0, 255).astype(np.uint8)
img_corrected = cv2.merge([b_corrected, g, r_corrected])
img_corrected_rgb = cv2.cvtColor(img_corrected, cv2.COLOR_BGR2RGB)
# 对比效果
plt.figure(figsize=(10,5))
plt.subplot(121), plt.imshow(img_tinted_rgb), plt.title("偏色原图")
plt.subplot(122), plt.imshow(img_corrected_rgb), plt.title("灰度世界白平衡校正后")
plt.show()
效果分析:校正后图像偏色被消除,白色物体恢复正常------灰度世界算法简单高效,适合大多数场景(若图像中无中性色,可改用"完美反射假设")。
五、总结与应用场景
本文拆解的四大色彩算法覆盖了图像处理的核心需求:
- 色彩空间转换:为后续算法提供更合理的特征空间;
- 直方图均衡化:提升图像对比度,优化视觉效果;
- 色彩聚类:实现图像分割、主色调提取;
- 白平衡:解决实际拍摄中的色彩偏色问题。
这些算法广泛应用于:
- 自动驾驶(道路分割、交通灯识别);
- 医学影像(病理切片色彩增强);
- 电商平台(商品图片色彩校正、主色调提取);
- 手机摄影(自动白平衡、人像色彩优化)。
掌握色彩处理的本质,就能让算法在"色彩维度"上更精准、更贴合实际需求------这正是图像处理的魅力所在。
代码说明:本文代码基于OpenCV 4.x、NumPy、Matplotlib、Scikit-learn,安装依赖:
bash
pip install opencv-python numpy matplotlib scikit-learn
如果觉得本文有帮助,欢迎点赞+收藏,关注博主获取更多图像处理算法解析!🚀