news 2026/6/7 13:16:37

OpenCV直方图比较:四种方法原理与实战应用详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpenCV直方图比较:四种方法原理与实战应用详解

1. 直方图比较:从“像不像”到“有多像”的量化之旅

在图像处理的世界里,我们经常需要回答一个看似简单却至关重要的问题:这两张图片“像不像”?对于人眼来说,判断两张风景照是否相似,或者两张产品图是否有色差,可能只是一瞬间的直觉。但要让计算机理解这种“相似性”,并将其转化为一个可量化、可比较的数值,就需要一套严谨的数学方法。这就是直方图比较(Histogram Comparison)的核心价值所在。它绕开了图像中像素的具体空间排列,转而从全局的统计分布特征入手,为我们提供了一种高效、稳健的相似性度量手段。无论是用于图像检索、内容过滤、质量控制,还是更复杂的计算机视觉流水线,掌握直方图比较都像是获得了一把打开图像内容分析大门的钥匙。今天,我们就深入OpenCV的cvCompareHist()函数,拆解其背后的四种统计学方法,并通过实际代码和场景分析,让你不仅会用,更懂其所以然。

2. 核心思路解析:为什么是直方图?又为何要比较?

在深入公式和代码之前,我们得先想明白两个根本问题:第一,为什么选择直方图作为比较的基础?第二,比较直方图的“相似度”,究竟在比较什么?

2.1 直方图作为“图像指纹”的优势

直方图是图像像素强度分布的统计图表。对于灰度图,它统计了每个灰度级(0-255)出现的次数;对于彩色图,可以分别统计R、G、B通道的分布,或转换到HSV等其他色彩空间后再统计。它的核心优势在于:

  1. 对几何变换不敏感:图像的旋转、平移、小幅度的缩放,不会显著改变其颜色或灰度的整体分布。一张正放和斜放的红色苹果图片,其红色通道的直方图依然高度相似。
  2. 计算效率高:计算一张图像的直方图复杂度是O(N),N为像素数,且OpenCV有高度优化的实现。比较两个直方图向量的计算量也远小于逐像素比对。
  3. 表征全局特征:它丢弃了所有的空间信息,这既是缺点也是优点。作为“全局描述子”,它能快速捕捉图像的整体色调、对比度和亮度风格。

注意:直方图的“不敏感”特性是一把双刃剑。两幅内容截然不同但颜色分布巧合相似的图像(比如一片蓝天和一块蓝布),其直方图可能非常接近。因此,直方图比较通常用于粗筛或需要颜色/纹理分布匹配的场景,而非精确的内容识别。

2.2 相似度度量的本质:距离与相关性

比较两个直方图,本质上是比较两个概率分布向量。假设我们已经将直方图进行了归一化(即所有bin的值之和为1),那么每个直方图都可以看作一个离散的概率分布。比较两个分布P和Q的相似性,统计学和数学中提供了多种度量方式,主要分为两大类:

  1. 距离度量:衡量两个分布之间的“差异”或“不相似性”。数值越大,表示差异越大,相似度越低。例如卡方距离、巴氏距离。
  2. 相关性度量:衡量两个分布之间的“关联程度”。数值越大(通常接近1),表示关联性越强,相似度越高。例如相关系数。

OpenCV的cvCompareHist()函数集成了四种经典方法,涵盖了这两种思路。理解它们各自的物理意义和适用场景,是正确使用的关键。

3. 四种比较方法深度剖析与实操要点

OpenCV定义了四种比较方法,对应不同的数学公式和解释。我们将逐一拆解,并附上关键的操作注意事项。

3.1 相关系数 (CV_COMP_CORREL)

这是最符合直觉的“相关性”比较方法之一,其公式源于统计学中的皮尔逊相关系数。

公式与解读:对于两个归一化的直方图H1和H2,每个都有N个bin,相关系数d的计算公式为:d = Σᵢ [ (H1(i) - H̄1) * (H2(i) - H̄2) ] / sqrt( Σᵢ (H1(i) - H̄1)² * Σᵢ (H2(i) - H̄2)² )其中,H̄1和H̄2分别是H1和H2的均值。

