灰度共生矩阵 (GLCM) 纹理特征实战:Python 代码提取 7 个 Haralick 特征

📅 2026/7/6 1:15:18
灰度共生矩阵 (GLCM) 纹理特征实战:Python 代码提取 7 个 Haralick 特征
灰度共生矩阵GLCM纹理特征实战Python代码提取7个Haralick特征在计算机视觉和图像处理领域纹理分析是一个重要的研究方向。纹理特征能够描述图像中像素之间的空间关系为图像分类、目标识别和场景理解等任务提供关键信息。本文将深入探讨灰度共生矩阵GLCM这一经典纹理特征提取方法并提供可直接复用的Python实现代码。1. GLCM纹理特征基础灰度共生矩阵Gray-Level Co-occurrence MatrixGLCM是1973年由Haralick等人提出的一种纹理分析方法。它通过统计图像中特定空间关系的像素对出现的频率来描述纹理特征。GLCM的核心思想是捕捉图像中灰度值的空间分布规律。1.1 GLCM的基本原理GLCM计算的是在特定空间关系距离d和方向θ下灰度值为i的像素与灰度值为j的像素同时出现的概率。常见的计算方向包括0°水平方向45°对角线方向90°垂直方向135°反对角线方向GLCM矩阵的大小取决于图像的灰度级数。对于一个8位灰度图像256级如果直接计算GLCM会非常大256×256。因此通常会对灰度级进行压缩例如降到16级或8级。1.2 Haralick特征简介Haralick从GLCM中提取了14个统计量来描述纹理特征。本文重点实现以下7个最常用的特征对比度Contrast度量图像局部变化的程度反映纹理的清晰度能量Energy又称角二阶矩反映图像灰度分布的均匀性熵Entropy衡量图像纹理的随机性和复杂度逆方差Inverse Difference Moment反映图像局部均匀性相关性Correlation度量灰度线性依赖关系均值MeanGLCM中像素对的平均灰度值标准差Standard DeviationGLCM中像素对灰度值的离散程度2. Python实现GLCM特征提取下面我们将实现一个完整的GLCM特征提取类包含图像预处理、GLCM计算和特征提取三个主要部分。2.1 图像预处理首先我们需要对输入图像进行预处理包括灰度转换和灰度级压缩import numpy as np import cv2 import math from matplotlib import pyplot as plt class GLCMFeatureExtractor: def __init__(self, gray_level16): self.gray_level gray_level def preprocess_image(self, image_path): 读取并预处理图像 # 读取图像 img cv2.imread(image_path) if img is None: raise ValueError(f无法读取图像: {image_path}) # 转换为灰度图 if len(img.shape) 3: img_gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) else: img_gray img # 调整图像大小可选 img_gray cv2.resize(img_gray, (img_gray.shape[1]//2, img_gray.shape[0]//2), interpolationcv2.INTER_CUBIC) # 灰度级压缩 max_gray np.max(img_gray) if max_gray self.gray_level: img_gray (img_gray * (self.gray_level-1) / max_gray).astype(np.uint8) return img_gray2.2 GLCM计算接下来实现GLCM的核心计算函数def compute_glcm(self, img_gray, d1, theta0): 计算灰度共生矩阵 Args: img_gray: 灰度图像 d: 像素对距离 theta: 方向角度(0,45,90,135) Returns: glcm: 归一化的灰度共生矩阵 height, width img_gray.shape glcm np.zeros((self.gray_level, self.gray_level), dtypenp.float32) # 根据方向计算偏移量 if theta 0: # 0度方向 dx, dy d, 0 elif theta 45: # 45度方向 dx, dy d, -d elif theta 90: # 90度方向 dx, dy 0, d elif theta 135: # 135度方向 dx, dy -d, d else: raise ValueError(theta必须是0,45,90或135度) # 计算共生矩阵 for y in range(max(-dy, 0), height - max(dy, 0)): for x in range(max(-dx, 0), width - max(dx, 0)): i img_gray[y, x] j img_gray[y dy, x dx] glcm[i, j] 1 # 归一化 glcm / glcm.sum() return glcm2.3 特征提取基于计算得到的GLCM我们可以提取7个Haralick特征def extract_features(self, glcm): 从GLCM中提取7个Haralick特征 # 初始化特征值 features { contrast: 0.0, energy: 0.0, entropy: 0.0, homogeneity: 0.0, correlation: 0.0, mean: 0.0, std_dev: 0.0 } # 计算均值 mean_i 0.0 mean_j 0.0 for i in range(self.gray_level): for j in range(self.gray_level): mean_i i * glcm[i, j] mean_j j * glcm[i, j] # 计算标准差 std_i 0.0 std_j 0.0 for i in range(self.gray_level): for j in range(self.gray_level): std_i (i - mean_i)**2 * glcm[i, j] std_j (j - mean_j)**2 * glcm[i, j] std_i math.sqrt(std_i) std_j math.sqrt(std_j) # 计算各特征 for i in range(self.gray_level): for j in range(self.gray_level): p glcm[i, j] if p 0: # 对比度 features[contrast] (i - j)**2 * p # 能量 features[energy] p**2 # 熵 features[entropy] - p * math.log(p) # 同质性逆方差 features[homogeneity] p / (1 (i - j)**2) # 相关性 if std_i 0 and std_j 0: features[correlation] ((i - mean_i) * (j - mean_j) * p) / (std_i * std_j) # 均值 features[mean] mean_i # 标准差 features[std_dev] std_i return features3. 多方向GLCM特征融合为了获得更全面的纹理描述我们通常会计算多个方向的GLCM然后将特征进行融合def extract_multi_direction_features(self, image_path, distances[1], angles[0, 45, 90, 135]): 提取多方向GLCM特征并融合 img_gray self.preprocess_image(image_path) all_features [] for d in distances: for angle in angles: glcm self.compute_glcm(img_gray, d, angle) features self.extract_features(glcm) all_features.append(features) # 计算各方向特征的平均值 avg_features {} for key in all_features[0].keys(): avg_features[key] np.mean([f[key] for f in all_features]) return avg_features4. 应用案例与可视化4.1 不同类型图像的纹理特征对比我们选取三种不同类型的图像织物、卫星图像和医学图像进行纹理特征分析def compare_texture_features(image_paths): extractor GLCMFeatureExtractor(gray_level16) results [] for path in image_paths: features extractor.extract_multi_direction_features(path) results.append((path.split(/)[-1], features)) # 可视化对比 fig, axes plt.subplots(1, len(image_paths), figsize(15, 5)) for idx, (name, features) in enumerate(results): # 显示图像 img cv2.imread(image_paths[idx]) img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) axes[idx].imshow(img) axes[idx].axis(off) axes[idx].set_title(name) # 打印特征值 print(f\n图像: {name}) for key, value in features.items(): print(f{key:15}: {value:.4f}) plt.tight_layout() plt.show() return results4.2 特征可视化我们可以将提取的特征进行可视化更直观地比较不同纹理的特性def visualize_features(results): 可视化不同图像的纹理特征 names [name for name, _ in results] features [feat for _, feat in results] feature_names list(features[0].keys()) plt.figure(figsize(12, 8)) for i, feat_name in enumerate(feature_names): plt.subplot(3, 3, i1) values [f[feat_name] for f in features] plt.bar(names, values) plt.title(feat_name) plt.xticks(rotation45) plt.tight_layout() plt.show()5. 工程实践建议在实际应用中使用GLCM提取纹理特征时需要注意以下几点5.1 参数选择优化灰度级数通常选择8、16或32级级数太少会丢失纹理细节太多会增加计算量距离d的选择常用d1但对于大尺度纹理可能需要更大的d可以尝试多个距离值并比较结果方向选择至少选择0°、45°、90°和135°四个方向对于有明显方向性的纹理可以增加方向数量5.2 性能优化技巧对于大图像或实时应用可以考虑以下优化方法def optimized_glcm_computation(img_gray, d1, theta0, gray_level16): 优化版的GLCM计算 # 使用向量化操作替代循环 height, width img_gray.shape # 根据方向计算偏移 if theta 0: dx, dy d, 0 elif theta 45: dx, dy d, -d elif theta 90: dx, dy 0, d elif theta 135: dx, dy -d, d # 创建坐标网格 y, x np.indices((height - abs(dy), width - abs(dx))) x_shift x dx y_shift y dy # 获取像素对 pixels_i img_gray[y, x] pixels_j img_gray[y_shift, x_shift] # 计算共生矩阵 glcm np.zeros((gray_level, gray_level), dtypenp.float32) np.add.at(glcm, (pixels_i, pixels_j), 1) # 归一化 glcm / glcm.sum() return glcm5.3 实际应用中的注意事项图像尺寸一致性确保所有比较的图像具有相同或相似的尺寸必要时进行归一化处理光照条件GLCM对光照变化敏感应用前可进行直方图均衡化特征选择不是所有Haralick特征都对特定任务有用可以通过特征重要性分析选择最相关的特征与其他特征结合GLCM特征可以与其他纹理特征如LBP结合使用也可以与颜色特征、形状特征等组合6. 扩展应用纹理分类GLCM特征常用于图像分类任务。下面是一个简单的纹理分类示例from sklearn.svm import SVC from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report def texture_classification(image_paths, labels): 使用GLCM特征进行纹理分类 extractor GLCMFeatureExtractor() # 提取特征 X [] for path in image_paths: features extractor.extract_multi_direction_features(path) X.append(list(features.values())) X np.array(X) y np.array(labels) # 划分训练测试集 X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, random_state42) # 训练SVM分类器 clf SVC(kernelrbf, gammascale) clf.fit(X_train, y_train) # 评估 y_pred clf.predict(X_test) print(classification_report(y_test, y_pred)) return clf7. 总结与展望灰度共生矩阵作为一种经典的纹理分析方法在多个领域都有广泛应用。本文实现的Python代码可以直接应用于各种图像分析任务包括但不限于遥感图像分类医学图像分析工业表面检测材质识别生物特征识别在实际项目中GLCM特征通常需要与其他特征和方法结合使用并根据具体任务进行调整和优化。随着深度学习的发展传统纹理特征方法可以与深度特征相结合发挥各自的优势。