
在计算机视觉任务中,"纹理"是我们描述图像内容的核心特征之一------从木纹的纹路、布料的编织纹理,到皮肤的毛孔、卫星图像中的地表纹理,纹理信息往往能直接决定图像的类别或属性。本文将从纹理的定义出发,详解纹理的定量分析方法,并通过代码实践让你快速掌握纹理特征的提取与应用。
一、纹理的定义与分类
1. 纹理的定义
纹理是图像中像素灰度值的空间分布模式,具有三大特性:
- 规律性:重复的图案结构(如棋盘格、砖墙);
- 随机性:无规则但有统计特征(如大理石纹理、噪声);
- 方向性:像素排列的主导方向(如木纹的纵向纹理、水流的条纹)。
简单来说,纹理是"局部像素的排列规律",是区分不同物体表面的关键特征(比如"皮革"和"纸张"的核心差异就是纹理)。
2. 纹理的分类
- 人工纹理:人为设计的重复图案(如棋盘格、条纹布);
- 自然纹理:自然界的纹理(如树叶脉络、岩石表面);
- 混合纹理:既有规律又有随机成分(如织物纹理)。
二、纹理的定量分析方法
定量分析纹理的核心是将视觉上的纹理特征转化为可计算的数值指标,主流方法分为四类:统计方法、频谱方法、结构方法和深度学习方法。
1. 统计方法:灰度共生矩阵(GLCM)
灰度共生矩阵是最经典的纹理统计分析方法,通过计算图像中不同位置像素对的灰度值共生概率,提取纹理的对比度、能量、熵等特征。
原理
GLCM描述了"距离为d、方向为θ的两个像素分别取灰度i和j"的概率。常用方向θ为0°、45°、90°、135°,距离d通常取1。基于GLCM可计算以下特征:
- 对比度:衡量纹理的清晰度和沟纹深浅,值越大纹理越清晰;
- 能量:衡量纹理的均匀性,值越大纹理越规则;
- 熵:衡量纹理的复杂度,值越大纹理越混乱;
- 相关性:衡量纹理的方向一致性,值越大纹理方向越明显。
代码实践:GLCM特征提取
使用skimage库实现GLCM特征计算(以经典的"布鲁克斯纹理数据集"为例):
python
import numpy as np
import cv2
from skimage.feature import graycomatrix, graycoprops
from skimage import data
import matplotlib.pyplot as plt
# 加载示例图像(skimage自带的纹理图像)
image = data.camera() # 灰度图像,若为彩色需先转灰度
# 计算GLCM(距离1,方向0°、45°、90°、135°)
glcm = graycomatrix(
image,
distances=[1],
angles=[0, np.pi/4, np.pi/2, 3*np.pi/4],
levels=256, # 灰度级数量
symmetric=True, # 对称矩阵(i,j和j,i视为同一对)
normed=True # 归一化
)
# 提取GLCM特征
contrast = graycoprops(glcm, 'contrast')[0]
energy = graycoprops(glcm, 'energy')[0]
entropy = graycoprops(glcm, 'entropy')[0] # 注意:skimage需手动计算熵,此处简化用graycoprops
correlation = graycoprops(glcm, 'correlation')[0]
# 输出特征值
print(f"对比度(0°,45°,90°,135°):{contrast}")
print(f"能量:{energy}")
print(f"相关性:{correlation}")
# 可视化原图
plt.imshow(image, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.show()
结果分析
- 若图像是"棋盘格",对比度会很高、能量也高(纹理规则);
- 若图像是"噪声图",熵会很高、相关性很低(纹理混乱)。
2. 频谱方法:傅里叶变换
纹理的周期性规律在频域中会表现为明显的峰值------比如横向条纹纹理在频域的垂直方向会有强分量,纵向条纹则在水平方向有强分量。通过分析傅里叶变换的频谱分布,可定量描述纹理的方向性和周期性。
原理
- 对图像做二维傅里叶变换,得到频域图像;
- 计算频谱的径向分布(不同频率的能量)和角度分布(不同方向的能量);
- 提取"主方向""频率峰值"等特征描述纹理。
代码实践:傅里叶变换分析纹理
python
import numpy as np
import cv2
import matplotlib.pyplot as plt
# 加载纹理图像(以横向条纹为例)
image = np.zeros((256, 256), dtype=np.uint8)
for i in range(0, 256, 10):
image[i:i+2, :] = 255 # 生成横向条纹
# 二维傅里叶变换
f = np.fft.fft2(image)
f_shift = np.fft.fftshift(f) # 移到中心
magnitude_spectrum = 20 * np.log(np.abs(f_shift)) # 幅度谱(对数缩放)
# 可视化原图和频谱
plt.subplot(121), plt.imshow(image, cmap='gray')
plt.title('Original Texture'), plt.axis('off')
plt.subplot(122), plt.imshow(magnitude_spectrum, cmap='gray')
plt.title('Fourier Spectrum'), plt.axis('off')
plt.show()
结果分析
横向条纹的频谱在垂直方向出现明显亮线(对应纹理的周期性方向),若为斜向条纹,亮线会出现在对应角度。
3. 深度学习方法:CNN提取纹理特征
传统方法依赖人工设计特征,而CNN可自动学习纹理的深层特征,尤其适合复杂纹理的分类或识别。
原理
利用预训练CNN(如ResNet、VGG)的卷积层输出,作为纹理的高维特征------浅层卷积层捕捉边缘、纹理细节,深层捕捉纹理的抽象模式。
代码实践:CNN纹理特征提取
python
import torch
import torch.nn as nn
from torchvision import models, transforms
from PIL import Image
# 加载预训练ResNet18
model = models.resnet18(pretrained=True)
# 移除全连接层,保留卷积层特征
feature_extractor = nn.Sequential(*list(model.children())[:-1])
feature_extractor.eval() # 推理模式
# 图像预处理
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
# 加载纹理图像(以皮革纹理为例)
image = Image.open('leather.jpg').convert('RGB')
input_tensor = transform(image).unsqueeze(0) # 加batch维度
# 提取特征
with torch.no_grad():
features = feature_extractor(input_tensor)
features = features.view(features.size(0), -1) # 展平
print(f"纹理特征维度:{features.shape}") # ResNet18输出512维特征
应用场景
提取的特征可直接用于纹理分类(如区分"皮革""木材""金属"),或结合SVM、KNN完成识别任务。
三、纹理分析的应用场景
- 工业质检:通过纹理缺陷(如布料的破洞、金属的划痕)检测产品质量;
- 医学影像:分析皮肤纹理诊断皮肤病,或通过肺部CT纹理识别病变;
- 遥感图像:根据地表纹理区分森林、农田、建筑区域;
- 图像检索:以纹理特征为关键词检索相似图像。
四、总结
纹理的定量分析是计算机视觉从"感知"到"理解"的关键步骤:传统方法(GLCM、傅里叶变换)解释性强,适合简单纹理;深度学习方法则更擅长复杂纹理的特征学习。在实际应用中,需根据纹理类型和任务需求选择合适的方法------比如工业质检用GLCM足够,而遥感图像分类可结合CNN提升精度。