结果范围与意义:

  • 结果范围:[-1, 1]
  • 1:表示两个直方图分布完全正相关。在归一化后,完全相同的直方图其相关系数为1。
  • -1:表示完全负相关(一个直方图高的地方另一个必然低)。
  • 0:表示无线性相关性。

实操要点与坑点:

  • 对整体亮度/对比度线性变化鲁棒:如果图像整体变亮或变暗(线性拉伸),直方图形状会平移或缩放,但相关系数可能变化不大,因为它衡量的是“变化趋势”的相似性。
  • 理解示例中的“反直觉”结果:在提供的示例中,纯黑(Black.jpg)和纯白(White.jpg)图片的相关系数输出为1。这看似奇怪,实则正确。因为黑图的直方图全部集中在0灰度级,白图全部集中在255灰度级。在计算时,归一化后,它们都是“只有一个bin为1,其余为0”的分布。这种分布形态(一个尖峰)是“相似”的,尽管位置不同。相关系数捕捉了这种“单峰集中”分布形态的相似性,而非峰值位置。
  • 适用场景:适用于寻找颜色分布“模式”相似的图像,对光照的均匀变化有一定抵抗力。

3.2 卡方检验 (CV_COMP_CHISQR)

卡方检验源于统计学,用于检验观察频数与期望频数之间的差异。在直方图比较中,我们将一个直方图视为“观察值”,另一个视为“期望值”。

公式与解读:d = Σᵢ [ (H1(i) - H2(i))² / H2(i) ]这是OpenCV使用的简化公式(假设H2(i)非零)。更对称的版本有时会使用(H1(i)-H2(i))²/(H1(i)+H2(i))

结果范围与意义:

  • 结果范围:[0, +∞)
  • 0:表示两个直方图完全一致。
  • 值越大:表示差异越大。

实操要点与坑点:

  • 分母的重要性:公式中除以H2(i)意味着,在H2(i)(期望值)很小的bin上,即使H1(i)的绝对差异不大,也会产生很大的贡献值。这使得卡方检验对直方图中低频区域(颜色出现少的区域)的差异非常敏感。
  • 非对称性:原始的卡方公式d(H1, H2)d(H2, H1)结果可能不同,因为它将第二个参数视为期望分布。OpenCV的实现可能采用对称化处理或固定顺序,使用时需注意。
  • 处理零值:当H2(i)为0时,公式分母为零,需要特殊处理(如加一个极小值epsilon)。OpenCV的内部实现应已处理此边界情况。
  • 适用场景:适用于对颜色分布中“稀有颜色”差异非常敏感的比较,例如在特定色调的检测中。

3.3 交集法 (CV_COMP_INTERSECT)

交集法是最简单直观的方法,它计算两个直方图在每个bin上的重合部分。

公式与解读:d = Σᵢ min(H1(i), H2(i))由于直方图已归一化,这个d的值域在[0, 1]之间。

结果范围与意义:

  • 1:表示两个直方图完全一致。
  • 0:表示两个直方图完全没有重叠(例如黑与白)。
  • 值表示重叠部分的总“质量”。

实操要点与坑点:

  • 计算简单快速:只有比较和加法,计算开销小。
  • 对峰值敏感,对分布形状不敏感:它只关心每个bin上共同的部分。如果两个直方图都有很高的峰值,即使峰值位置不同,只要在某个bin上有重叠,就能贡献值。例如,一个峰值在100,一个在150,但两者在灰度级120-130都有一些像素,交集法就会捕捉到这部分相似性,而相关系数可能很低。
  • 示例分析:在黑与白的例子中,交集为0,完美符合预期。
  • 适用场景:适用于快速粗略匹配,或对直方图峰值匹配要求较高的场景。在简单的颜色检索中效果不错。

3.4 巴氏距离 (CV_COMP_BHATTACHARYYA)

巴氏距离(Bhattacharyya distance)用于衡量两个概率分布之间的重叠程度,在统计学和模式识别中广泛应用。OpenCV实际计算的是巴氏系数(Bhattacharyya coefficient)后再转换为距离。

公式与解读:巴氏系数:BC(H1, H2) = Σᵢ sqrt(H1(i) * H2(i))巴氏距离:d = sqrt( 1 - BC(H1, H2) )

结果范围与意义:

  • 结果范围:[0, 1]
  • 0:表示两个分布完全一致(BC=1)。
  • 1:表示两个分布完全无重叠(BC=0)。

