查看全课大纲(第 13 / 93 节)
  1. 1.计算机视觉概述
  2. 2.计算机视觉应用场景
  3. 3.困难与挑战
  4. 4.开源库介绍
  5. 5.图像显示与存储
  6. 6.CLAHE
  7. 7.腐蚀膨胀与开闭运算
  8. 8.滤波与边缘填充
  9. 9.各种滤波
  10. 10.图像金字塔
  11. 11.傅里叶变换
  12. 12.短时傅里叶变换与小波变换
  13. 13.颜色特征与颜色直方图
  14. 14.几何特征_边缘
  15. 15.几何特征-角点与斑点
  16. 16.局部特征-SIFT特征描述子
  17. 17.局部特征-SURF特征描述子
  18. 18.局部特征-ORB特征描述子
  19. 19.其他特征描述子
  20. 20.传统图像分割技术
  21. 21.GraphCut
  22. 22.GrabCut
  23. 23.人脸检测的传统方法
  24. 24.行人检测的传统方法HOG+SVM
  25. 25.行人检测DPM
  26. 26.人工神经网络的架构
  27. 27.目标函数与梯度下降
  28. 28.误差反向传播
  29. 29.可手算的神经网络
  30. 30.改进目标函数与克服梯度消散
  31. 31.神经网络之传统神经网络与深度网络的差异
  32. 32.各种梯度下降算法
  33. 33.如何选择合适的梯度下降算法
  34. 34.避免过适应
  35. 35.CNN的架构
  36. 36.CNN的误差反向传播_卷积层
  37. 37.CNN的误差反向传播_池化层
  38. 38.分类所用的数据集
  39. 39.Alexnet详解
  40. 40.VGG详解
  41. 41.GoogLeNet_v1
  42. 42.BatchNormalization
  43. 43.GoogLeNet_v3v4
  44. 44.ResNet
  45. 45.ResNeXt
  46. 46.CNN设计准则
  47. 47.图像检索与推土机距离
  48. 48.基于颜色相似性
  49. 49.基于形状相似性
  50. 50.基于纹理相似性
  51. 51.基于局部特征相似性
  52. 52.DL的二值哈希编码
  53. 53.高维空间中检索KDTree
  54. 54.高维空间中检索LSH
  55. 55.目标识别任务综述
  56. 56.RCNN
  57. 57.SPP-Net
  58. 58.Fast R-CNN
  59. 59.Faster R-CNN
  60. 60.R-CNN系列模型回顾
  61. 61.R-FCN的设计思路
  62. 62.R-FCN的实现
  63. 63.YOLOv1
  64. 64.YOLOv2_9000
  65. 65.YOLOv3
  66. 66.图像分割应用场景与数据集
  67. 67.上采样的实现方式
  68. 68.FCN网络架构的由来
  69. 69.FCN构建细节
  70. 70.DeepLabv1
  71. 71.CRF
  72. 72.DeepLabv2
  73. 73.DeepLabv3
  74. 74.特定的医学影像分割任务
  75. 75.U-Net
  76. 76.3D U-Net
  77. 77.V-Net
  78. 78.DenseNet
  79. 79.病理切片分析任务及数据集
  80. 80.病理切片分析
  81. 81.图说任务及其传统处理方法
  82. 82.深度语言模型与RNN
  83. 83.LSTM及其变种
  84. 84.NIC模型
  85. 85.SAT模型
  86. 86.图说的性能指标
  87. 87.判别模型与生成模型
  88. 88.KL散度与JS散度
  89. 89.VAE
  90. 90.GAN的基本原理
  91. 91.DCGAN与CGAN
  92. 92.Wasserstein GAN
  93. 93.SRGAN

颜色特征与颜色直方图

小象实战讲义 · 基于深度学习的计算机视觉

