目录
赛题地址:农民身份识别挑战赛
数据集如图:
1 图像特征统计(传统方法)个人解读
1.1 导入相关模块
import os, sys, glob, argparse
from PIL import Image
import cv2
import pandas as pd
import numpy as np
from tqdm import tqdm
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_predict
from sklearn.metrics import classification_report
os模块
- 路径操作:os.path子库,处理文件路径及信息
- 进程管理:启动系统中其他程序
- 环境参数:获得系统软件硬件信息等环境参数
python标准库 —— os模块_python os库_wakeyo_J的博客-CSDN博客
sys模块
- sys模块是最常用的和python解释器交互的模块,sys模块可供访问由解释器(interpreter)使用或维护的变量和与解释器进行交互的函数。
sys
模块提供了许多函数和变量来处理 Python 运行时环境的不同部分。
Python 标准库之 sys 模块详解_python sys模块详解_轩辕御龙的博客-CSDN博客
glob模块
- glob模块可以使用Unix shell风格的通配符匹配符合特定格式的文件和文件夹,跟windows的文件搜索功能差不多。glob模块并非调用一个子shell实现搜索功能,而是在内部调用了os.listdir()和fnmatch.fnmatch()。
python中glob库的使用_python glob_C小C的博客-CSDN博客
PIL模块
argparse模块
- argparse库是用来给python脚本传入参数的库
argparse库教程(超易懂)Fan19zju的博客-CSDN博客
tqdm模块
- Tqdm 是一个快速,可扩展的Python进度条,可以在 Python 长循环中添加一个进度提示信息,用户只需要封装任意的迭代器 tqdm(iterator)。
python进度条库tqdm详解 - 知乎 (zhihu.com)
1.2 数据收集与准备
# 读取数据集
train_path = glob.glob('./农民身份识别挑战赛公开数据/train/*')
test_path = glob.glob('./农民身份识别挑战赛公开数据/test/*')
train_path.sort()
test_path.sort()
train_df = pd.read_csv('农民身份识别挑战赛公开数据/train.csv')
train_df = train_df.sort_values(by='name')
train_label = train_df['label'].values
glob.glob('./农民身份识别挑战赛公开数据/train/*')
:返回的是一个list列表,包含所有农民身份识别挑战赛公开数据/train
文件夹里的文件路径train_path.sort()
:对train_path列表中的所有路径名进行排序,因为前面的所属文件夹都一样,因此也就是对图片名称进行排序。train_df = train_df.sort_values(by='name')
:对train_df里的数据依照name进行排序。train_label = train_df['label'].values
:获取排序后的label值,此时的label与前面的train_path里的path是一一对应的。
1.3 特征提取
# 读取图像特征
def image_feat(path):
img = cv2.imread(path, 0)
img = img.astype(np.float32)
feat = [
(img != 0).sum(), # 非零像素的数量
(img == 0).sum(), # 零像素的数量
img.mean(), # 平均值
img.std(), # 标准差
len(np.where(img.mean(0))[0]), # 在列方向上平均值不为零的数量
len(np.where(img.mean(1))[0]), # 在行方向上平均值不为零的数量
img.mean(0).max(), # 列方向上的最大平均值
img.mean(1).max() # 行方向上的最大平均值
]
return feat
- 该部分定义的
image_feat()
函数的主要功能是:
1、传入图片路径path
2、将图像数据类型转换为np.float32
,这样可以确保计算过程中的数据精度
3、提取这张图片的相关特征
4、以列表形式返回特征 - 关于
cv2.imread(path, 0)
的第二个参数:
cv2.IMREAD_COLOR:默认参数,读入一副彩色图片,忽略alpha通道,可用1作为实参替代
cv2.IMREAD_GRAYSCALE:读入灰度图片,可用0作为实参替代
cv2.IMREAD_UNCHANGED:顾名思义,读入完整图片,包括alpha通道,可用-1作为实参替代
PS:alpha通道,又称A通道,是一个8位的灰度通道,该通道用256级灰度来记录图像中的透明度复信息,定义透明、不透明和半透明区域,其中黑表示全透明,白表示不透明,灰表示半透明。 np.where(img.mean(0))[0]
:
numpy.where(condition, x, y)
:当满足的时候执行x
,不满足执行y
np.where(condition)
是np.asarray(condition).nonzero()
的简写
python用np.where遍历图像像素(更快的遍历)_np.where 图像像素值_YH_24H的博客-CSDN博客- np.array里的0和1
np.where()[0]
表示行的索引;
np.where()[1]
则表示列的索引。 img != 0
:
网上未找到相关博客,经过个人试验,返回的是一个与灰度图img的shape相同的列表,若img在该位置上的灰度值不为0则是True,否则为False。
1.4 模型训练、评估与优化
# 训练集特征
train_feat = []
for path in tqdm(train_path):
train_feat += [image_feat(path)]
# 测试集特征
test_feat = []
for path in tqdm(test_path):
test_feat += [image_feat(path)]
# 训练集交叉验证
train_pred = cross_val_predict(
KNeighborsClassifier(),
np.array(train_feat),
train_label
)
print(classification_report(train_label, train_pred))
# 模型训练与预测
model = KNeighborsClassifier()
model.fit(
np.array(train_feat),
train_label
)
test_pred = model.predict(np.array(test_feat))
- 利用之前定义的
image_feat
函数对训练集和测试集中每一张图片进行提取特征操作,并分别将提取到的特征收集起来。先使用交叉验证评估模型在训练集上的性能,并打印相应的报告,然后再使用整个训练集对模型进行训练。 - 交叉验证是一种更可靠的评估模型性能的方法,因为它能够更好地利用训练数据,减少因为数据划分而引入的随机性。
cross_val_predict
通常接受以下参数:estimator
: 机器学习模型(例如分类器或回归器)X
: 特征数据,通常是一个二维数组y
: 目标标签,通常是一个一维数组cv
: 交叉验证的迭代器或次数n_jobs
: 并行处理的作业数量(如果可用)
classification_report
是用于分类模型评估的函数,它常用于机器学习任务中,特别是用于多类别分类问题的结果分析和报告生成。接受以下参数:-
y_true
:实际的目标标签
y_pred
:模型预测的目标标签target_names
:类别名称,用于指定每个类别的名称,方便在报告中显示
-
test_pred = model.predict(np.array(test_feat))
中np.array(test_feat)
将test_feat列表转化为np数组:高效计算、确保兼容。
1.5 结果输出
# 生成测试集提交结果
submit = pd.DataFrame(
{
'name': [x.split('/')[-1] for x in test_path],
'label': test_pred
})
submit = submit.sort_values(by='name')
submit.to_csv('submit.csv', index=None)
name
的生成是遍历test_path,即之前生成的训练集图片路径。列表里的元素大概像这样:./农民身份识别挑战赛公开数据/train/abcdefg.jpg
,因此用/
分割,并取最后一个,即:abcdefg.jpg
2 个人总结
- 传统提取图像特征的方法在结果上表现并不好,但是仍然可以有启发作用。
- 通过仔细阅读,我学习到了tqdm以及glob库的使用,特别是glob,极大地方便了我后续读取文件的过程。
- 有关注到这种K最邻近算法模型的构建方法,还有训练集的交叉验证过程,都给了我很大的启发。在此之前,我都是numpy和pandas一条龙,效率低而且缺乏严谨性,花费了很多时间效果却很差。
- 我将自己每一次的学习笔记分享出去,方便你,还有我温习。