查看全课大纲(第 3 / 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

困难与挑战

计算机视觉的难点与挑战

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

在上一节,我们领略了计算机视觉(Computer Vision)的广阔应用前景。然而,从“看到”到“看懂”,从“像素值”到“语义”,计算机需要跨越一道巨大的鸿沟。本节将带你深入理解计算机视觉面临的核心挑战,这些挑战既是传统方法的难点,也是驱动深度学习技术不断发展的根本动力。理解这些挑战,将帮助你建立对后续所有模型设计初衷的深刻洞察。

💡 核心导读

  • 感知鸿沟:理解人类与计算机“看”图的本质差异,即从“语义”到“像素矩阵”的鸿沟。
  • 核心挑战:掌握计算机视觉面临的七大经典挑战:视角变化、光照变化、尺度变化、形态变化、背景混淆与干扰、遮挡、类内物体外观差异。
  • 问题根源:认识到这些挑战源于三维世界到二维图像的映射损失、物理世界的不确定性以及语义的复杂性。
  • 目标导向:明确计算机视觉的根本目标是构建从像素值到高层语义的桥梁。

人类与计算机的感知鸿沟

我们首先回到一个根本性的问题:人类和计算机是如何“看”一张图片的?

对人类而言,视觉感知是一个高度集成且带有先验知识的认知过程。当我们看到一张爱因斯坦的肖像时,视网膜接收到的光信号会立刻被大脑处理。我们几乎不假思索地就能识别出图像中的灰度变化、色差构成了一个特定人物的面部特征,并将其与我们记忆中的知识关联起来,得出“这是爱因斯坦”的结论。这个过程快速、自然,且充满了高层语义理解——我们知道这是一个物理学家,他的标志性发型等等。

然而,对于没有任何先验知识的计算机来说,它“看到”的完全是另一番景象。计算机存储和处理的图像,本质上是一个数字矩阵。

例如,一张灰度图像在计算机中就是一个二维数组(矩阵),数组中的每个元素(像素)用一个数值表示其亮度,通常0代表纯黑,255代表纯白。一张彩色图像则通常由红(R)、绿(G)、蓝(B)三个通道的矩阵叠加而成。

import numpy as np

# 模拟计算机“看到”的一张 3x3 的微小灰度图像
tiny_gray_image_matrix = np.array([
    [0, 128, 255],
    [64, 192, 32],
    [255, 0, 128]
], dtype=np.uint8)

print("计算机‘眼中’的灰度图像(3x3 像素矩阵):")
print(tiny_gray_image_matrix)
计算机‘眼中’的灰度图像(3x3 像素矩阵):
[[  0 128 255]
 [ 64 192  32]
 [255   0 128]]

这仅仅是一堆从0到255的数字。计算机无法从[[0, 128, 255], ...]这组数字中直接理解“这是爱因斯坦”、“这是方向盘”或“这是一只手”。它不知道哪些像素共同构成了一个有意义的“整体”(物体),更无法理解“手离开了方向盘”这种涉及物体关系、状态和意图的高层语义。

因此,计算机视觉的根本目标,就是解决“像素值”与“语义”之间的巨大鸿沟。我们需要设计算法和模型,让计算机能够从底层的像素矩阵出发,逐步识别出边缘、角点、纹理等低级特征,再组合成部件、物体等中级特征,最终理解场景、关系、行为等高级语义。接下来,我们将探讨在实现这一目标道路上的具体挑战。

计算机视觉的研究挑战

即使我们教会计算机从像素中提取特征,现实世界图像的复杂性也给识别和理解带来了巨大困难。这些挑战主要源于三维物理世界向二维图像投影过程中信息的丢失,以及现实世界本身的变化性和复杂性。

视角变化 (Viewpoint Variation)

我们生活在三维世界,而相机捕捉的是二维图像。同一个三维物体,从不同角度观察,在二维图像上会呈现出完全不同的样子。

import numpy as np

# 假设一个简单三维“L”形物体在不同视角下的二维投影(极度简化示意)
# 视角1:正面看
view_1 = np.array([
    [1, 1, 0],
    [1, 0, 0],
    [1, 0, 0]
])
# 视角2:顺时针旋转90度后看(非零格数必须与视角1相同)
view_2 = np.array([
    [1, 1, 1],
    [0, 0, 1],
    [0, 0, 0]
])

print("视角1(正面)投影:")
print(view_1)
print("\n视角2(旋转后)投影:")
print(view_2)
print("\n对计算机而言,这两个矩阵可能代表完全不同的事物。")
视角1(正面)投影:
[[1 1 0]
 [1 0 0]
 [1 0 0]]

视角2(旋转后)投影:
[[1 1 1]
 [0 0 1]
 [0 0 0]]

对计算机而言,这两个矩阵可能代表完全不同的事物。

就像课程视频中展示的雕塑旋转示例,计算机必须学会“视角不变性”,即理解这些外观迥异的图像实际上对应同一个物体。早期的特征描述子如SIFT (Scale-Invariant Feature Transform) 的一大贡献就是其旋转不变性,而深度学习模型则通过数据增强(如随机旋转训练图片)和网络本身的学习能力来应对这一挑战。

光照变化 (Illumination Change)

光线是成像的基础,但其强度、方向和色温的微小变化都会极大改变像素值。在阴影、高光、背光等条件下,同一物体的颜色和纹理在图像中可能差异巨大。

import numpy as np

# 模拟同一简单物体在不同光照下的像素值(假设物体本身反射率一致)
# 强光照射区域
high_light = np.full((3, 3), 250, dtype=np.uint8)
# 正常光照
normal_light = np.full((3, 3), 150, dtype=np.uint8)
# 弱光/阴影区域
low_light = np.full((3, 3), 50, dtype=np.uint8)

print("强光下像素值矩阵:")
print(high_light)
print("\n正常光照下像素值矩阵:")
print(normal_light)
print("\n弱光下像素值矩阵:")
print(low_light)
print("\n尽管代表同一物体,像素值却相差数倍。")
强光下像素值矩阵:
[[250 250 250]
 [250 250 250]
 [250 250 250]]

正常光照下像素值矩阵:
[[150 150 150]
 [150 150 150]
 [150 150 150]]

弱光下像素值矩阵:
[[50 50 50]
 [50 50 50]
 [50 50 50]]

尽管代表同一物体,像素值却相差数倍。

如同课程视频中的小企鹅示例,光线从不同方向打来,产生的明暗和影子完全不同。计算机视觉算法需要区分哪些像素变化是由光照引起的(应被忽略),哪些是由物体本身属性或边界引起的(应被关注)。直方图均衡化 (Histogram Equalization) 等传统图像处理技术,以及深度学习中的输入归一化与数据增强(如随机亮度、对比度扰动),都在一定程度上帮助模型克服光照变化的影响。

尺度变化 (Scale Variation)

物体在图像中的大小(所占像素多少)会随着其与相机距离的远近而剧烈变化。一个远处的汽车可能只占几十个像素,而近处的汽车则可能占据图像的大部分区域。

形态变化 (Deformation)

许多物体并非刚性,其形状可以发生改变。例如,同一个人可以做出站立、坐下、奔跑等不同姿势;一只猫可以蜷缩、伸展。物体的非刚性形变使得其像素级的表象极不稳定。

背景混淆与干扰 (Background Clutter)

物体很少孤立地出现在纯色背景中。复杂的背景(如森林中的动物、街景中的行人)包含大量与目标物体无关的纹理和边缘,极易对识别算法造成干扰。

遮挡 (Occlusion)

目标物体可能被其他物体部分遮挡,导致只能看到其一部分。遮挡比背景干扰更棘手,因为被遮挡部分的外观信息直接缺失。

类内物体的外观差异 (Intra-class Variation)

同一类别的物体,在外观上可能千差万别。例如,“椅子”这类物体,有办公椅、扶手椅、吧台椅、沙发椅等多种形态、颜色和材质。计算机需要学习到这些差异巨大的实例背后共有的、定义“椅子”的本质特征,同时忽略无关的细节变化。

这些挑战相互交织,使得计算机视觉成为一个极其复杂的领域。传统方法通过精心设计不变性特征 (Invariant Features) 和复杂的机器学习模型(如支持向量机 SVM 与可变形部件模型 DPM)来应对,但效果往往有瓶颈。深度学习的强大之处在于,它通过多层非线性变换,能够从海量数据中自动学习到对上述变化具有鲁棒性的高层特征表示,从而在诸多任务上取得了革命性的进步。然而,理解这些根本挑战,对于我们设计、选择和评估深度学习模型依然至关重要。

📝 动手练一练

  1. 概念辨析:假设你正在设计一个用于手机相册的“猫猫识别”功能。请分析在用户实际拍摄的照片中,以上七种挑战(视角、光照、尺度、形态、背景混淆、遮挡、类内差异)可能分别以何种具体形式出现?(例如:“尺度变化”体现在用户可能拍摄远处的猫或给猫拍特写。)
👉 点击查看参考答案

可能的分析如下:

  • 视角变化:猫可能正面朝向镜头、背对镜头、侧躺、或从俯视角度拍摄。
  • 光照变化:可能在室内昏暗灯光下、阳光直射的窗台、或夜晚开闪光灯拍摄,导致猫的毛色在照片中亮度、对比度差异巨大。
  • 尺度变化:照片可能是包含整个猫身的全景,也可能只是猫脸的大特写。
  • 形态变化:猫的姿态千变万化,如蜷缩成球、伸懒腰、跳跃、坐着等。
  • 背景混淆:猫可能藏在花纹复杂的沙发里,背景纹理与猫毛相近。
  • 遮挡:猫身体的一部分被茶几、窗帘或其他物体挡住。
  • 类内差异:需要识别不同品种(如英短、布偶、狸花猫)、不同毛色、不同年龄的猫,它们外观差异很大。
  1. 代码思考:回顾“光照变化”小节中的代码示例。如果我们想简单模拟一个算法“忽略”光照影响,尝试将三张不同光照的图片归一化到相近的亮度范围。请使用numpy编写代码,将high_light、normal_light、low_light三个矩阵,通过线性变换,使其平均值都接近128。
👉 点击查看参考答案
import numpy as np

high_light = np.full((3, 3), 250, dtype=np.float32) # 转为float以便计算
normal_light = np.full((3, 3), 150, dtype=np.float32)
low_light = np.full((3, 3), 50, dtype=np.float32)

def normalize_to_mean(arr, target_mean=128):
    """将数组线性变换到目标均值(简单模拟光照归一化)"""
    current_mean = np.mean(arr)
    # 避免除以零
    if current_mean != 0:
        scale = target_mean / current_mean
        normalized = arr * scale
        # 确保值在0-255范围内并取整
        normalized = np.clip(normalized, 0, 255).astype(np.uint8)
        return normalized
    else:
        return arr.astype(np.uint8)

print("归一化后的矩阵(目标均值128):")
print("原高光矩阵 ->", normalize_to_mean(high_light))
print("原正常矩阵 ->", normalize_to_mean(normal_light))
print("原弱光矩阵 ->", normalize_to_mean(low_light))
归一化后的矩阵(目标均值128):
原高光矩阵 -> [[128 128 128]
 [128 128 128]
 [128 128 128]]
原正常矩阵 -> [[128 128 128]
 [128 128 128]
 [128 128 128]]
原弱光矩阵 -> [[128 128 128]
 [128 128 128]
 [128 128 128]]

说明:这是一个极度简化的演示。真实的光照归一化(如直方图规定化或深度学习中的实例归一化)要复杂得多,需要考虑整个图像的统计分布或特征图的通道信息。此代码仅展示通过调整全局亮度来减少光照差异的基本思想。

本章小结

本节我们深入剖析了计算机视觉的核心困境与经典挑战。关键在于理解:

  1. 鸿沟所在:计算机视觉的核心任务是弥合底层像素数据与高层语义理解之间的巨大差距。
  2. 挑战根源:七大挑战(视角、光照、尺度、形态、背景混淆、遮挡、类内差异)源于物理世界到数字图像的映射损失以及现实世界本身的多样性。
  3. 驱动力量:这些挑战正是推动计算机视觉技术从传统特征工程向深度学习发展的根本原因,因为深度学习模型具备从数据中自动学习鲁棒特征表示的潜力。

📋 行动清单

  • 理解鸿沟:在脑海中清晰构建“像素矩阵 ↔ 语义”的认知模型,明确我们所有后续技术都在为跨越此鸿沟服务。
  • 识别挑战:尝试在日常生活看到的图片中,主动识别出本节提到的七种挑战的具体表现。
  • 关联思考:在后续学习每一个具体模型(如SIFT、CNN、YOLO)时,思考它是如何设计来应对本节所讲的一个或多个挑战的。

—— 小象教研组