在计算机视觉中,如何让机器“看懂”一张图片?第一步往往是提取图像的特征。颜色,作为人眼感知图像最直观的属性,自然也成为机器理解图像的首要特征。本节我们将学习如何用数学工具——颜色直方图,来量化、表达和比较图像的颜色特征,这是图像检索、分类等任务的基础。

💡 核心导读

  • 颜色特征的地位:颜色是图像最显著的特征之一,尤其在彩色图像中。
  • 两种直方图构建方法:量化颜色直方图适用于颜色分布有限的RGB/HSV空间;聚类颜色直方图则适用于颜色分布极广的Lab空间。
  • 直方图相似性度量的挑战:简单的L1或欧氏距离无法考虑相邻颜色之间的相似性。
  • 解决方案:引入二次式距离或对直方图进行平滑过滤,以更合理地衡量图像间的颜色相似度。

颜色特征:图像的“第一印象”

当我们观察一幅图像时,颜色往往是最先被注意到的属性。蓝天、绿草、红色的苹果——这些颜色信息构成了我们对图像内容最初步的理解。在计算机视觉中,颜色特征正是这种直观感知的数字化表达。它计算简单,对图像的旋转、缩放等几何变换不敏感,因此在许多视觉任务中作为基础特征被广泛应用。

那么,如何用一种简洁、有效的数学形式来描述一幅图像的颜色分布呢?答案就是颜色直方图。

量化颜色直方图

量化颜色直方图是最直观的构建方法。其核心思想是:先将整个颜色空间(如RGB或HSV)划分为若干个小的单元,称为bin。每个bin用一个代表性的颜色(通常是该单元的中心颜色)来指代。然后,遍历图像中的所有像素,判断每个像素的颜色落在哪个bin中,并对该bin的计数器加一。最终,统计每个bin中像素的数量,就形成了颜色直方图。

工作原理与示例

以HSV颜色空间为例,它是一个圆锥体模型。我们可以沿着色相(H)、饱和度(S)、明度(V)三个维度进行均匀划分。例如,将色相分为若干份,饱和度从中心(灰色)到边缘(纯色)分为几层,明度从黑到白也分为几层。这样,整个HSV空间就被划分成了许多小格子。

import numpy as np
import cv2

# 为了演示,我们手动构造一个简单的“图像”,用HSV值表示
# 假设图像只有4个像素,每个像素用(H, S, V)表示,H范围[0,179], S,V范围[0,255]
pixels_hsv = np.array([
    [10, 200, 230],   # 偏红高饱和
    [12, 190, 220],   # 偏红高饱和(与第一个很接近)
    [100, 210, 150],  # 偏蓝(H=100 对应约 200° 色角)
    [30, 50, 200]     # 偏黄低饱和
], dtype=np.uint8)

# 1. 量化:这里我们简化演示,仅对色相(H)进行粗量化
# 将0-179的色相范围划分为6个bin,每个bin范围30
def quantize_hue(hue_value):
    bin_idx = hue_value // 30  # 0,1,2,3,4,5 共6个bin
    return bin_idx

# 2. 统计直方图
hist_bins = 6
hist = np.zeros(hist_bins, dtype=int)

for pixel in pixels_hsv:
    h_bin = quantize_hue(pixel[0])
    hist[h_bin] += 1

print("量化后的色相bin索引(每个像素):", [int(quantize_hue(p[0])) for p in pixels_hsv])
print("颜色直方图(统计每个bin的像素数):", hist)
量化后的色相bin索引(每个像素): [0, 0, 3, 1]
颜色直方图(统计每个bin的像素数): [2 1 0 1 0 0]

从输出可以看出,前两个偏红的像素(色相10和12)都被划分到了第0个bin(色相0-29度),因此该bin的计数值为2。这就是量化颜色直方图的生成过程。

优势与不足

优势:

  • 计算高效:bin是预先定义好的,只需要简单的查找和计数操作,速度很快。

