1 实验介绍
近年来,世界各国对于海洋鱼类资源的重视程度与日俱增。海洋鱼类资源不仅具有⼀定的食用价值,同时也具有较高的药用价值。在鱼类资源的开发利用中,需要对鱼类进行识别,但由于海洋鱼种类繁多,外形相似,且海底拍摄环境亮度低、场景模糊,导致人工进行鱼类资源识别较为困难。
针对上述问题,本实验利用卷积神经网络构建深度学习模型进行高质量特征的自动提取,以提高海洋鱼类识别的准确率。实验所用数据集是由台湾电力公司、台湾海洋研究所和垦丁国家公园在2010年10月1日至2013年9月30日期间,于台湾南湾海峡、兰屿岛和胡比湖的⽔下观景台收集的鱼类图像数据集,包含23类鱼种,共有27370张鱼的图像。

本实验所构建的模型在测试数据集上的Top-1准确率达到了99.27% ,模型对海洋鱼类的识别准确率超过⼈眼,已初步具备实用价值。
2 数据准备
2.1 解压数据
将数据集压缩⽂件解压到实验数据对应的⽂件夹下,同时创建类别字典,将⻥类标签与类别名相对应。
SRC_PATH = "./data/data14492/fish_image23.zip" # 压缩包路径
DST_PATH = "./data" # 解压路径
DATA_PATH = DST_PATH + "/fish_image" # 实验数据集路径
INFER_LIST = [("./work/pm.jpg", "Pomacentrus moluccensis"),
("./work/ac.jpg", "Amphiprion clarkii"),
("./work/a.jpg", "Myripristis kuntee"),
("./work/b.jpg", "Amphiprion clarkii")] # 预测数据
MODEL_PATH = "GoogLeNet.pdparams" # 模型参数保存路径
save_dir="./save"LAB_DICT = {
'fish_1': 'Dascyllus reticulatus', 'fish_2': 'Plectroglyphidodon dickii',
'fish_3': 'Chromis chrysura', 'fish_4': 'Amphiprion clarkii',
'fish_5': 'Chaetodon lunulatus', 'fish_6': 'Chaetodon trifascialis',
'fish_7': 'Myripristis kuntee', 'fish_8': 'Acanthurus nigrofuscus',
'fish_9': 'Hemigymnus fasciatus', 'fish_10': 'Neoniphon sammara',
'fish_11': 'Abudefduf vaigiensis', 'fish_12': 'Canthigaster valentini',
'fish_13': 'Pomacentrus moluccensis', 'fish_14': 'Zebrasoma scopas',
'fish_15': 'Hemigymnus melapterus', 'fish_16': 'Lutjanus fulvus',
'fish_17': 'Scolopsis bilineata', 'fish_18': 'Scaridae',
'fish_19': 'Pempheris vanicolensis', 'fish_20': 'Zanclus cornutus',
'fish_21': 'Neoglyphidodon nigroris', 'fish_22': 'Balistapus undulatus',
'fish_23': 'Siganus fuscescens'} # 用于将文件名和标签相对应
if not os.path.isdir(DATA_PATH):
z = zipfile.ZipFile(SRC_PATH, "r") # 打开压缩文件,创建zip对象
z.extractall(path=DST_PATH) # 解压zip文件至目标路径
z.close()
print("数据集解压完成!")
2.2 划分训练集和测试集
将原始数据集按9:1的⽐例划分为训练集和测试集,其中训练集用于训练模型参数,训练完指定的轮数后,使用测试集检验模型的泛化能力。
type_num, lab_dict = 0, {
} # 方便动物类别在字符型和整型之间转换
train_list, test_list = [], [] # 存放数据的路径及标签的映射关系
file_folders = os.listdir(DATA_PATH) # 统计数据集下的文件夹
for folder in file_folders:
lab_dict[str(type_num)] = LAB_DICT[folder] # 记录标签和数字代号的对应关系
imgs = os.listdir(os.path.join(DATA_PATH, folder))
for idx, img in enumerate(imgs):
path = os.path.join(DATA_PATH, folder, img)
if idx % 10 == 0: # 按照1:9的比例划分数据集
test_list.append([path, type_num])
else:
train_list.append([path, type_num])
type_num += 1
2.3 定义数据读取与处理方式
通过继承 paddle.io.Dataset 类自定义数据集类 MyDataset ,对传⼊的数据列表进行随机打乱,使用 ToTensor 接口对数据进行转换,以匹配数据馈送格式,并对图像的三通道分别进⾏标准化。在 data_mapper 中进行了图像的缩放、转换为 numpy 数组、转置和归一化等操作。确保这些处理与模型的期望输入一致,否则可能会导致训练问题,完整类定义如下:
class MyDataset(Dataset):
''' 自定义的数据集类 '''
def __init__(self, label_list, transform):
'''
* `label_list`: 标签与文件路径的映射列表
* `transform`: 数据处理函数
'''
super(MyDataset, self).__init__()
random.shuffle(label_list) # 打乱映射列表
self.label_list = label_list
self.transform = transform
def __getitem__(self, index):
''' 根据位序获取对应数据 '''
img_path, label = self.label_list[index]
img = self.transform(img_path)
return img, int(label)
def __len__(self):
''' 获取数据集样本总数 '''
return len(self.label_list)
def _load_img(self, path):
"""
从磁盘读取图片
"""
img = Image.open(path)
if img.mode != 'RGB':
img = img.convert('RGB')
img = img.resize((224, 224), Image.ANTIALIAS)
return img
def data_mapper(img_path, show=False):
''' 图像处理函数 '''
img = Image.open(img_path)
if show: # 展示图像
display(img)
# 将其缩放为224*224的高质量图像:
img = img.resize((224, 224), Image.ANTIALIAS)
# 把图像变成一个numpy数组以匹配数据馈送格式:
img = np.array(img).astype("float32")
# 将图像矩阵由“rgb,rgb,rbg...”转置为“rr...,gg...,bb...”:
img = img.transpose((2, 0, 1))
# 将图像数据归一化,并转换成Tensor格式:
img = paddle.to_tensor(img / 255.0)
return img
3 实验过程
3.1 模型选择
本次实验识别的对象为彩色图,尺⼨为224x224 ,相对于其他简单的神经网络模型,本实验选择使用效果更好、结构更为复杂的AlexNet与GoogLeNet模型完成分类任务。
3.1.1 AlexNet
AlexNet 由 Alex Krizhevsky 等 人 于 2012 年 在 论 文 ImageNet Classification w

最低0.47元/天 解锁文章
225

被折叠的 条评论
为什么被折叠?



