【OpenCV】Python图像处理之特征提取

Python 图像处理中的特征提取是从图像中提取具有代表性的信息(如边缘、纹理、形状、关键点等),用于后续的分类、识别、检索等任务。以下结合常用算法和库(OpenCV、Scikit-image、PIL)详细介绍关键特征提取技术及实现代码。

一、基础特征提取

1. 颜色特征

颜色直方图是最常用的颜色特征,描述图像中颜色的分布。

‌OpenCV中‌calcHist函数用于计算图像的颜色直方图,支持多通道统计和自定义参数。以下是核心用法和注意事项:

函数原型:
python 复制代码
cv2.calcHist(images, channels, mask, histSize, ranges)
  • images: 输入图像列表(需用中括号包裹)
  • channels: 通道索引(灰度图用,彩色图用[0,1,2]表示BGR通道)
  • mask: 掩膜(None表示全图统计)
  • histSize: 直方图的灰度级数(如[256])
  • ranges: 像素值范围(如[0,256])
示例代码:
python 复制代码
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图像并转换为RGB
img = cv2.imread('image.jpg')
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 计算RGB颜色直方图
hist_r = cv2.calcHist([img_rgb], [0], None, [256], [0, 256])
hist_g = cv2.calcHist([img_rgb], [1], None, [256], [0, 256])
hist_b = cv2.calcHist([img_rgb], [2], None, [256], [0, 256])

# 绘制直方图
plt.figure(figsize=(12, 4))
plt.plot(hist_r, color='red', alpha=0.7)
plt.plot(hist_g, color='green', alpha=0.7)
plt.plot(hist_b, color='blue', alpha=0.7)
plt.title('RGB Color Histogram')
plt.xlabel('Pixel Value')
plt.ylabel('Frequency')
plt.show()
注意事项
  • 多通道处理:彩色图需指定通道(如[0,1,2]),可分别计算各通道直方图。
  • 掩膜应用:通过mask参数可限定统计区域(如只计算图像某部分)。
  • 颜色空间转换:通常使用‌HSV或‌YUV等颜色空间提取更鲁棒的颜色特征
2. 纹理特征(灰度共生矩阵 GLCM)

GLCM 描述图像中灰度的空间分布关系,用于提取纹理特征(对比度、能量、熵等)。

python 复制代码
from skimage.feature import greycomatrix, greycoprops
from skimage.color import rgb2gray

# 转换为灰度图像
gray_img = rgb2gray(img_rgb)
gray_img = (gray_img * 255).astype(np.uint8)  # 转换为8位灰度图

# 计算GLCM(距离1,角度0°、45°、90°、135°)
glcm = greycomatrix(gray_img, distances=[1], angles=[0, np.pi/4, np.pi/2, 3*np.pi/4], 
                    levels=256, symmetric=True, normed=True)

# 提取纹理特征
contrast = greycoprops(glcm, 'contrast')[0, 0]  # 对比度
energy = greycoprops(glcm, 'energy')[0, 0]      # 能量
homogeneity = greycoprops(glcm, 'homogeneity')[0, 0]  # 同质性
entropy = -np.sum(glcm * np.log2(glcm + 1e-10))  # 熵(需手动计算)

print(f"对比度: {contrast:.2f}, 能量: {energy:.2f}, 同质性: {homogeneity:.2f}, 熵: {entropy:.2f}")

二、边缘与轮廓特征

1. 边缘检测(Canny 算法)

Canny 算法通过多步骤检测图像中的边缘,具有高精度和低误检率。

‌Canny边缘检测算法是‌一种多级边缘检测算法,通过‌高斯滤波、‌梯度计算、‌非极大值抑制和‌双阈值检测四步实现图像边缘提取,最终输出二值边缘图像。

核心步骤
噪声去除

使用‌高斯滤波器(如5×5核)平滑图像,减少噪声干扰 。

计算梯度
  • 通过‌Sobel算子计算水平(Gx)和垂直(Gy)方向的梯度 。 ‌
  • 梯度幅值:,方向:θ=arctan⁡(Gy/Gx) 。 ‌
非极大值抑制

沿梯度方向(垂直、水平或对角线)比较当前像素与相邻像素的梯度值,仅保留局部最大值点,使边缘变"瘦" 。

双阈值检测
  • 高阈值(maxVal):直接保留强边缘 。
  • 低阈值(minVal):仅保留与强边缘相连的弱边缘 。
代码示例:
python 复制代码
# Canny边缘检测
edges = cv2.Canny(img_rgb, threshold1=100, threshold2=200)

# 显示结果
plt.figure(figsize=(10, 5))
plt.subplot(121), plt.imshow(img_rgb), plt.title('Original')
plt.subplot(122), plt.imshow(edges, cmap='gray'), plt.title('Canny Edges')
plt.axis('off')
plt.show()
参数说明:
  • threshold1(minVal)和threshold2(maxVal)控制边缘强度 。

  • apertureSize指定Sobel核大小(默认3×3) 。 ‌

2. 轮廓检测

轮廓是图像中物体的边界,可用于形状分析和目标识别。

python 复制代码
# 转换为灰度图并二值化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

# 检测轮廓
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 绘制轮廓
contour_img = cv2.drawContours(img_rgb.copy(), contours, -1, (0, 255, 0), 2)

plt.imshow(contour_img)
plt.title('Contours')
plt.axis('off')
plt.show()