实操要点与坑点:

  • 几何解释:可以将每个归一化直方图看作一个高维空间中的向量,巴氏系数就是这两个向量各分量几何平均(平方根乘积)的和。它衡量的是两个向量的“夹角”或“重叠度”。
  • 对称且平滑:它是对称的,且由于平方根操作,对直方图的变化不那么尖锐,比卡方更平滑。
  • 与交集法的关系:巴氏系数类似于一种“软”交集,它不像交集法那样只取最小值,而是通过几何平均来度量所有分量上的“共同存在感”。
  • 适用场景:在目标跟踪(如Mean-Shift跟踪器中使用颜色直方图作为特征)和图像分类中非常常见,因为它能提供稳定、有界的相似性度量。

4. 完整实操流程与代码精讲

理解了原理,我们来看如何用OpenCV (C++ API) 实现。虽然原始资料使用了较旧的C API (IplImage*),但我们将以现代OpenCV C++ API (cv::Mat) 重写,这是当前的主流和推荐做法。

4.1 环境准备与基础代码结构

首先确保你的开发环境已配置好OpenCV。以下是一个完整的、可编译的示例程序框架:

#include <opencv2/opencv.hpp> #include <opencv2/imgproc.hpp> #include <iostream> int main() { // 1. 读取图像(强制转为灰度图进行比较) cv::Mat img1 = cv::imread("RiverBank.jpg", cv::IMREAD_GRAYSCALE); cv::Mat img2 = cv::imread("DarkClouds.jpg", cv::IMREAD_GRAYSCALE); if (img1.empty() || img2.empty()) { std::cerr << "Error: Could not load images!" << std::endl; return -1; } // 2. 设置直方图参数 int histSize = 256; // bin的数量 float range[] = {0, 256}; // 像素值范围 const float* histRange = {range}; bool uniform = true, accumulate = false; // 3. 计算直方图 cv::Mat hist1, hist2; cv::calcHist(&img1, 1, 0, cv::Mat(), hist1, 1, &histSize, &histRange, uniform, accumulate); cv::calcHist(&img2, 1, 0, cv::Mat(), hist2, 1, &histSize, &histRange, uniform, accumulate); // 4. 归一化直方图(通常归一化到[0,1]区间,方便比较) cv::normalize(hist1, hist1, 1.0, 0.0, cv::NORM_L1); // L1归一化,和为1 cv::normalize(hist2, hist2, 1.0, 0.0, cv::NORM_L1); // 5. 比较直方图 double correl = cv::compareHist(hist1, hist2, cv::HISTCMP_CORREL); double chisqr = cv::compareHist(hist1, hist2, cv::HISTCMP_CHISQR); double intersect = cv::compareHist(hist1, hist2, cv::HISTCMP_INTERSECT); double bhatt = cv::compareHist(hist1, hist2, cv::HISTCMP_BHATTACHARYYA); // 6. 输出结果 std::cout << "Correlation: " << correl << std::endl; std::cout << "Chi-Square: " << chisqr << std::endl; std::cout << "Intersection: " << intersect << std::endl; std::cout << "Bhattacharyya: " << bhatt << std::endl; // 7. 显示图像(可选) cv::imshow("Image 1", img1); cv::imshow("Image 2", img2); cv::waitKey(0); return 0; }

4.2 关键步骤详解与参数选择

步骤1:图像读取与预处理

  • cv::IMREAD_GRAYSCALE:直接以灰度模式读入,简化问题。对于彩色图比较,通常需要选择色彩空间(如HSV)并单独比较H(色调)通道,或计算多维度直方图。
  • 错误检查:务必检查图像是否成功加载,这是避免后续崩溃的好习惯。

步骤2:直方图参数设置

  • histSize:直方图bin的数量。256是灰度图的常用值,表示将0-255的灰度级每个都作为一个bin。对于彩色图或为了降低计算量/增加鲁棒性,可以减少到16、32或64。
  • range:像素值范围。对于标准的8位灰度图,是[0,256),注意上界是256(不包括),这是OpenCV的惯例。
  • uniform:设为true表示bin的宽度均匀。
  • accumulate:设为false表示在计算前不清空直方图矩阵。如果需要在多张图上累积直方图,则设为true

