基于OpenCV的直方图特征提取:如何计算均值、方差、归一化方差与熵
基于OpenCV的直方图特征提取实现方案
你现有的直方图计算流程已经完全可以支撑特征提取需求,不需要引入复杂依赖,借助NumPy即可实现均值、方差、归一化方差、熵四类特征的落地计算,完全兼容你已有的代码逻辑。
各特征的计算实现
所有计算函数均适配cv2.calcHist()的输出格式(形状为(256,1)的二维数组),不需要额外做复杂的格式转换。
1. 直方图均值
- 核心逻辑:以每个灰度级的像素计数为权重,计算灰度值的加权平均,等价于图像全局像素的平均灰度值
- 可复用代码:
import numpy as np def calc_hist_mean(hist): hist_flat = hist.flatten() # 生成每个bin对应的灰度取值(256个bin对应0~255) bin_levels = np.arange(hist_flat.shape[0]) total_pixels = hist_flat.sum() mean = (bin_levels * hist_flat).sum() / total_pixels return mean
2. 直方图方差
- 核心逻辑:衡量直方图分布的离散程度,计算每个灰度值与均值差值的平方加权和
- 可复用代码:
def calc_hist_variance(hist, mean=None): hist_flat = hist.flatten() bin_levels = np.arange(hist_flat.shape[0]) total_pixels = hist_flat.sum() if mean is None: mean = (bin_levels * hist_flat).sum() / total_pixels variance = ((bin_levels - mean) ** 2 * hist_flat).sum() / total_pixels return variance
3. 归一化方差
- 核心逻辑:消除直方图bin数量不同带来的尺度影响,让不同分箱粒度的直方图特征具备横向可比性,计算方式为方差除以bin总数的平方
- 可复用代码:
def calc_hist_norm_variance(hist, variance=None): hist_flat = hist.flatten() n_bins = hist_flat.shape[0] if variance is None: variance = calc_hist_variance(hist) norm_variance = variance / (n_bins ** 2) return norm_variance
4. 直方图熵
- 核心逻辑:衡量直方图的分布均匀度,分布越均匀熵值越高,分布越集中熵值越低。计算时需要过滤计数为0的bin,避免出现对数计算错误
- 可复用代码:
def calc_hist_entropy(hist): hist_flat = hist.flatten() total_pixels = hist_flat.sum() # 过滤零值bin,计算归一化概率 valid_p = hist_flat[hist_flat > 0] / total_pixels entropy = - (valid_p * np.log2(valid_p)).sum() return entropy
与现有代码的整合
把上述特征计算函数嵌入你已有的直方图对比流程中即可,整合后的完整代码如下,同时修正了原代码中对比方法硬编码的问题:
HIST_METHODS = { "Correlation": cv2.HISTCMP_CORREL, "Chi-Squared": cv2.HISTCMP_CHISQR, "Intersection": cv2.HISTCMP_INTERSECT, "Hellinger": cv2.HISTCMP_BHATTACHARYYA } HIST_COLORS = ('b','g','r') # 此处放置上述定义的4个特征计算函数 for key, value in HIST_METHODS.items(): compare_results = [] feature_results = [] for i, col in enumerate(HIST_COLORS): hist1 = cv2.calcHist([img1],[i],None,[256],[0,256], accumulate = False) hist2 = cv2.calcHist([img2],[i],None,[256],[0,256], accumulate = False) # 原有直方图对比逻辑,修正为使用循环内的对比方法值 res = cv2.compareHist(hist1, hist2, value) compare_results.append(res) # 提取两个图像的直方图特征 img1_feat = { "mean": calc_hist_mean(hist1), "variance": calc_hist_variance(hist1), "norm_variance": calc_hist_norm_variance(hist1), "entropy": calc_hist_entropy(hist1) } img2_feat = { "mean": calc_hist_mean(hist2), "variance": calc_hist_variance(hist2), "norm_variance": calc_hist_norm_variance(hist2), "entropy": calc_hist_entropy(hist2) } feature_results.append((img1_feat, img2_feat))
注意:你原代码中
cv2.compareHist的第三个参数硬编码为cv2.HISTCMP_CORREL,没有使用循环遍历到的方法值,实际运行时无论循环到哪种对比方法,返回结果都是相关性对比的结果,可顺手修正。
内容的提问来源于stack exchange,提问作者Lleims
相关产品推荐
相关产品推荐