不足:

  1. 量化问题:如何划分bin(划分的粗细)是个难题。划分太细,直方图会非常稀疏(很多bin是0);划分太粗,又会把视觉上差异明显的颜色混为一谈,丢失细节。
  2. 稀疏性:对于一张具体的图片,其颜色只占据整个颜色空间的很小一部分,导致直方图中大部分bin的值为0,如上例中的bin 2,4,5。
  3. 相似性度量缺陷:假设两幅图的颜色直方图几乎一样,只是整体颜色稍微偏了一点点(例如所有像素的色相都增加了5度),使大量像素落入与原来相邻的bin(当bin划分较细、宽度不超过5°时尤其明显)。如果用L1距离或欧氏距离计算,它们会被判定为非常不相似,但这显然不符合人眼的感知。

聚类颜色直方图

当颜色空间本身非常庞大时(例如Lab颜色空间),量化直方图的稀疏性问题会变得极其严重。Lab空间是为了数字化描述人眼视觉感应而设计的,它包含了正常人眼能看到的所有颜色,且与显示设备无关。

  • L分量:亮度,范围0(纯黑)到100(纯白)。
  • a分量:从品红色(+127)到深绿色(-128)的范围。
  • b分量:从黄色(+127)到蓝色(-128)的范围。

对于Lab这样广阔的颜色空间,预先划分出所有可能的bin是不现实的。聚类颜色直方图提供了另一种思路:让数据自己告诉我们应该有哪些bin。

工作原理

  1. 聚类:将图像中所有像素的颜色值(在Lab空间或其他空间)视为数据点,使用聚类算法(如K-Means)将这些点聚合成若干类(例如K类)。
  2. 定义bin:每个聚类中心就代表一个bin。
  3. 统计:统计属于每个聚类的像素数量,形成直方图。

这样做的好处是,直方图的bin(即聚类中心)是自适应于当前图像颜色分布的,避免了在颜色稀疏区域无效地设置大量bin,使得直方图更紧凑、信息密度更高。

# 演示聚类思想。我们使用一个更简单的2D例子来模拟颜色聚类。
import numpy as np

np.random.seed(42)  # 固定随机种子以保证结果可复现
# 模拟两类颜色点:红色调(集中在x=2附近)和蓝色调(集中在x=8附近)
red_points = np.random.randn(30, 2) * 0.5 + [2, 5]
blue_points = np.random.randn(20, 2) * 0.5 + [8, 5]
all_points = np.vstack([red_points, blue_points])  # 共50个点,模拟50个像素的颜色

# 简化演示:我们“事先知道”有两类,手动指定两个初始中心
centers = np.array([[1, 5], [9, 5]])  # 初始聚类中心
print("初始聚类中心:\n", centers)

# 执行一轮简单的K-Means分配(仅演示分配步骤,不迭代更新中心)
def assign_points(points, centers):
    distances = np.linalg.norm(points[:, np.newaxis, :] - centers[np.newaxis, :, :], axis=2)
    labels = np.argmin(distances, axis=1)
    return labels

labels = assign_points(all_points, centers)
hist_cluster = np.bincount(labels, minlength=len(centers))
print("像素点聚类标签(前10个):", labels[:10])
print("聚类颜色直方图:", hist_cluster)
初始聚类中心:
 [[1 5]
 [9 5]]
像素点聚类标签(前10个): [0 0 0 0 0 0 0 0 0 0]
聚类颜色直方图: [30 20]

输出显示,50个像素点被分配到了两个聚类中,分别有30个和20个点,形成了两个bin的直方图。在实际应用中,我们会使用更严谨的K-Means算法迭代优化中心点。

如何比较颜色直方图?

构建直方图的最终目的是为了比较,例如判断两幅图像的颜色是否相似。最简单的方法是计算两个直方图向量之间的L1距离(曼哈顿距离) 或L2距离(欧氏距离)。

# 假设有两幅图的量化颜色直方图(6个bin)
import numpy as np

hist1 = np.array([20, 5, 0, 3, 0, 0])  # 图像1的直方图
hist2 = np.array([0, 22, 3, 4, 0, 0])  # 图像2的直方图,整体颜色“偏移”了一个bin