步骤3:计算直方图

  • cv::calcHist函数参数较多:
    • 第1、2个参数:输入图像数组和图像数量。
    • 第3个参数:需要统计的通道索引(对于灰度图是0)。
    • 第4个参数:可选的掩码(cv::Mat()表示无掩码)。
    • 第5个参数:输出的直方图(cv::Mat类型)。
    • 第6个参数:直方图维度(这里是1维)。
    • 第7个参数:每个维度的bin数量指针。
    • 第8个参数:每个维度的值范围指针。
    • 最后两个:均匀和累积标志。

步骤4:归一化

  • 这是至关重要的一步cv::compareHist的许多方法(尤其是相关性、交集、巴氏距离)都假设输入的是归一化的概率分布。
  • cv::NORM_L1:将直方图归一化,使其所有元素之和为1(即L1范数归一化)。1.00.0是目标范围的最小值和最大值。
  • 也可以使用cv::NORM_MINMAX归一化到[0,1]区间,但NORM_L1更符合概率分布的定义。

步骤5:比较直方图

  • cv::compareHist函数直接返回一个双精度浮点数结果。注意比较方法的枚举名称在现代OpenCV中已更新(如cv::HISTCMP_CORREL)。

4.3 扩展到彩色图像与多维直方图

灰度直方图比较是基础。在实际应用中,彩色信息至关重要。比较彩色直方图主要有两种策略:

策略一:单通道分离比较将彩色图像转换到HSV色彩空间,然后单独比较H(色调)通道的直方图。因为色调更能代表物体的颜色本质,对光照强度(V)和饱和度(S)的变化相对不敏感。

cv::Mat img_color = cv::imread("color_image.jpg"); cv::Mat img_hsv; std::vector<cv::Mat> hsv_planes; cv::cvtColor(img_color, img_hsv, cv::COLOR_BGR2HSV); cv::split(img_hsv, hsv_planes); // 分离通道 // 只计算H通道的直方图 cv::Mat hist_h; int h_bins = 180; // 色调范围是[0,180) float h_range[] = {0, 180}; const float* hranges = {h_range}; cv::calcHist(&hsv_planes[0], 1, 0, cv::Mat(), hist_h, 1, &h_bins, &hranges, true, false); cv::normalize(hist_h, hist_h, 1.0, 0.0, cv::NORM_L1); // ... 然后比较两个图像的H通道直方图

策略二:多维联合直方图计算2D(如H-S)或3D(H-S-V)直方图,能同时捕捉颜色和饱和度的联合分布信息,描述能力更强,但计算量和存储需求也呈指数增长(“维度灾难”)。

int histSize[] = {50, 60}; // H和S的bin数量,可以比单通道少 float h_ranges[] = {0, 180}; float s_ranges[] = {0, 256}; const float* ranges[] = {h_ranges, s_ranges}; int channels[] = {0, 1}; // 统计H和S通道 cv::Mat hist_2d; cv::calcHist(&img_hsv, 1, channels, cv::Mat(), hist_2d, 2, histSize, ranges, true, false); cv::normalize(hist_2d, hist_2d, 1.0, 0.0, cv::NORM_L1); // 比较时,compareHist函数同样支持多维直方图(cv::Mat)

实操心得:对于大多数应用,策略一(仅比较H通道)是性价比最高的选择。它既保留了核心的颜色信息,又大幅降低了计算复杂度,且对光照变化有较好的鲁棒性。只有在颜色区分度要求极高、且光照和饱和度变化可控的场景下,才考虑使用多维直方图,并且要谨慎选择bin的数量,避免直方图过于稀疏。

5. 实战场景分析与结果解读

让我们回到原始资料中的三个例子,结合我们现在的理解进行深度解读:

场景一:不同场景图像 (RiverBank vs DarkClouds)

  • 输出:Correl: -0.1407, ChiSqr: 0.6690, Intersect: 0.4757, Bhatt: 0.4490
  • 解读
    • Correl接近0且为负,说明两张图的灰度分布几乎没有线性相关性,甚至趋势略有相反。
    • ChiSqrBhatt值都显著大于0(相对后面自比较的情况),表明差异很大。
    • Intersect为0.4757,说明有约47.6%的灰度分布是重叠的,这比完全不同的图像要高,符合直觉(都是自然图像,包含一些中间灰度)。

