图像特征提取基础:颜色直方图、边缘检测与Harris角点实战指南

📅 发布时间:2026/9/4 12:17:04
图像特征提取基础:颜色直方图、边缘检测与Harris角点实战指南
图像特征的提取就像给图片做一次“体检报表”颜色分布是否偏暖、轮廓有没有明显的角点、区域内的纹理是粗糙还是细腻。计算机视觉的任务无论多复杂最终都要建立在可靠的数值化描述之上。这篇文章就是《从零开始学CV系列课程》中图像特征方向的上篇重点聊手工设计的“基础特征”包括颜色特征、颜色直方图、边缘梯度特征、Harris 角点以及它们各自适合什么场景。适合刚入手 OpenCV、准备搞图像分类/目标检测/图像检索又想先把底层原理打扎实的读者。1. 图像特征从像素到数值描述1.1 为什么不能直接使用原始像素一张 128×128 的彩色图片在 RGB 三通道下就有 128×128×3 49152 个数值。如果直接把这 4 万多个值喂给下游算法计算量是一回事更关键的是这些原始像素中包含了大量冗余信息例如光照变化、拍摄噪声和背景干扰。图像特征提取的目标就是从原始像素中提炼出具有代表性、稳定性和区分度的数值描述也叫特征向量或特征描述子。想象一个场景我们要判断两张图片是不是同一个物体。如果直接用像素逐一对比一旦物体移动、旋转或者发生尺度变化像素坐标就完全对不上了。但如果我们提取的是目标区域的边缘方向直方图、颜色主色调、角点位置等特征那么即使物体在画面里的位置变了这些统计层面的特征依然保持一致。所以在传统图像处理时代人们把绝大部分精力都花在设计特征上希望特征本身能覆盖旋转、缩放、光照变化等干扰因素。1.2 基础特征与高级特征的边界“基础特征”和“高级特征”没有严格的统一定义但在视觉工程中我们通常这样切分层级典型代表特点底层基础特征颜色均值、颜色直方图、边缘、角点、梯度幅值计算简单、速度快、解释性强直接反映局部或全局的像素统计结构中层结构特征HOG方向梯度直方图、纹理特征、LBP、形状上下文在局部区域上做统计编码对光照和几何变形比像素更鲁棒高级语义特征SIFT、SURF、ORB以及深度学习提取的 CNN 特征尺度不变、旋转不变能描述关键点邻域的独特结构本文作为上篇先把“颜色—边缘—角点”这三类基础特征讲透。因为它们不仅本身有用还是理解 HOG、SIFT、ORB 等进阶特征的基石。例如 HOG 就是在边缘梯度基础上做分块统计SIFT 也依赖图像金字塔和高斯差分后提取的关键点。1.3 一套完整特征提取流程通常是什么样无论我们在做图像检索、简单分类还是目标检测手工特征提取阶段几乎都遵循同一个套路图像预处理缩放、去噪、颜色空间转换、归一化。特征计算在预处理后的图像上计算颜色直方图、边缘幅值方向、角点响应等。特征组织将多维特征写成一维特征向量或生成结构化特征图。特征归一化/降维消除不同维度之间的量纲差异必要时用 PCA 等降维。交给后续模型或匹配算法分类器、聚类、相似度检索。下面整个文章会按照这个思路用 Python OpenCV 完整跑通其中的第 1~3 步。2. 环境准备与版本说明本文涉及代码实验建议准备好 Python 环境。开发环境按常规配置即可不要求最新版本操作系统Windows 10/11、macOS 或 Linux 均可。Python3.8 及以上推荐 3.10 左右。图像库OpenCV习惯写作cv24.x 版本即可。数值计算库NumPy。可视化库Matplotlib用于绘制直方图和展示处理结果。安装命令比较直接pip install opencv-python numpy matplotlib如果你的电脑上安装过版本比较旧的 OpenCV建议先看一下版本号import cv2 print(cv2.__version__)OpenCV 3 和 OpenCV 4 在接口上有少量差异尤其是部分算法模块从cv2.xfeatures2d移到了独立包里。不过本文主要使用的基础函数都有几十年沉淀版本兼容性较好。只要输出在 4.x都可以正常运行本文示例。为了不依赖外部图片实验部分我会用 NumPy 手动构造一张包含矩形、圆形和线段的合成图像。这样你能直接复制代码运行不会被“找不到本地图片”挡住。真实场景中如果要读取自己文件夹里的图片请替换cv2.imread()中的路径即可。建议建立一个干净的工程目录feature-basics/ ├── images/ # 存放测试图片 ├── 01_color_features.py # 颜色特征提取脚本 ├── 02_structure_features.py # 边缘与角点特征脚本 └── output/ # 保存结果图3. 三类基础特征的原理解释3.1 颜色特征最直观的全局描述颜色特征是计算成本最低、实现最简单的一类特征也是很多图像检索系统最早使用的方案。颜色特征又可以分为两个层面第一层全局统计特征比如计算每个通道的均值、标准差、最大值、最小值。这种方式把一个 RGB 图像压缩成 9 个数字甚至更少。实战中统计特征可以快速完成粗分类。例如在交通标志识别中红色标志和蓝色标志在 RGB 均值上往往有明显差异。不过统计特征的信息太粗糙无法反映“红色集中在上半边还是下半边”。于是有了第二层。第二层颜色直方图颜色直方图统计的是图像中每种颜色出现的次数或比例。它不在意颜色像素的具体位置因此天然对旋转和平移不敏感。缺点是完全没有空间信息——一张蓝天白云的照片和一张同样颜色分布但纹理完全不同的图片在直方图上可能十分接近。为了平衡这个缺点工程上通常会把图像划分成若干子块在每个子块内单独计算直方图然后拼接起来形成空间增强的颜色特征。在颜色空间选择上RGB 并不总是最优。RGB 三个通道之间相关性很强且对光照变化非常敏感。相比而言HSV 颜色空间把色调 H、饱和度 S、亮度 V 分开更适合提取与光照弱相关的颜色特征。很多情况下只对 H、S 通道统计直方图忽略 V从而降低亮度影响。3.2 边缘特征目标结构的重要线索边缘是图像中亮度发生剧烈变化的位置是物体轮廓的主要来源。宏观上目标的边界往往伴随着灰度突变。我们只要找到这种突变就能画出目标轮廓。突变程度的数学描述称为梯度。对灰度图I(x, y)来说在水平方向的梯度定义为Gx I(x1, y) - I(x-1, y)垂直方向类似Gy I(x, y1) - I(x, y-1)梯度幅值表示变化强度梯度方向表示变化朝向。Sobel 算子就是用固定卷积核模拟这种差分运算。Canny 边缘检测则是在梯度基础上继续做非极大值抑制和双阈值连接最后输出完整的二值轮廓图。边缘特征有一个突出优势相比颜色特征它对光照变化更稳健。因为同一物体的边缘由物理结构决定光照变亮或变暗不会让边缘消失。因此边缘常被用于目标轮廓提取、形状匹配、车道线检测等任务。但也要注意边缘容易受到噪声和复杂纹理干扰。过度提取的边缘图会让后续算法失去重点所以往往还需要先做高斯模糊降噪再进行边缘计算。3.3 角点特征图像中的特征点角点可以理解为图像中两边相交、灰度变化同时出现在多个方向上的像素点。为什么角点很重要因为无论是图像拼接、相机标定还是物体识别我们都希望找到一些“容易定位的锚点”。平坦区域内任何像素看起来都一样无法唯一匹配边缘上的点虽然能确定在边缘线上的位置但沿边缘方向滑动时又无法区分。而角点同时在两个方向上有明显灰度变化具有较高的唯一性。Harris 角点检测是经典算法之一。核心思路是在一个小窗口内平移图像如果任意方向移动都会引起窗口内灰度的大幅变化就认为中心点是角点。Harris 通过构造结构张量矩阵计算两个特征值再得到角点响应值 R用阈值筛选角点区域。Harris 角点不具备尺度不变性但对旋转具有一定鲁棒性。后续 SIFT、ORB 等特征点算法也都是在“找关键点”的概念上进一步加入尺度空间和描述子。4. 完整实战用 OpenCV 提取图像基础特征这一节开始进入实操。我会用一个手动生成的合成图演示颜色特征、边缘特征、角点特征的提取全过程。4.1 构造测试图像并做基本预处理新建脚本utils.py用来生成测试图像和展示图像# utils.py import cv2 import numpy as np import matplotlib.pyplot as plt def create_sample_image(): 构造一个包含矩形、圆形、线段的合成图便于观察特征提取结果。 img np.zeros((300, 400, 3), dtypenp.uint8) # 背景设为浅灰色注意 OpenCV 默认通道顺序是 BGR img[:] (200, 200, 200) # 画一个红色矩形 cv2.rectangle(img, (30, 30), (150, 220), (0, 0, 255), thickness-1) # 画一个绿色圆形 cv2.circle(img, (280, 110), 60, (0, 180, 0), thickness-1) # 画一条蓝色斜线 cv2.line(img, (200, 260), (380, 40), (255, 0, 0), thickness6) return img def to_rgb(img_bgr): OpenCV 默认是 BGR 顺序转为 RGB 方便 Matplotlib 显示。 return cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB) def show_images(titles, images, save_nameNone): 批量显示图像。 n len(images) plt.figure(figsize(4 * n, 5)) for i in range(n): plt.subplot(1, n, i 1) # 检测一下是否需要转 RGB if images[i].ndim 3: disp_img to_rgb(images[i]) else: disp_img images[i] plt.imshow(disp_img, cmapgray) plt.title(titles[i]) plt.axis(off) if save_name: plt.savefig(save_name, dpi100, bbox_inchestight) plt.show()这里show_images会自动处理灰度图和彩色图的显示通道问题。新建测试入口# run_basic.py import cv2 from utils import create_sample_image # 生成测试图并保存到本地 img create_sample_image() cv2.imwrite(output/sample.png, img) # 查看图像尺寸与通道数 print(图像尺寸:, img.shape) print(数据类型:, img.dtype)运行后会输出类似图像尺寸: (300, 400, 3) 数据类型: uint8这里可以解释一下shape返回三个值分别是高度、宽度、通道数。彩色图通常是 3 通道灰度图是单通道个别带透明通道的 PNG 则是 4 通道。理解通道顺序对后续编写特征提取代码非常重要。4.2 颜色特征提取通道统计与颜色直方图编写01_color_features.py主要包含以下 4 个工作读取图片并转换到 HSV 颜色空间。计算 RGB、HSV 各通道的均值、标准差。计算 BGR 三个通道的颜色直方图。对直方图做归一化便于后续比较。完整示例代码如下# 01_color_features.py import cv2 import numpy as np import matplotlib.pyplot as plt from utils import create_sample_image, to_rgb def channel_stats(image, color_spaceBGR): 计算各通道的均值与标准差返回特征字典。 stats {} channel_names [] if color_space BGR: channels cv2.split(image) channel_names [B, G, R] elif color_space HSV: hsv cv2.cvtColor(image, cv2.COLOR_BGR2HSV) channels cv2.split(hsv) channel_names [H, S, V] else: raise ValueError(仅支持 BGR 或 HSV) for ch, name in zip(channels, channel_names): stats[f{name}_mean] float(ch.mean()) stats[f{name}_std] float(ch.std()) return stats def calc_color_histogram(image): 分别计算 BGR 三个通道的颜色直方图。 hist_b cv2.calcHist([image], [0], None, [256], [0, 256]) hist_g cv2.calcHist([image], [1], None, [256], [0, 256]) hist_r cv2.calcHist([image], [2], None, [256], [0, 256]) return hist_b, hist_g, hist_r if __name__ __main__: img create_sample_image() # 1. 通道统计特征 bgr_stats channel_stats(img, BGR) hsv_stats channel_stats(img, HSV) print(BGR 通道统计:, bgr_stats) print(HSV 通道统计:, hsv_stats) # 2. 计算颜色直方图 hist_b, hist_g, hist_r calc_color_histogram(img) # 3. 绘制直方图并保存 plt.figure(figsize(8, 4)) plt.plot(hist_b, colorblue, labelBlue) plt.plot(hist_g, colorgreen, labelGreen) plt.plot(hist_r, colorred, labelRed) plt.title(BGR Color Histogram) plt.xlabel(Pixel Value) plt.ylabel(Pixel Count) plt.legend() plt.savefig(output/color_histogram.png, dpi100) plt.show()运行结果分析BGR 通道统计: {B_mean: 187.37..., G_mean: 157.71..., R_mean: 111.15..., B_std: ..., ...} HSV 通道统计: {H_mean: ..., S_mean: ..., V_mean: ...}在合成图中浅灰色背景的比重很大因此 B 通道均值会比较接近 200G、R 通道均值也集中在中高段。矩形和圆形区域贡献了低亮度、高饱和度的局部像素所以整体标准差也不会太小。这里需要注意cv2.calcHist的参数cv2.calcHist(images, channels, mask, histSize, ranges)第一个参数必须传列表即使只有一张图也要写成[image]。channels[0]表示第一个通道如果是灰度图则只能传[0]。histSize[256]表示分 256 个 bin。ranges[0, 256]表示像素值范围。颜色直方图通常还需要做归一化因为不同图片尺寸不同直接比较像素频率会受图像大小影响。OpenCV 提供了cv2.normalize()hist_b_norm cv2.normalize(hist_b, hist_b, 0, 1, cv2.NORM_MINMAX)归一化后每个 bin 的值落在 0~1 之间比较不同尺寸图片时才公平。4.3 边缘特征提取Sobel 与 Canny边缘特征通常是在灰度图上进行计算。编写02_structural_features.py文件内容如下# 02_structural_features.py import cv2 import numpy as np import matplotlib.pyplot as plt from utils import create_sample_image, show_images def gray_conversion(img): gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) return gray def sobel_edge(gray): # 直接使用 CV_64F避免负梯度被截断 sobel_x cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize3) sobel_y cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize3) # 计算梯度幅值 magnitude cv2.magnitude(sobel_x, sobel_y) # 转为 0~255 的灰度图方便保存与展示 magnitude cv2.normalize(magnitude, None, 0, 255, cv2.NORM_MINMAX) return np.uint8(magnitude) def canny_edge(gray, low50, high150): # Canny 接收的是单通道 8 位灰度图 edges cv2.Canny(gray, low, high) return edges if __name__ __main__: img create_sample_image() gray gray_conversion(img) sobel_result sobel_edge(gray) canny_result canny_edge(gray) show_images( [Original, Sobel Magnitude, Canny Edges], [img, sobel_result, canny_result] ) cv2.imwrite(output/sobel.png, sobel_result) cv2.imwrite(output/canny.png, canny_result)关键点讲解为什么 Sobel 要指定cv2.CV_64F因为 Sobel 卷积时图像可能出现负梯度。如果直接用cv2.CV_8U负数会被截断为 0导致方向信息丢失。工程上通常用浮点数类型计算之后再做归一化和类型转换。Canny 的双阈值是什么意思low50、high150是双阈值。梯度幅值大于高阈值的像素一定属于边缘小于低阈值的像素不是边缘处于两者之间的像素只有与强边缘连通时才被保留。这样能够抑制孤立的噪声点。Canny 的输入要求Canny 要求输入必须是单通道 8 位灰度图也就是CV_8UC1。如果直接传彩色图会得到如下报错error: (-215:Assertion failed) image.type() CV_8UC1 in function cv::Canny这类错误在第一接触 Canny 或 HoughLinesP 算法的朋友中很常见。后面“常见问题”部分还会专门扩展。4.4 Harris 角点检测Harris 角点检测同样基于灰度图不同之处在于算法内部需要计算图像的局部梯度矩阵因此通常建议将灰度图转成float32类型。示例代码如下# 03_harris_corner.py import cv2 import numpy as np from utils import create_sample_image img create_sample_image() gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray np.float32(gray) # 调用 Harris 角点检测 dst cv2.cornerHarris(gray, blockSize2, ksize3, k0.04) # 膨胀便于标记 dst cv2.dilate(dst, None) # 角点响应值超过最大值一定比例的位置视为角点 threshold 0.01 * dst.max() corner_img img.copy() corner_img[dst threshold] [0, 0, 255] cv2.imwrite(output/harris_corner.png, corner_img) print(Harris 响应图大小:, dst.shape) print(检测到的大致角点像素数:, int((dst threshold).sum()))这里参数的含义blockSize2表示计算每个像素邻域大小为 2×2。邻域小定位更精细但对噪声更敏感。ksize3表示 Sobel 算子窗口大小用于计算梯度。k0.04是 Harris 响应函数中的经验系数常见范围是 0.04~0.06。dst是角点响应矩阵数值越大越可能是角点。dst.max()是寻找整幅图中最大响应值。绝对阈值不容易设置所以常使用相对比例比如 0.01 倍最大值。因为合成图的背景是平坦的而矩形、圆形、线段都有清晰的角点所以运行后可以预期得到若干分布合理的红色标记点。如果阈值设得太低平坦区域会被误判成角点设得太高原来偏圆的角点可能丢失。实际项目中需要按分辨率调整比例系数。4.5 把特征向量组织起来基础特征最终要作为输入送给模型因此要写一个把上述特征串联成“一维特征向量”的函数这一步常被初学者忽略。下面是一个简单的封装示例# feature_builder.py import cv2 import numpy as np def extract_all_features(image, bins32): 综合提取多种基础特征返回一个一维特征向量。 features [] # 1. 全局 BGR 均值与标准差 for ch in cv2.split(image): features.append(ch.mean()) features.append(ch.std()) # 2. 灰度图上的统计 gray cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) features.append(gray.mean()) features.append(gray.std()) # 3. Canny 边缘密度特征边缘像素占整张图的比例 edges cv2.Canny(gray, 80, 180) edge_density float((edges 0).sum()) / edges.size features.append(edge_density) # 4. HSV 颜色直方图的降维版本 hsv cv2.cvtColor(image, cv2.COLOR_BGR2HSV) hist_h cv2.calcHist([hsv], [0], None, [bins], [0, 180]) hist_h cv2.normalize(hist_h, hist_h).flatten() features.extend(hist_h.tolist()) return np.array(features, dtypenp.float32) if __name__ __main__: from utils import create_sample_image sample create_sample_image() feat extract_all_features(sample) print(特征向量维度:, feat.shape) print(特征向量前 10 个分量:, feat[:10])这种向量适合输入到逻辑回归、SVM、随机森林等传统机器学习模型。特征向量中有些分量是 0~255 量级有些是 0~1 的小数直接喂给模型容易被数值大的维度主导。实际使用时应做标准化或归一化处理。5. 高频问题与排查思路问题现象常见原因解决思路cv2.imread()读出的图片是None程序崩溃图片路径错误或中文路径导致 OpenCV 无法读取改用绝对路径中文路径可用cv2.imdecode()读取error: (-215:Assertion failed) image.type() CV_8UC1 in function cv::CannyCanny 输入不是单通道 8 位灰度图用cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)转灰度Canny 只接收CV_8UC1error: (-215:Assertion failed) image.type() CV_8UC1 in function cv::HoughLinesPHoughLinesP 输入不是单通道 8 位边缘图先转灰度再用 Canny 或 threshold 生成二值边缘图再传入 HoughLinesPcalcHist报参数格式错误参数没有加列表写成cv2.calcHist(img, 0, ...)正确写法cv2.calcHist([img], [0], None, [256], [0, 256])Harris 检测出的角点大量集中在某块区域阈值设得过高或过低也可能是模糊或采样问题使用相对最大值比例调整必要时先做高斯模糊或增大 blockSize颜色直方图受光照影响明显直接使用 RGB 直方图光照变化导致整体偏移换成 HSV/HSL 颜色空间只提取 H/S 通道或先做光照归一化Matplotlib 显示 OpenCV 图像颜色偏蓝偏红OpenCV 使用 BGRMatplotlib 默认使用 RGB显示前调用cv2.cvtColor(img, cv2.COLOR_BGR2RGB)单独讲一下 HoughLinesP 的报错。它本质和 Canny 一样都是受限输入类型需要 8 位单通道二值图像。很多初学者在边缘检测后直接拿原始灰度图或彩色图去做线段检测就会遇到error: (-215:Assertion failed) image.type() CV_8UC1 in function cv::HoughLinesP正确流程应当是gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) edges cv2.Canny(gray, 50, 150) lines cv2.HoughLinesP(edges, 1, np.pi / 180, threshold50)edge是 Canny 输出的二值图类型是CV_8UC1传入 HoughLinesP 就不会报错。这个错误提醒我们一条通用开发原则调用 API 前先检查输入数组的类型、维度和通道数而不是只关注算法参数。6. 工程实践中的关键建议基础特征提取看似简单但实际项目中决定效果的不是某个高大上的算法而是工程细节。以下是过去项目中总结出的几条建议对刚接触 CV 的开发者来说有直接帮助。第一颜色空间选择要有依据。做图像检索或粗分类时HSI/HSV 往往比 RGB 更符合人对颜色的感知。对 H 通道直方图做检索时一定要结合饱和度 S 做筛选否则低饱和度的灰色区域会被误认为色彩相近的颜色干扰匹配结果。第二直方图比较时使用合适的度量方法。OpenCV 提供了多种直方图比较方式例如相关度、卡方、巴氏距离。卡方和巴氏距离适合比较概率分布型直方图相关度对整体亮度的线性变化更稳健因为它们计算的是向量之间的方向相似性。建议两种都尝试一下不要一上来就固定在cv2.compareHist()的某一种方法上。第三边缘检测之前先降噪。边缘检测对噪声敏感。在高噪声图像上直接 Canny会得到大量碎片轮廓。普遍做法是先高斯模糊再跑 Cannyblurred cv2.GaussianBlur(gray, (5, 5), 1.2) edges cv2.Canny(blurred, 100, 200)注意高斯核的尺寸要结合图像分辨率缩放。对 4K 图像使用 3×3 核往往没有明显效果可以适当加大到 7×7。第四特征设计要考虑“区分度”和“鲁棒性”的平衡。颜色特征鲁棒性好但对同类不同颜色的物体区分度很差边缘特征对结构区分好但在遮挡、背景复杂的情况下容易失效Harris 角点能找到稳定可重复的关键点但本身不携带描述子需要配合后续局部特征算法一起使用。项目选型时应先用可视化结果对照需求而不是只盯着某个数值指标。第五给数据做好归一化。无论是输入到传统机器学习模型还是做特征匹配不同量纲的特征混在一起会影响距离计算。一个最常用的标准化方法是用sklearn.preprocessing.StandardScaler或者简单地对每个维度做 min-max 归一化。OpenCV 中也内置了cv2.normalize()函数适合处理单张图像的特征图。第六控制代码的输入输出格式。这一步在团队协作中非常容易被忽略。例如你在算法内部默认输入是 RGB而下游同学来了一张 BGR 图最后结果就会全错。建议在核心特征提取函数里明确标注输入图片的颜色空间、通道顺序、数据类型并做断言检查assert image.ndim 3, 输入应为三通道图像 assert image.dtype np.uint8, 输入图像应为 uint8 类型越早暴露类型问题调试成本越低。7. 后续从基础特征到高级特征在“图像特征提取上”篇中我们完成了传统视觉的第一段旅程把颜色、边缘、角点变成可计算的数字。但真正用于图像配准、物体识别和图像拼接的场景里单纯的全局颜色直方图还不够。下一部分通常研究这些方向把边缘梯度统计成块特征形成 HOG 方向梯度直方图用于行人检测。引入尺度空间设计出 SIFT 特征让关键点不再惧怕图像缩放。用 ORB 这类快速局部特征替代 SIFT满足实时性和移动端部署需求。用灰度共生矩阵GLCM、LBP 等方案量化纹理特征服务表面缺陷检测与医学图像分析。这几个方向都属于“图像特征提取下”中可以展开的内容。强烈建议先把本文的颜色直方图、Canny 边缘、Harris 角点完整跑一遍并拿着自己拍的照片尝试修改阈值、调整颜色空间观察特征结果的变化。这个过程能帮助你形成对“特征”的直观经验。如果之后打算系统学习计算机视觉可以把本文内容作为后续阅读 SIFT 源码、目标检测文章中“传统特征”部分的基石。建议写代码时建立一个自己的通用feature_utils.py后续系列文章都会在同一个工具包基础上扩展。这套基础特征的手工设计思路和后来深度卷积网络学习到的特征是相辅相成的。先理解了颜色、边缘、角点这些底层概念再去理解卷积神经网络第一层学到的边缘滤波器、纹理响应会发现很多知识是相通的。现在就可以打开 OpenCV把上面三个脚本执行一遍看看你的图片会输出什么样的特征。