# 计算L1和L2距离
l1_dist = np.sum(np.abs(hist1 - hist2))
l2_dist = np.sqrt(np.sum((hist1 - hist2) ** 2))

print("直方图1:", hist1)
print("直方图2:", hist2)
print("L1距离:", l1_dist)
print("L2距离:", l2_dist)
直方图1: [20  5  0  3  0  0]
直方图2: [ 0 22  3  4  0  0]
L1距离: 41
L2距离: 26.43860813280457

计算出的距离值很大,意味着这两幅图在简单的距离度量下非常不相似。但设想一个场景:图像1主要是深红色,图像2主要是稍浅一点的红色。由于量化误差,深红色落在了bin1,浅红色落在了bin2。在人眼看来,这两幅图颜色是相似的,但直方图距离却给出了相反的判断。

改进方法:考虑颜色相似性

为了解决这个问题,我们需要在计算距离时,考虑不同bin所代表颜色之间的相似度。两种常见方法是:

  1. 二次式距离 (Quadratic Form Distance): 它不仅计算直方图对应位置的差异,还通过一个颜色相似度矩阵A,将不同位置(不同颜色)的差异关联起来。公式为: DQ(H1,H2)=(H1−H2)TA(H1−H2)D_Q(H_1, H_2) = \sqrt{(H_1 - H_2)^T A (H_1 - H_2)} 其中矩阵A的元素 aija_{ij} 表示第i个bin的颜色与第j个bin的颜色之间的相似度(例如用 aij=1−dij/dmax⁡a_{ij}=1-d_{ij}/d_{\max} 定义,dijd_{ij} 是两个bin代表色在颜色空间中的距离,dmax⁡d_{\max} 为该空间中的最大距离)。相似的颜色之间 aija_{ij} 值大,即使直方图峰值错开一个bin,也能通过矩阵A的“平滑”作用得到较小的距离。

  2. 直方图平滑过滤 (Histogram Smoothing): 在统计直方图之前或之后,对每个像素的“贡献”进行平滑。一个像素不仅对其所属的bin有贡献,也对其相邻(颜色相似)的bin有部分贡献。这相当于在统计直方图时使用了“软分配”,而不是“硬分配”,生成的直方图本身就带有平滑效果,再用常规距离计算就会更合理。

# 伪代码:二次式距离计算思路
1. 计算颜色相似度矩阵A(例如,基于Lab空间颜色距离的指数衰减函数)。
2. 计算直方图差值向量 d = H1 - H2。
3. 计算二次式距离 distance = sqrt( d.T @ A @ d )。

# 伪代码:直方图平滑思路
1. 对于每个像素的颜色c,找到K个最近的颜色bin中心。
2. 根据c到这些bin中心的距离,按一定权重(如高斯权重)将像素计数分配到多个bin中。
3. 生成平滑后的直方图。

📝 动手练一练

  1. 概念辨析:假设你有一张主要在Lab颜色空间分布的风景照片,天空是渐变的蓝色,草地是渐变的绿色。如果你想用一个128维的向量来表达它的颜色特征,你会选择量化颜色直方图还是聚类颜色直方图?为什么?
👉 点击查看参考答案

参考答案: 应该选择聚类颜色直方图。

  • 原因:Lab颜色空间非常广阔,包含的颜色数量极多。如果使用量化直方图,为了覆盖所有可能颜色,需要将三维的L、a、b通道都划分得很细,这会导致bin的数量爆炸(远超过128个),而实际图像用到的颜色只是其中很小一部分,生成的128维量化直方图会极度稀疏(大部分是0),无法有效表达特征。
  • 聚类直方图的优势:通过聚类,我们可以直接将特征维度设置为128(即聚成128类)。算法会自适应地在图像颜色实际分布的区域(蓝色渐变区和绿色渐变区)找到有代表性的128个颜色中心作为bin。这样生成的128维直方图是稠密的,每个bin都有一定的像素贡献,能更紧凑、更有代表性地表达这张特定图像的颜色分布。
  1. 手算理解:有两幅单通道灰度图像(像素值0-255),我们将其量化为4个bin:bin1:[0-63], bin2:[64-127], bin3:[128-191], bin4:[192-255]。图像A的直方图为 H_A = [10, 40, 30, 20],图像B的直方图为 H_B = [5, 45, 35, 15]。请计算它们之间的L1距离和L2距离。如果图像C的直方图为 H_C = [40, 10, 20, 30],你觉得哪两幅图像看起来颜色分布更相似?这反映了简单距离度量的什么局限?