场景二:相同图像自比较 (RiverBank vs RiverBank)

  • 输出:Correl: 1, ChiSqr: 0, Intersect: 1, Bhatt: 0
  • 解读:这是理想情况。相关系数和交集法为1,卡方和巴氏距离为0,完美匹配。这验证了我们的代码和归一化过程是正确的。

场景三:极端对立图像 (纯黑 vs 纯白)

  • 输出:Correl: 1, ChiSqr: 1, Intersect: 0, Bhatt: 1
  • 深度解读
    • Correl = 1:如前所述,归一化后两者都是“只有一个bin为1”的极端分布,这种“单峰冲击”的形态在相关系数看来是完全相关的。这揭示了相关系数关注分布“形状”而非“位置”的特性。
    • Intersect = 0:两者灰度级完全没有重叠,结果正确且直观。
    • ChiSqr = 1Bhatt = 1:都达到了最大值,表示完全不相似。对于卡方,因为H1(0)=1, H2(0)=0,公式中(1-0)²/0需要处理,OpenCV可能返回一个定义的最大值或特殊值(示例中简化为1)。巴氏距离因为sqrt(1*0)=0,所以距离为1。

这个例子强烈地告诉我们:没有一种度量是完美的,必须根据任务目标选择方法。如果你想区分纯黑和纯白,交集法、卡方、巴氏距离都有效,而相关系数会误判。如果你想找到具有相似对比度变化模式的图像(如都具有相似的纹理明暗变化),那么相关系数可能更合适。

6. 常见问题、陷阱与进阶技巧

在实际项目中,直接调用compareHist可能会遇到各种问题。以下是一些经验总结:

6.1 直方图稀疏性与bin数量选择

问题:当bin数量设置过多(如256)而图像尺寸较小,或图像颜色范围很窄时,直方图会变得很稀疏(很多bin是0)。这会导致:

  1. 卡方距离对零值敏感,可能产生不稳定的大数值。
  2. 巴氏距离中sqrt(0)的计算没问题,但稀疏性可能使比较失去鉴别力。
  3. 计算效率降低。

解决方案

  • 减少bin数量:将灰度级从256合并到32或64。对于彩色H通道(0-180),使用30或36个bin。这相当于对颜色进行了“量化”,能增加每个bin的统计量,使直方图更平滑、更鲁棒。
  • 平滑直方图:在归一化前,对直方图应用一个高斯滤波或简单平均滤波,可以缓解稀疏性问题。
    cv::Mat smoothed_hist; cv::GaussianBlur(hist1, smoothed_hist, cv::Size(3,1), 0.5); // 一维高斯平滑 cv::normalize(smoothed_hist, smoothed_hist, 1.0, 0.0, cv::NORM_L1);

6.2 光照变化与色彩空间选择

问题:同一物体在不同光照下,其RGB值变化巨大,导致直方图直接比较失效。

解决方案

  • 转换色彩空间:如前所述,使用HSV空间并主要依赖H(色调)通道。色调对光照强度变化相对不敏感。
  • 使用更高级的归一化:除了L1归一化,可以尝试对直方图进行幂律(伽马)压缩,如hist = cv::pow(hist, 0.5),然后再归一化。这可以抑制过强的峰值,增强弱信号的贡献。
  • 局部直方图:将图像分割成若干网格(如3x3),分别计算每个网格的直方图,然后串联起来或分别比较再综合。这在一定程度上保留了空间信息,对遮挡和局部光照变化更鲁棒。

6.3 相似度阈值如何设定?

问题compareHist返回一个数值,但多大算“相似”?这个阈值因方法、因数据集、因应用而异。

解决方案

  • 基准测试法:在自己的数据集上,手动标注一批“相似”和“不相似”的图像对。分别计算它们用不同方法得到的距离/相似度分数。
  • 统计分析:观察“相似对”和“不相似对”得分的分布。理想情况下,两个分布应尽可能分开。阈值可以设在两个分布之间的“山谷”处,或者根据误报率/漏报率的需求来调整。
  • 经验值参考(需自行验证)
    • 相关系数 (Correl):通常>0.8或0.9可以认为高度相似。
    • 交集法 (Intersect):归一化后,>0.7或0.8可认为相似。
    • 巴氏距离 (Bhatt):通常<0.3或0.2可认为相似(值越小越相似)。
    • 卡方 (ChiSqr):阈值高度依赖bin数和数据,需大量实验确定。

