YoloV8实战:使用YoloV8实现水下目标检测(RUOD)

2024-04-07 09:36

本文主要是介绍YoloV8实战:使用YoloV8实现水下目标检测(RUOD),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

摘要

水下目标检测技术在生态监测、管道检修、沉船捕捞等任务中发挥着重要作用。常用的检测方法包括高清视像、侧扫声呐等。光学图像检测因高分辨率和灵活性,在近距离检测中优势显著。但水下图像受水体吸收、衰减、光源分布等影响,呈现蓝绿色,且存在低对比度、非均匀光照、模糊、亮斑和高噪声等问题。此外,水下环境复杂,数据集相对较少,目标小且分布密集,重叠遮挡现象常见。现有的检测算法在复杂水下环境中精确度有限。URPC2021和DUO等数据集为水下目标检测研究提供了重要资源。DUO为URPC挑战赛多年数据集的整合,对其中重复数据进行删除,训练集并且对有误的标签进行了重新标注。

下载链接:

https://github.com/xiaoDetection/RUOD

或者
https://aistudio.baidu.com/datasetdetail/216919(这个链接下载速度快,飕飕的)
数据集格式:COCO格式

类别:

holothurian,echinus,scallop,starfish,fish,corals,diver,cuttlefish,turtle,jellyfish10个常见类别

数据集转换与可视化

项目结构如下:

在这里插入图片描述

将数据集转成Yolo格式

代码:

import json
import glob
import os
import shutil
from pathlib import Path
import numpy as np
from tqdm import tqdmdef make_folders(path='./coco/'):# Create foldersif os.path.exists(path):shutil.rmtree(path)  # delete output folderos.makedirs(path)  # make new output folderos.makedirs(path + os.sep + 'labels')  # make new labels folderos.makedirs(path + os.sep + 'images')  # make new labels folderreturn pathdef convert_coco_json(json_dir='./RUOD/RUOD_ANN/'):jsons = glob.glob(json_dir + '*.json')# Import jsonfor json_file in sorted(jsons):fn = 'coco/labels/%s/' % Path(json_file).stem.replace('instances_', '')  # folder namefn_images = 'coco/images/%s/' % Path(json_file).stem.replace('instances_', '')  # folder nameos.makedirs(fn, exist_ok=True)os.makedirs(fn_images, exist_ok=True)with open(json_file) as f:data = json.load(f)print(fn)# Create image dictimages = {'%g' % x['id']: x for x in data['images']}# Write labels filefor x in tqdm(data['annotations'], desc='Annotations %s' % json_file):if x['iscrowd']:continueimg = images['%g' % x['image_id']]h, w, f = img['height'], img['width'], img['file_name']file_path = './RUOD/RUOD_pic/' + fn.split('/')[-2] + "/" + f# The Labelbox bounding box format is [top left x, top left y, width, height]box = np.array(x['bbox'], dtype=np.float64)box[:2] += box[2:] / 2  # xy top-left corner to centerbox[[0, 2]] /= w  # normalize xbox[[1, 3]] /= h  # normalize yif (box[2] > 0.) and (box[3] > 0.):  # if w > 0 and h > 0with open(fn + Path(f).stem + '.txt', 'a') as file:file.write('%g %.6f %.6f %.6f %.6f\n' % (x['category_id'] - 1, *box))file_path_t = fn_images + fprint(file_path, file_path_t)shutil.copy(file_path, file_path_t)convert_coco_json()

可视化

import cv2
import osdef draw_box_in_single_image(image_path, txt_path):# 读取图像image = cv2.imread(image_path)# 读取txt文件信息def read_list(txt_path):pos = []with open(txt_path, 'r') as file_to_read:while True:lines = file_to_read.readline()  # 整行读取数据if not lines:break# 将整行数据分割处理,如果分割符是空格,括号里就不用传入参数,如果是逗号, 则传入‘,'字符。p_tmp = [float(i) for i in lines.split(' ')]pos.append(p_tmp)  # 添加新读取的数据# Efield.append(E_tmp)passreturn pos# txt转换为boxdef convert(size, box):xmin = (box[1]-box[3]/2.)*size[1]xmax = (box[1]+box[3]/2.)*size[1]ymin = (box[2]-box[4]/2.)*size[0]ymax = (box[2]+box[4]/2.)*size[0]box = (int(xmin), int(ymin), int(xmax), int(ymax))return boxpos = read_list(txt_path)print(pos)tl = int((image.shape[0]+image.shape[1])/2)lf = max(tl-1,1)for i in range(len(pos)):label = str(int(pos[i][0]))print('label is '+label)box = convert(image.shape, pos[i])image = cv2.rectangle(image,(box[0], box[1]),(box[2],box[3]),(0,0,255),2)cv2.putText(image,label,(box[0],box[1]-2), 0, 1, [0,0,255], thickness=2, lineType=cv2.LINE_AA)passif pos:cv2.imwrite('./VOCData/see_images/{}.png'.format(image_path.split('\\')[-1][:-4]), image)else:print('None')print('./VOCData/see_images/{}.png'.format(image_path.split('\\')[-1][:-4]))# cv2.imshow("images", image)# cv2.waitKey(0)# cv2.destroyAllWindows()img_folder = "./coco/images/train"
img_list = os.listdir(img_folder)
img_list.sort()label_folder = "./coco/labels/train"
label_list = os.listdir(label_folder)
label_list.sort()
if not os.path.exists('./VOCData/see_images'):os.makedirs('./VOCData/see_images')
for i in range(len(img_list)):image_path = img_folder + "\\" + img_list[i]txt_path = label_folder + "\\" + label_list[i]draw_box_in_single_image(image_path, txt_path)