👉 点击查看参考答案

计算过程:

  • A与B的L1距离:|10-5| + |40-45| + |30-35| + |20-15| = 5+5+5+5 = 20
  • A与B的L2距离:sqrt((5)^2 + (5)^2 + (5)^2 + (5)^2) = sqrt(100) = 10
  • A与C的L1距离:|10-40| + |40-10| + |30-20| + |20-30| = 30+30+10+10 = 80
  • A与C的L2距离:sqrt((30)^2 + (30)^2 + (10)^2 + (10)^2) = sqrt(900+900+100+100)= sqrt(2000) ≈ 44.72

分析: 从数值上看,A与B的距离(L1=20, L2=10)远小于A与C的距离(L1=80, L2≈44.72)。因此,简单距离度量认为A和B更相似。

  • 观察直方图:A和B的形状非常接近,都是中间高(bin2, bin3像素多),两头低(bin1, bin4像素少),只是整体计数有些许浮动。这对应了两幅图像整体亮度和对比度非常接近。
  • A和C的形状则完全相反,A是中间高,C是两头高。
  • 人眼感知:如果A是一张正常曝光的照片,B可能是其亮度稍微调整后的版本,两者内容看起来会非常相似。而C可能是一张严重过曝或欠曝、或者负片效果的图片,与A差异巨大。
  • 局限的反映:这个例子说明,L1/L2距离能够捕捉直方图形状的差异。对于颜色分布形状相似但整体亮度有偏移的图像,它们能给出“相似”的判断。这正是我们想要的。然而,本节正文中提到的“错开一个bin”的问题,是形状相似但峰值位置有平移的情况,那是简单距离无法很好处理的另一种局限。

本章小结

本节我们深入探讨了图像最基础的特征——颜色特征,及其核心表达工具颜色直方图。我们学习了两种构建直方图的方法:适用于颜色分布有限空间的量化颜色直方图,以及适用于广阔颜色空间的聚类颜色直方图。更重要的是,我们认识到,将直方图用于图像相似性比较时,必须考虑颜色本身的相似性,为此引入了二次式距离和直方图平滑等改进方法。颜色直方图是许多视觉任务的起点,理解其原理与局限,是构建更复杂视觉系统的基石。需要说明的是,手工设计的颜色直方图在今天更多用作快速基线、传统特征拼接和颜色敏感场景的初筛;在图像分类、检索等任务上,端到端卷积网络学到的特征通常更强。

📋 行动清单

  • 在脑海中复现量化颜色直方图的构建过程:划分颜色空间 -> 像素归类 -> 统计计数。
  • 理解聚类颜色直方图“数据驱动生成bin”的核心思想,并与量化方法进行对比。
  • 思考:如果让你设计一个简单的图像颜色检索系统,仅基于颜色直方图,你会如何选择直方图类型和相似度度量方法?

—— 小象教研组

配套资料 · 直接下载

课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。

  • 第3章《图像特征与描述》配套课件(PDF)
    PDF · 5.2MB · 原课教辅
    下载
  • 第3章《图像特征与描述》配套代码包
    ZIP · 0.9MB · 原课教辅
    下载
  • 第3章《图像特征与描述》配套代码包(补充素材 1)
    ZIP · 0.2MB · 原课教辅
    下载