6.4 多方法融合与性能优化

问题:单一方法有时不靠谱,如何提升判断的准确性?

解决方案

  • 加权融合:计算多种方法的得分,然后进行加权平均。例如,最终得分 = w1*correl + w2*(1-bhatt) + w3*intersect,其中权重w1,w2,w3通过实验调整。注意要将距离度量(如Bhatt)转换为相似度度量(1-distance)。
  • 级联筛选:先用计算速度快、召回率高的方法(如交集法)进行粗筛,得到一个候选集,再用更精确但较慢的方法(如基于多维直方图的巴氏距离)进行精筛。
  • 积分直方图加速:对于需要计算图像多个区域(如滑动窗口)直方图的应用,可以使用积分直方图技术,实现O(1)时间复杂度的区域直方图计算,极大提升速度。

6.5 直方图比较的局限性认知

必须清醒认识到,直方图比较丢失了全部空间信息。这是其速度快、对几何变化鲁棒的原因,也是其致命弱点。

经典反例

  • “蓝天”和“蓝墙”可能有相似的蓝色直方图。
  • 国际象棋棋盘和它的反色棋盘(黑变白,白变黑),灰度直方图完全一样,但内容截然相反。

应对策略

  • 结合其他特征:将直方图特征与纹理特征(如LBP、Haralick特征)、边缘特征(如HOG)或局部特征(如SIFT、ORB的关键点描述子)结合,形成更强大的图像描述符。
  • 作为预过滤步骤:在复杂的图像检索或匹配系统中,先用直方图比较快速过滤掉明显不相关的图像,减少需要精细匹配的图像数量。

直方图比较是图像处理中一项基础而强大的工具。它就像一位快速的颜色风格鉴定师,能迅速告诉你两幅画用的颜料盘是否相似。但要想真正理解画作的内容,你还需要结合线条、构图等其他信息。掌握其原理、熟练其代码、明了其优劣,你就能在合适的场景中,让这位“鉴定师”发挥出最大的价值。在实际项目中,我通常会从简单的H通道直方图交集法开始快速原型验证,然后根据具体问题的难点(如光照、相似度判别模糊)逐步引入更复杂的方法或与其他特征融合,这是一个不断迭代和调优的过程。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/7 13:14:10

Intel TBB 2019 Update 8(2019年6月5日发布)Windows全功能开发包

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;包含完整头文件、预编译64位动态/静态库&#xff08;intel64&#xff09;、CMake支持脚本&#xff08;FindTBB.cmake&#xff09;、Parallel STL&#xff08;pstl&#xff09;子模块、多套可运行示例&#xff0…

作者头像 李华
网站建设 2026/6/7 13:12:12

如何高效管理Steam游戏清单:Onekey下载器完整解决方案

如何高效管理Steam游戏清单&#xff1a;Onekey下载器完整解决方案 【免费下载链接】Onekey Onekey Steam Depot Manifest Downloader 项目地址: https://gitcode.com/gh_mirrors/one/Onekey 想要轻松获取和管理Steam游戏的完整清单文件吗&#xff1f;Onekey Steam Depot…

作者头像 李华
网站建设 2026/6/7 13:03:42

如何3步完成网易云NCM音乐格式转换:解密工具全面指南

如何3步完成网易云NCM音乐格式转换&#xff1a;解密工具全面指南 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 你是否曾为网易云音乐下载的歌曲只能在特定客户端播放而烦恼&#xff1f;当你想在车载音响、手机自带播放器或其他设备…

作者头像 李华
网站建设 2026/6/7 13:00:32

C语言小工具:输入一个正整数,分行列出它的所有约数并报总数

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;输入一个正整数n&#xff0c;程序自动找出1到n之间所有能整除n的数&#xff0c;每个约数单独占一行输出&#xff0c;最后显示总共找到多少个。代码用标准C编写&#xff0c;不依赖外部库&#xff0c;直接gcc编译…

作者头像 李华