# 提取轮廓特征(面积、周长)
for cnt in contours:
    area = cv2.contourArea(cnt)  # 面积
    perimeter = cv2.arcLength(cnt, closed=True)  # 周长
    print(f"轮廓面积: {area:.2f}, 周长: {perimeter:.2f}")

三、关键点与局部特征

1. SIFT(尺度不变特征变换)

SIFT 提取具有尺度和旋转不变性的关键点,适用于图像匹配和目标识别(需注意专利问题,OpenCV 4.4 + 需手动安装扩展)。

python 复制代码
# 初始化SIFT检测器
sift = cv2.SIFT_create()

# 检测关键点并计算描述符
keypoints, descriptors = sift.detectAndCompute(gray, None)

# 绘制关键点
sift_img = cv2.drawKeypoints(img_rgb, keypoints, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

plt.imshow(sift_img)
plt.title('SIFT Keypoints')
plt.axis('off')
plt.show()

print(f"检测到关键点数量: {len(keypoints)}, 描述符维度: {descriptors.shape}")
2. SURF(加速稳健特征)

SURF 是 SIFT 的加速版本,效率更高(同样存在专利问题)。

python 复制代码
# 初始化SURF检测器(Hessian阈值设为400)
surf = cv2.xfeatures2d.SURF_create(hessianThreshold=400)

# 检测关键点并计算描述符
keypoints_surf, descriptors_surf = surf.detectAndCompute(gray, None)

# 绘制关键点
surf_img = cv2.drawKeypoints(img_rgb, keypoints_surf, None, (255, 0, 0), 4)

plt.imshow(surf_img)
plt.title('SURF Keypoints')
plt.axis('off')
plt.show()
3. ORB(Oriented FAST and Rotated BRIEF)

ORB 是开源的、高效的局部特征提取算法,结合了 FAST 关键点检测和 BRIEF 描述符,具有旋转不变性。

python 复制代码
# 初始化ORB检测器
orb = cv2.ORB_create(nfeatures=1000)

# 检测关键点并计算描述符
keypoints_orb, descriptors_orb = orb.detectAndCompute(gray, None)

# 绘制关键点
orb_img = cv2.drawKeypoints(img_rgb, keypoints_orb, None, (0, 0, 255), 4)

plt.imshow(orb_img)
plt.title('ORB Keypoints')
plt.axis('off')
plt.show()

print(f"ORB关键点数量: {len(keypoints_orb)}, 描述符维度: {descriptors_orb.shape}")

四、深度学习特征提取

1. 使用预训练 CNN 模型(如 ResNet、VGG)

通过预训练的卷积神经网络提取高层语义特征,适用于复杂图像任务。

python 复制代码
import torch
import torchvision.models as models
import torchvision.transforms as transforms

# 加载预训练ResNet50
model = models.resnet50(pretrained=True)
model.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])
])

# 读取图像并预处理
from PIL import Image
img_pil = Image.open('image.jpg').convert('RGB')
input_tensor = transform(img_pil).unsqueeze(0)  # 添加batch维度

# 提取特征(去掉最后全连接层)
feature_extractor = torch.nn.Sequential(*list(model.children())[:-1])
with torch.no_grad():
    features = feature_extractor(input_tensor)

features = features.squeeze().numpy()  # 转为NumPy数组
print(f"CNN特征维度: {features.shape}")  # ResNet50输出2048维特征

五、形状特征(Hu 矩)

Hu 矩是一组具有平移、旋转和尺度不变性的矩特征,用于形状描述。

python 复制代码
# 计算Hu矩
moments = cv2.moments(gray)
hu_moments = cv2.HuMoments(moments)

# 对数变换(便于观察)
hu_moments = -np.sign(hu_moments) * np.log10(np.abs(hu_moments))

print("Hu矩特征:")
for i, hu in enumerate(hu_moments):
    print(f"Hu{i+1}: {hu[0]:.6f}")

六、总结

特征提取的核心是选择与任务匹配的特征类型:

  • 基础任务(如图像检索):颜色直方图、纹理特征(GLCM);
  • 目标匹配 / 识别:SIFT、ORB 等局部特征;
  • 复杂语义任务(如分类、检测):深度学习 CNN 特征;
  • 形状分析:轮廓特征、Hu 矩。

结合传统算法和深度学习方法,可高效提取图像的浅层和深层特征,满足不同场景需求。

相关推荐
用户576905308011 小时前
微调入门尝试:沐雪角色扮演
python·llm
ku_code_ku1 小时前
python几种包管理器的分析比较
开发语言·python·包管理器
2301_795167201 小时前
Python 高手编程系列一十三:现实例子 — 延迟求值属性
开发语言·windows·python
h***04771 小时前
爬虫学习案例3
爬虫·python·学习
2501_916008891 小时前
Python抓包HTTPS详解:Wireshark、Fiddler、Charles等工具使用教程
python·ios·小程序·https·uni-app·wireshark·iphone
Gitpchy1 小时前
Day 58 经典时序模型2
python
2301_795167201 小时前
Python 高手编程系列一十五:使用 __new __()方法覆写实例创建过程
开发语言·网络·python
轻竹办公PPT1 小时前
AI一键生成年终总结PPT
人工智能·python·powerpoint
是Dream呀1 小时前
昇腾平台 PyTorch 迁移实操:从环境搭建到精度达标的完整步骤
人工智能·pytorch·python·昇腾