在这里插入图片描述

在这里插入图片描述

训练

完成上面的数据准备工作就可以开启训练了。将得到的数据集放到datasets文件夹下面,在项目的根目录新建coco.yaml,如下图:
在这里插入图片描述

coco.yaml插入内容:

train: ./coco/images/train # train images
val: ./coco/images/test # val imagesnames: ['holothurian', 'echinus', 'scallop', 'starfish','fish','corals','diver','cuttlefish','turtle','jellyfish']

然后新建train.py,插入内容:

from ultralytics import YOLO
import osif __name__ == '__main__':model = YOLO(model="ultralytics/cfg/models/v8/yolov8s.yaml")  # 从头开始构建新模型print(model)# Use the modelresults = model.train(data="coco.yaml", patience=0, epochs=50, device='0', batch=16, seed=42)  # 训练模

在这里插入图片描述
然后,运行train.py,就可以开启训练了!如下图:
在这里插入图片描述

测试结果

在这里插入图片描述

验证

代码如下:

from ultralytics import YOLOif __name__ == '__main__':# Load a model# model = YOLO('yolov8m.pt')  # load an official modelmodel = YOLO('runs/detect/train/weights/best.pt')  # load a custom model# Validate the modelmetrics = model.val(split='val',save_json=True)  # no arguments needed, dataset and settings remembered

split参数设置为val,则测试val指向数据集,如果设置为test,则测试test指向的数据集。本次没有test,所以我们只能设置为val。

save_json设置为True,则会保存类似coco格式的json文件。如下图:

在这里插入图片描述

测试

新建test.py,插入代码:

from ultralytics import YOLOif __name__ == '__main__':# Load a model# model = YOLO('yolov8m.pt')  # load an official modelmodel = YOLO('runs/detect/train/weights/best.pt')  # load a custom modelresults = model.predict(source="ultralytics/assets", device='0', visualize=True, save=True)  # predict on an imageprint(results)

其他的参数就不解释了!说一说YoloV8里没有介绍,或者难以理解的参数。
visualize设置为True,可视化每层的特征。设置后,会生成每层的特征,如下图:
在这里插入图片描述
保存的路径:
在这里插入图片描述
stage后面的数字代表的是YoloV8网络中的层,里面有两种文件,png文件是抽取的特征组成的图片,npy文件则是保存了所有的特征信息。读取方式:

#导入所需的包
import numpy as np#导入npy文件路径位置
test = np.load('runs/detect/predict/zidane/stage2_C2f_features.npy')print(test.shape[0])

总结

本次实战讲解了RUOD数据集的使用,以及训练、验证相关的知识。不知道还有没有遗漏的,欢迎大家补充。

完整的代码:


这篇关于YoloV8实战:使用YoloV8实现水下目标检测(RUOD)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/882242

相关文章

MyBatis分页查询实战案例完整流程

《MyBatis分页查询实战案例完整流程》MyBatis是一个强大的Java持久层框架,支持自定义SQL和高级映射,本案例以员工工资信息管理为例,详细讲解如何在IDEA中使用MyBatis结合Page... 目录1. MyBATis框架简介2. 分页查询原理与应用场景2.1 分页查询的基本原理2.1.1 分

Spring Security简介、使用与最佳实践

《SpringSecurity简介、使用与最佳实践》SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,本文给大家介绍SpringSec... 目录一、如何理解 Spring Security?—— 核心思想二、如何在 Java 项目中使用?——

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

Nginx部署HTTP/3的实现步骤

《Nginx部署HTTP/3的实现步骤》本文介绍了在Nginx中部署HTTP/3的详细步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前提条件第一步:安装必要的依赖库第二步:获取并构建 BoringSSL第三步:获取 Nginx

springboot中使用okhttp3的小结

《springboot中使用okhttp3的小结》OkHttp3是一个JavaHTTP客户端,可以处理各种请求类型,比如GET、POST、PUT等,并且支持高效的HTTP连接池、请求和响应缓存、以及异... 在 Spring Boot 项目中使用 OkHttp3 进行 HTTP 请求是一个高效且流行的方式。

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

Java实现字节字符转bcd编码

《Java实现字节字符转bcd编码》BCD是一种将十进制数字编码为二进制的表示方式,常用于数字显示和存储,本文将介绍如何在Java中实现字节字符转BCD码的过程,需要的小伙伴可以了解下... 目录前言BCD码是什么Java实现字节转bcd编码方法补充总结前言BCD码(Binary-Coded Decima

SpringBoot全局域名替换的实现

《SpringBoot全局域名替换的实现》本文主要介绍了SpringBoot全局域名替换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录 项目结构⚙️ 配置文件application.yml️ 配置类AppProperties.Ja

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC