深度学习实验一之图像特征提取和深度学习训练数据标注
1、安装 Anaconda
从 Anaconda 官网(https://www.anaconda.com/)下载对应操作系统(Windows/macOS/Linux)的安装包,双击运行安装程序,按提示完成安装(建议勾选 “Add Anaconda3 to my PATH environment variable”,方便后续命令行调用);安装完成后,通过 “开始菜单”(Windows)或 “启动台”(macOS)打开 Anaconda Prompt,输入 conda --version,显示版本号则表明 Anaconda 安装成功。(网上相关教程较多,不再赘述)
如下图所示。windows命令行cmd中输入conda –version回车显示anaconda版本号,说明安装成功,同时成功启动anaconda Navigator
2、创建并激活conda环境
3、安装依赖库
结果出现报错,提示在当前通道获取不到对应的依赖包。
尝试使用pip进行安装
下载较慢,尝试使用国内镜像源,提高下载速度
安装完成
4、验证环境可用性
1、测试Numpy功能
2、测试 OpenCV-Python
使用opencv创建一个窗口
点击任意键后关闭窗口。
说明opencv-python安装成功!
5、Pycharm安装与项目配置
1、安装pycharm
官网下载安装即可,如下图图标
如下图所示,安装成功
2、配置 Pycharm 项目与解释器
进入pycharm创建新项目,并解释器设置为刚刚创建的python虚拟环境
3、编写与运行边缘检测代码
在创建好的项目中创建python文件,用于测试边缘检测。
然后,编写代码,如下
import cv2# 1. 读取测试图像
image = cv2.imread('panda.png', 0)# 检查图像是否成功读取(避免路径错误出现控制)
if image is None:print('Error: 无法读取图像,请检查文件路径或文件格式!')
else:# 2. Canny边缘检测(参数100为下限阈值,200为上限阈值,可调整)edges = cv2.Canny(image, 100, 200)# 3. 显示原始图像和边缘检测结果cv2.imshow('Original Gray Image', image)cv2.imshow('Canny Edge Detection Result', edges)# 4. 等待按键输入,按ESC键关闭窗口(避免窗口闪退)while True:key = cv2.waitKey(1)if key == 27: # 27为ESC键的ASCII码break# 5. 关闭所有图像窗口,释放资源cv2.destroyAllWindows()# 6. 保存边缘检测结果cv2.imwrite('canny_edge_result.jpg', edges)print("边缘检测结果已保存为 canny_edge_result.jpg")
运行如下
点击ESC键,后退出,并保存边缘图像在所在目录中,如下
6、基于不同算子的图像边缘特征检测
1、实验原理
Roberts 算子:采用 2×2 邻域,通过计算对角线方向的像素灰度差分(如 (f(x+1,y+1)-f(x,y)) 和 (f(x+1,y)-f(x,y+1)))检测边缘,对陡峭边缘响应灵敏,但抗噪声能力较弱。
Sobel 算子:采用 3×3 邻域,分别计算 x 方向(水平)和 y 方向(垂直)的梯度值,通过梯度幅值判断边缘,对噪声有一定抑制作用,能有效检测水平和垂直边缘。
Prewitt 算子:同样采用 3×3 邻域,通过邻域像素平均差分计算梯度,对边缘的平滑作用优于 Sobel 算子,抗噪声能力更强,但边缘定位精度略低。
2、代码编写
创建名为 “edge_detection_operators.py” 的文件,编写代码如下
import cv2
import numpy as np
# 读取灰度图像
image = cv2.imread('panda.png', 0)
if image is None:print("Error: 无法读取图像!")exit()# 1. Roberts算子边缘检测(自定义卷积核)
roberts_x = np.array([[1, 0], [0, -1]], dtype=np.float32) # x方向(对角线1)
roberts_y = np.array([[0, 1], [-1, 0]], dtype=np.float32) # y方向(对角线2)
roberts_edge_x = cv2.filter2D(image, -1, roberts_x) # 卷积计算x方向边缘
roberts_edge_y = cv2.filter2D(image, -1, roberts_y) # 卷积计算y方向边缘
roberts_edge = cv2.addWeighted(roberts_edge_x, 0.5, roberts_edge_y, 0.5, 0) # 融合两个方向边缘# 2. Sobel算子边缘检测(OpenCV内置函数)
sobel_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3) # x方向,ksize为卷积核大小
sobel_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3) # y方向
sobel_x_abs = cv2.convertScaleAbs(sobel_x) # 转换为绝对值(避免负梯度被截断)
sobel_y_abs = cv2.convertScaleAbs(sobel_y)
sobel_edge = cv2.addWeighted(sobel_x_abs, 0.5, sobel_y_abs, 0.5, 0) # 融合边缘# 3. Prewitt算子边缘检测(自定义卷积核)
prewitt_x = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]], dtype=np.float32) # x方向
prewitt_y = np.array([[-1, -1, -1], [0, 0, 0], [1, 1, 1]], dtype=np.float32) # y方向
prewitt_edge_x = cv2.filter2D(image, -1, prewitt_x)
prewitt_edge_y = cv2.filter2D(image, -1, prewitt_y)
prewitt_edge = cv2.addWeighted(prewitt_edge_x, 0.5, prewitt_edge_y, 0.5, 0)# 显示所有结果
cv2.imshow('Original Image', image)
cv2.imshow('Roberts Edge Detection', roberts_edge)
cv2.imshow('Sobel Edge Detection', sobel_edge)
cv2.imshow('Prewitt Edge Detection', prewitt_edge)
# 保存结果
cv2.imwrite('roberts_edge.jpg', roberts_edge)
cv2.imwrite('sobel_edge.jpg', sobel_edge)
cv2.imwrite('prewitt_edge.jpg', prewitt_edge)
# 等待按键关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
print("所有边缘检测结果已保存!")
运行代码,如下
成功显示三种算子处理过的边缘图像以及原始灰度图像,并保存三种算子处理后的图像在工程目录,如下图所示。
3、简单分析
首先展示Roberts算子代码截图以及实验结果,如下图所示。
分析:通过自定义x、y方向的卷积核,用filter2D计算两个方向边缘,再用addWeighted融合,实现对角边缘检测,对陡峭低噪声边缘敏感。
其次展示Sobel算子代码截图以及实验结果,如下图所示。
分析:借助 OpenCV 内置Sobel函数计算x、y方向梯度,经convertScaleAbs转绝对值后,用addWeighted融合,能有效检测不同方向边缘,抗噪性较好。
最后展示Prewitt算子代码截图以及实验结果,如下图所示。
分析:自定义x、y方向卷积核,经filter2D计算边缘后用addWeighted融合,对水平和垂直边缘检测效果较好,在一定程度上抑制噪声。
7、基于三种算子的图像特征点提取(以 Harris、SIFT、ORB 为例)
1、实验原理
Harris 算子:通过计算图像局部区域的灰度变化矩阵(自相关矩阵),分析矩阵的特征值判断该区域是否为角点(特征值均较大则为角点),具有旋转不变性,但不具备尺度不变性。
SIFT 算子(尺度不变特征变换):通过构建尺度空间(高斯金字塔)检测不同尺度下的极值点,计算极值点的方向信息,生成具有尺度、旋转不变性的特征描述子,适用于复杂场景下的特征匹配,但计算速度较慢。
ORB 算子(Oriented FAST and Rotated BRIEF):基于 FAST 算子检测特征点,结合 BRIEF 描述子并加入方向信息,具有尺度、旋转不变性,且计算速度远快于 SIFT(无专利限制),适合实时场景。
2、代码实现
考虑到黑色背景比较影响视觉,因此改成白色主题,
继续创建python文件,编写特征点提取代码
代码如下
import cv2
import numpy as np# 读取彩色图像(特征点绘制需彩色图像背景)
image = cv2.imread('panda.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 转为灰度图用于特征点检测
if image is None:print("Error: 无法读取图像!")exit()# 复制原始图像用于绘制不同算子的特征点(避免相互覆盖)
img_harris = image.copy()
img_sift = image.copy()
img_orb = image.copy()# 1. Harris角点检测
# 步骤1:计算灰度图的协方差矩阵(使用 Sobel 算子计算梯度)
gray_float = np.float32(gray)
harris_corners = cv2.cornerHarris(gray_float, blockSize=2, ksize=3, k=0.04)
# 步骤2:膨胀结果(使角点更明显,便于绘制)
harris_corners = cv2.dilate(harris_corners, None)
# 步骤3:标记角点(阈值设为最大值的0.01,超过阈值则视为角点,用红色标记)
img_harris[harris_corners > 0.01 * harris_corners.max()] = [0, 0, 255] # BGR格式,红色为[0,0,255]# 2. SIFT特征点检测(OpenCV 4.x需安装opencv-contrib-python,避免专利问题)
# 安装命令:conda install -c conda-forge opencv-contrib-python
sift = cv2.SIFT_create()
keypoints_sift, descriptors_sift = sift.detectAndCompute(gray, None) # 检测特征点并计算描述子
# 绘制特征点(参数:图像、特征点、绘制颜色、特征点大小)
img_sift = cv2.drawKeypoints(image, keypoints_sift, img_sift, color=(0, 255, 0), flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)# 3. ORB特征点检测(OpenCV内置,无专利限制)
orb = cv2.ORB_create(nfeatures=500) # nfeatures设为最大特征点数量
keypoints_orb, descriptors_orb = orb.detectAndCompute(gray, None)
# 绘制特征点(用蓝色标记)
img_orb = cv2.drawKeypoints(image, keypoints_orb, img_orb, color=(255, 0, 0), flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)# 显示结果
cv2.imshow('Harris Corners', img_harris)
cv2.imshow('SIFT Feature Points', img_sift)
cv2.imshow('ORB Feature Points', img_orb)
# 保存结果
cv2.imwrite('harris_corners.jpg', img_harris)
cv2.imwrite('sift_features.jpg', img_sift)
cv2.imwrite('orb_features.jpg', img_orb)
# 打印特征点数量
print(f"Harris角点数量:{len(np.where(harris_corners > 0.01 * harris_corners.max())[0])}")
print(f"SIFT特征点数量:{len(keypoints_sift)}")
print(f"ORB特征点数量:{len(keypoints_orb)}")# 等待按键关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
运行代码,效果如下
3、简单分析
首先是基于Harris 算子的代码、实验结果及分析:
分析:将灰度图转为浮点型后用cornerHarris计算角点,经dilate膨胀增强,通过阈值筛选出角点并用红色标记,适合检测图像中的角点特征。
其次是基于SIFT 算子的代码、实验结果及分析:
分析:通过SIFT_create()创建检测器,调用detectAndCompute同时检测特征点和计算描述子,用绿色绘制含大小方向信息的特征点,能提取稳定的尺度不变特征。
最后是基于ORB 算子的代码、实验结果及分析:
分析:用ORB_create初始化并设置最大特征点数量,检测计算后以蓝色绘制特征点,是无专利限制的快速特征检测方法,兼具旋转不变性。
8、基于三种方法的图像纹理特征提取(GLCM、LBP、Gabor)
1、实验原理
灰度共生矩阵(GLCM):统计图像中距离为 d、角度为 θ 的两个像素的灰度值组合出现频率,生成矩阵后计算对比度(纹理清晰度)、相关性(像素灰度相关性)、能量(纹理均匀度)、熵(纹理复杂度)等特征,描述图像纹理的宏观特性。
局部二值模式(LBP):对每个像素,将其与 3×3 邻域内的 8 个像素比较,大于中心像素则记为 1,否则记为 0,组成 8 位二进制数作为该像素的 LBP 值,通过统计 LBP 值的直方图反映图像纹理的局部特征,对光照变化有较强鲁棒性。
Gabor 滤波器:基于高斯函数调制的正弦波,可通过调整方向(theta)、尺度(sigma)、频率(lambda)等参数,对不同方向和尺度的纹理进行响应,提取纹理的方向和频率特征,模拟人类视觉系统对纹理的感知。
2、安装依赖包
3、代码实现
同理,创建名为 “texture_feature_extraction.py” 的文件,编写代码如下
import cv2
import numpy as np
from skimage.feature import graycomatrix, graycoprops
from skimage.feature import local_binary_pattern
import matplotlib.pyplot as plt# 读取灰度图像
image = cv2.imread('panda.png', 0)
if image is None:print("Error: 无法读取图像!")exit()# 1. 灰度共生矩阵(GLCM)特征提取
# 步骤1:生成GLCM(距离d=1,角度theta=0°,灰度级设为256)
glcm = graycomatrix(image, distances=[1], angles=[0], levels=256, symmetric=True, normed=True)
# 步骤2:计算GLCM支持的特征(对比度、相关性、能量、均匀性)
contrast = graycoprops(glcm, 'contrast')[0, 0]
correlation = graycoprops(glcm, 'correlation')[0, 0]
energy = graycoprops(glcm, 'energy')[0, 0]
homogeneity = graycoprops(glcm, 'homogeneity')[0, 0]# 自定义计算熵
def calculate_entropy(glcm_matrix):# 确保矩阵是二维的glcm_2d = glcm_matrix[:, :, 0, 0]# 计算熵,熵的公式为 -sum(p * log2(p)),其中p是概率(这里GLCM已经归一化)entropy = 0for i in range(glcm_2d.shape[0]):for j in range(glcm_2d.shape[1]):if glcm_2d[i, j] > 0:entropy -= glcm_2d[i, j] * np.log2(glcm_2d[i, j])return entropyentropy = calculate_entropy(glcm)# 打印GLCM特征值
print("=" * 20)
print("GLCM纹理特征:")
print(f"对比度:{contrast:.4f}(值越大,纹理越清晰)")
print(f"相关性:{correlation:.4f}(值接近1,纹理越有规律)")
print(f"能量:{energy:.4f}(值越大,纹理越均匀)")
print(f"均匀性:{homogeneity:.4f}(值越大,纹理局部越均匀)")
print(f"熵:{entropy:.4f}(值越大,纹理越复杂)")# 2. 局部二值模式(LBP)特征提取
# 步骤1:计算LBP值(邻域半径1,邻域像素数8)
radius = 1
n_points = 8 * radius
lbp = local_binary_pattern(image, n_points, radius, method='uniform') # uniform方法减少特征维度
# 步骤2:计算LBP直方图(反映纹理分布)
lbp_hist, _ = np.histogram(lbp.ravel(), bins=np.arange(0, n_points + 3), range=(0, n_points + 2))
lbp_hist = lbp_hist.astype("float")
lbp_hist /= (lbp_hist.sum() + 1e-6) # 归一化(避免除以0)
# 显示LBP图像(将LBP值映射到0-255便于显示)
lbp_normalized = cv2.normalize(lbp, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)
cv2.imshow('LBP Image', lbp_normalized)
cv2.imwrite('lbp_image.jpg', lbp_normalized)
# 打印LBP直方图前5个值
print("=" * 20)
print("LBP纹理特征(归一化直方图前5个值):")
for i in range(5):print(f"bin_{i}:{lbp_hist[i]:.4f}")# 3. Gabor滤波器纹理特征提取
def create_gabor_kernel(theta=0):"""创建Gabor滤波器核(参数:方向theta,单位弧度)"""sigma = 2.0 # 高斯标准差lambda_ = 8.0 # 正弦波波长gamma = 0.5 # 空间纵横比psi = 0 # 相位偏移ksize = 31 # 卷积核大小(奇数)kernel = cv2.getGaborKernel((ksize, ksize), sigma, theta, lambda_, gamma, psi, ktype=cv2.CV_32F)return kernel
# 步骤1:创建不同方向的Gabor核(0°、45°、90°、135°)
thetas = [0, np.pi/4, np.pi/2, 3*np.pi/4]
gabor_images = []
for theta in thetas:kernel = create_gabor_kernel(theta)# 步骤2:用Gabor核卷积图像(提取对应方向的纹理)gabor_img = cv2.filter2D(image, cv2.CV_8UC3, kernel)gabor_images.append(gabor_img)# 显示各方向Gabor滤波结果direction = int(theta * 180 / np.pi)cv2.imshow(f'Gabor Filter (Direction {direction}°)', gabor_img)cv2.imwrite(f'gabor_{direction}deg.jpg', gabor_img)
# 等待按键关闭窗口
print("=" * 20)
print("Gabor滤波结果已保存,按任意键关闭窗口...")
cv2.waitKey(0)
cv2.destroyAllWindows()
代码运行后,如下
4、简单分析
首先是基于灰度共生矩阵(GLCM)的代码、实验结果及分析:
分析:先将灰度图生成指定距离和角度的 GLCM 矩阵,用graycoprops直接计算对比度、相关性等支持特征,再通过自定义函数按熵公式计算纹理复杂度,最后打印所有特征值来量化纹理属性。
其次是基于局部二值模式(LBP)的代码、实验结果及分析:
分析:以指定半径和邻域像素数计算图像 LBP 值,对 LBP 结果求直方图并归一化,将 LBP 值映射到 0-255 后显示保存图像,同时打印直方图前 5 个值来反映纹理分布特征。
最后是基于Gabor 滤波器的代码、实验结果及分析:
分析:先定义函数生成含高斯、波长等参数的 Gabor 核,创建 4 个不同方向的核并与图像卷积,对每个方向的滤波结果进行显示和保存,最终通过多方向结果提取图像纹理的方向信息。
9、基于 labelimg 的目标检测训练数据集标注
1、安装 labelimg 工具
在 “py39” 虚拟环境中,打开 Anaconda Prompt,输入命令 pip install labelImg 安装 labelimg(若安装失败,可尝试 pip install labelImg -i https://pypi.tuna.tsinghua.edu.cn/simple 用国内源加速);安装完成后,输入 labelImg 命令启动工具,确认界面正常显示(无报错)。
2、标注前准备
整理数据集:创建 “dataset” 文件夹,内部再创建 “images”(存放待标注图像,格式为 JPG/PNG)和 “annotations”(用于保存标注文件)两个子文件夹,将待标注图像(如 “car_01.jpg”“car_02.jpg”,含汽车、行人等目标)放入 “images” 文件夹。
启动 labelimg 后,点击顶部菜单栏 “File”→“Change Save Dir”,选择 “annotations” 文件夹作为标注文件保存路径;点击 “View”,勾选 “Auto Save mode”(自动保存标注)、“Display Labels”(显示已标注标签)、“Advanced Mode”(显示更多标注选项)。
3、标注流程
3.1 加载图像
点击顶部菜单栏 “Open Dir”,选择 “images” 文件夹,工具会自动加载文件夹中的第一张图像;
3.2 创建标注
点击左侧工具栏 “Create RectBox”(或按快捷键 “W”),鼠标拖动在图像目标(如汽车)周围绘制边界框,确保边界框完整包围目标(不超出目标范围,也不遗漏目标部分);
绘制完成后,弹出 “Enter object label” 对话框,输入目标类别(如 “car”,类别名称需统一,避免大小写或拼写差异,如 “Car” 和 “car” 视为不同类别),点击 “OK” 完成单个目标标注;
若图像含多个目标(如同时有 “car” 和 “pedestrian”),重复上述步骤,分别绘制边界框并标注类别;
3.3 检查与修改
若边界框位置不准确,可点击边界框边缘的控制点拖动调整,或按 “D” 键删除错误标注;
标注完成后,可通过顶部工具栏 “Next Image”(快捷键 “D”)切换到下一张图像,重复标注流程;
3.4 保存标注
标注文件会自动保存为 XML 格式(与图像同名,如 “car_01.xml”),存储在 “annotations” 文件夹中,XML 文件包含目标类别、边界框坐标(xmin、ymin、xmax、ymax)、图像尺寸等信息,符合 VOC 数据集格式,可直接用于 YOLO、Faster R-CNN 等目标检测模型训练。
标注文件检查,如下图,进入查看对应XML文件,以第一张图标注文件为例查看内容:
4、标注质量检查
标注完成后,随机抽取 10%-20% 的标注文件和对应图像进行检查:
准确性:边界框是否准确包围目标(无 “漏标”“多标”,类别标签无错误);
一致性:同一类目标的标注标准是否统一(如 “car” 类是否包含所有车辆,无将 “truck” 误标为 “car”);
完整性:图像中所有目标是否均被标注(无遗漏关键目标,如小尺寸行人未标注);
若发现问题,需返回 labelimg 修正标注,确保数据集质量符合模型训练要求。