当前位置: 首页 > news >正文

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

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

一、基础特征提取

1. 颜色特征

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

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

函数原型:
cv2.calcHist(images, channels, mask, histSize, ranges)
  • images: 输入图像列表(需用中括号包裹)
  • channels: 通道索引(灰度图用,彩色图用[0,1,2]表示BGR通道)
  • mask: 掩膜(None表示全图统计)
  • histSize: 直方图的灰度级数(如[256])
  • ranges: 像素值范围(如[0,256])
示例代码:
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 描述图像中灰度的空间分布关系,用于提取纹理特征(对比度、能量、熵等)。

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):仅保留与强边缘相连的弱边缘 。
代码示例:
# 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. 轮廓检测

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

# 转换为灰度图并二值化
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 + 需手动安装扩展)。

# 初始化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 的加速版本,效率更高(同样存在专利问题)。

# 初始化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 描述符,具有旋转不变性。

# 初始化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)

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

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 矩是一组具有平移、旋转和尺度不变性的矩特征,用于形状描述。

# 计算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 矩。

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

http://www.jsqmd.com/news/365462/

相关文章:

  • 2026年薪酬绩效管理咨询推荐:上海创锟咨询,薪酬绩效体系/设计/管理一站式服务 - 品牌推荐官
  • 2026年河南靠谱的激光除锈机厂商排名,朋朋激光位居前列 - myqiye
  • 目前(截至2024年),**OpenClaw**、**VibeCoding** 并非真实存在的、被广泛认可的开源框架或主流AI编程工具
  • 2026年口碑不错的物业公司费用多少,有资质的来了解 - mypinpai
  • 小程序首次加载过慢优化
  • 明正精密机械好不好,它在管材加工设备市场口碑咋样 - 工业推荐榜
  • 好写作AI:从“玄学抽卡”到“精准许愿”,你的提示词才是真正的魔法杖
  • arduino led入门:从连接到编程实现闪烁控制
  • 卫报新闻文章数据集-2016-2022年14万+篇多领域英文新闻全文数据-适用于自然语言处理模型训练与内容分析研究-自然语言处理研究、媒体分析、社会趋势研究以及人工智能模型训练
  • mysql的主从安装
  • 好写作AI:当访谈录音堆成山,让AI当你的“定性研究整理大师”
  • PUDN和CSDN区别:源码下载vs技术社区哪个好?
  • 保障安全与效率:详解沼气工程核心设备——双膜储气柜
  • P10113 [GESP202312 八级] 大量的工作沟通 题解
  • 好写作AI:当答辩现场变身“AI模拟考场”,社恐学霸也能carry全场!
  • 别让并发 Bug 毁掉你的系统:从 HR 项目实战聊聊数据库锁的正确姿势
  • JDK的错误提示纠偏作用不太友好
  • 招聘心理学:看懂候选人的“身体语言”
  • 2026年解码耳放工厂推荐:针对定制化与交付痛点,全产业链服务能力深度评价 - 品牌推荐
  • 蒂芙尼广告:自1837年以来,见证每一段爱情故事
  • 关于Java开发体验的反思
  • 2026年解码耳放工厂推荐:五大厂商综合评测与精准排名解析 - 品牌推荐
  • 告别爽约?三招提升面试到场率
  • NoETL 语义编织 vs 传统 ETL/ELT,指标平台选型深度对比
  • 互联网大厂Java面试:JVM、Spring Boot与微服务场景解析
  • 基于PDF.js的安全PDF预览组件实现:从虚拟滚动到水印渲染
  • 2026年度螺杆式制冷机组选型指南:主流厂家推荐与性价比产品攻略! - 品牌推荐大师1
  • C语言循环双端队列实现与防溢出指南
  • 国产AI芯片企业如何2天搭建全链路模型管理平台?CSGHub私有化+API自动化实践
  • SpringBoot 项目中 yml 配置文件的所有属性引用 / 加载方式