【yolov8分类任务-全流程】【公开数据白内障-101:101例白内障手术的视频数据集】

news2024/12/23 15:31:17

文章目录

  • 1.公开数据集
    • 1.1.白内障-101:数据集文件结构
      • 1.1.1.视频文件
      • 1.1.2.注释文件
        • (1)videos.csv
        • (2) phases.csv
        • (3)annotations.csv
    • 1.2. 数据处理
      • 1.2.1.抽帧脚本全部代码(每行都有注释)
      • 1.2.2.分类任务划分数据集脚本
  • 2.yolov8分类任务训练
    • 2.1.配环境
    • 2.2.训练命令:
    • 2.3.训练结果

1.公开数据集

白内障-101:101例白内障手术的视频数据集

摘要
白内障手术是眼科领域最常进行的显微手术之一。这种手术背后的目标是用人造晶状体代替人眼晶状体,这是由于衰老而经常需要的干预。整个手术是在显微镜下进行的,但共同安装的摄像机可以记录和存档手术过程。目前,录制的视频以术后方式用于记录和培训。录制白内障视频的另一个好处是,它们能够进行视频分析(即手动和/或自动视频内容分析),以调查与医学相关的研究问题(例如,并发症的原因)。然而,这需要一个医疗多媒体信息系统,该系统根据现有数据进行训练和评估,而这些数据目前尚未公开。在这项工作中,我们提供了一个公共视频数据集,其中包含 101 例白内障手术,这些手术由四位不同的外科医生在 9 个月内进行。这些外科医生分为中等经验和经验丰富的外科医生(助理医生与高级医生),为基于经验的视频分析提供了基础。所有视频均由高级眼科医生用准标准化操作阶段进行注释。

1.1.白内障-101:数据集文件结构

在这里插入图片描述

1.1.1.视频文件

在这里插入图片描述

视频文件存储在 videos 子目录中,文件名遵循以下模式:

case_videoID.mp4

例如,视频 269 的文件名为 case_269.mp4

视频文件使用 H.264/AVC 编解码器编码,帧率为 25 帧每秒,分辨率为 720x540 像素。提供的视频的平均持续时间约为 12500 帧(8.3 分钟)。

1.1.2.注释文件

注释以三个以分号分隔的值文件提供,每个文件都包含描述字段的标题行。

(1)videos.csv

在这里插入图片描述

包含有关整个视频文件的元数据,包括所有整数字段:

  • 视频 ID
  • 视频帧数
  • 帧率(25)
  • 手术医生 ID(1-4)
  • 手术医生的经验水平(1 = 低,2 = 高)

下表显示了每位手术医生的视频分布以及每个经验水平的视频数量。

手术医生 ID视频
125
224
332
420
经验水平视频
1(低)45
2(高)56
(2) phases.csv

在这里插入图片描述

描述白内障手术的十个准标准操作阶段(更多信息请参阅上述引用的论文)。这两个字段是:

  • 阶段 ID(1-10 的整数)
  • 阶段名称(字符串)
(3)annotations.csv

在这里插入图片描述

包含所有提供视频的操作阶段边界的专家注释。由于注释工具的使用,仅注释了操作阶段的起始点,手动选择时间点的准确性不超过 +/- 1 秒(+/- 25 帧)。尽管如此,注释以帧分辨率提供,以便使用该数据集进行基于帧的评估时进行比较。

CSV 文件的每一行(除了标题行)描述了一个操作阶段注释的起始点,具有以下所有整数字段:

  • 视频 ID(与 videos.csv 中的 ID 匹配)
  • 表示操作阶段起始点的帧编号(从零开始),该帧延伸到下一个注释或同一视频的结束
  • 阶段 ID(与 phases.csv 中的 ID 匹配)

CSV 文件中的行按(视频 ID,帧编号)的词典顺序排序。

请注意所选择的注释过程的以下后果:

  1. 给定视频的第一个注释(第一个操作阶段的开始)之前的视频段实际上未被注释,即未分配给任何操作阶段。
  2. 给定视频的最后一个注释开始的视频段实际上延伸到视频的结束,尽管注释的操作阶段实际上可能会提前结束。然而,视频获取过程表明,手术末期的这段“超出阶段”的时间通常只有几秒钟。
  3. 同一视频中可能会连续出现相同操作阶段的注释,因为同一阶段可能会重复或分成也由医学专家注释的子阶段。事后已整合子阶段以符合 phases.csv 中描述的准标准阶段。

最后,请注意,phases.csv 中定义的操作阶段的线性顺序通常在手术中不严格遵循,主要有两个原因:

  • 第2阶段(注入粘性剂)通常在每次白内障手术中发生两次,并且两个视频片段与相同的阶段 ID 进行了注释,因为从视觉角度通常无法区分它们。
  • 手术医生(特别是经验较少的医生)有时可能不得不重复某些阶段或阶段序列。

1.2. 数据处理

1.2.1.抽帧脚本全部代码(每行都有注释)

  • 对101例白内障手术的视频数据集视频进行处理,根据提供的标签CSV文件中的分类信息,从每个视频中抽取帧,并将这些帧按照YOLO分类任务的不同类别进行分类。每个类别将被放置在不同的文件夹中,并且每个帧的文件名将包含相关信息。

  • 鉴于从视频中每秒抽取25帧会导致数据重复过多,并且产生的数据量超过一百万张图片,因此决定调整抽帧策略,每秒仅抽取2帧。这样既可以有效减少数据量,也有助于降低重复数据的比例。

  • 抽帧结果示例:
    在这里插入图片描述
    在这里插入图片描述

脚本名Script.py

import os
import cv2
import pandas as pd

# 设置 CSV 文件路径和视频文件目录
annotations_csv_path = 'annotations.csv'  # 您的 CSV 文件路径
phases_csv_path = 'phases.csv'  # phases.csv 文件路径
video_dir = 'videos'  # 视频文件所在的目录

# 设置输出文件夹路径
output_dir = 'output_frames10'

# 如果输出文件夹不存在,创建它
if not os.path.exists(output_dir):
    os.makedirs(output_dir)

# 读取 phases.csv 文件,创建阶段 ID 到含义的字典
phases_df = pd.read_csv(phases_csv_path, sep=';')
phases_dict = dict(zip(phases_df['Phase'], phases_df['Meaning']))

# 读取 annotations.csv 文件
df = pd.read_csv(annotations_csv_path, sep=';')

# 遍历 annotations.csv 文件中的每一行
for index, row in df.iterrows():
    video_id = row['VideoID']
    start_frame_no = row['FrameNo']
    phase_id = row['Phase']
    phase_meaning = phases_dict.get(phase_id, f'Phase_{phase_id}')
    print(phase_meaning)
    # 查找下一个阶段的帧编号
    if index + 1 < len(df) and df.iloc[index + 1]['VideoID'] == video_id:
        end_frame_no = df.iloc[index + 1]['FrameNo']
    else:
        # 如果没有下一个阶段,则将结束帧设置为视频的最后一帧
        video_cap = cv2.VideoCapture(os.path.join(video_dir, f'case_{video_id}.mp4'))
        end_frame_no = int(video_cap.get(cv2.CAP_PROP_FRAME_COUNT))
        video_cap.release()

    # 构建视频文件路径
    video_file_path = os.path.join(video_dir, f'case_{video_id}.mp4')

    # 检查视频文件是否存在
    if not os.path.exists(video_file_path):
        print(f'Video file not found: {video_file_path}')
        continue

    # 打开视频文件
    video_cap = cv2.VideoCapture(video_file_path)

    # 从起始帧到结束帧的范围读取帧
    for current_frame_no in range(int(start_frame_no), int(end_frame_no),12):
        # 设置视频的位置到指定的帧编号
        video_cap.set(cv2.CAP_PROP_POS_FRAMES, current_frame_no)

        # 读取帧
        success, frame = video_cap.read()

        # 如果读取成功
        if success:
            # 创建输出文件夹,按 phase_meaning 创建子目录
            phase_folder = os.path.join(output_dir, phase_meaning)
            # video_folder = os.path.join(phase_folder, f'video_{video_id}')
            if not os.path.exists(phase_folder):
                os.makedirs(phase_folder)

            # 构建输出文件路径
            output_file_path = os.path.join(phase_folder, f'case_{video_id}_frame_{current_frame_no}_phase_{phase_meaning}.jpg')

            # 保存帧到输出文件
            cv2.imwrite(output_file_path, frame)
            print(f'Saved frame: {output_file_path}')
        else:
            print(f'Failed to read frame: {current_frame_no} from video: {video_file_path}')

    # 关闭视频文件
    video_cap.release()

print('Finished extracting frames.')

1.2.2.分类任务划分数据集脚本

脚本名:cla_split.py

import os
import random
import shutil
from shutil import copy2

def data_set_split(src_data_folder, target_data_folder, train_scale=0.8, val_scale=0.1, test_scale=0.1):
	#读取源数据文件夹,生成划分好的文件夹,分为trian、val、test三个文件夹
    print("开始数据集划分")
    class_names = os.listdir(src_data_folder)
    split_names = ['train', 'val', 'test']
    for split_name in split_names:
        split_path = os.path.join(target_data_folder, split_name)
        if os.path.isdir(split_path):
            pass
        else:
            os.mkdir(split_path)
        for class_name in class_names:
            class_split_path = os.path.join(split_path, class_name)
            if os.path.isdir(class_split_path):
                pass
            else:
                os.mkdir(class_split_path)

    for class_name in class_names:
        current_class_data_path = os.path.join(src_data_folder, class_name)
        current_all_data = os.listdir(current_class_data_path)
        current_data_length = len(current_all_data)
        current_data_index_list = list(range(current_data_length))
        random.shuffle(current_data_index_list)

        train_folder = os.path.join(os.path.join(target_data_folder, 'train'), class_name)
        val_folder = os.path.join(os.path.join(target_data_folder, 'val'), class_name)
        test_folder = os.path.join(os.path.join(target_data_folder, 'test'), class_name)
        train_stop_flag = current_data_length * train_scale
        val_stop_flag = current_data_length * (train_scale + val_scale)
        current_idx = 0
        train_num = 0
        val_num = 0
        test_num = 0
        for i in current_data_index_list:
            src_img_path = os.path.join(current_class_data_path, current_all_data[i])
            if current_idx <= train_stop_flag:
                copy2(src_img_path, train_folder)
                train_num = train_num + 1
            elif (current_idx > train_stop_flag) and (current_idx <= val_stop_flag):
                copy2(src_img_path, val_folder)
                val_num = val_num + 1
            else:
                copy2(src_img_path, test_folder)
                test_num = test_num + 1
            
            current_idx = current_idx + 1

        print("*********************************{}*************************************".format(class_name))
        print("{}类按照{}:{}:{}的比例划分完成,一共{}张图片".format(class_name, train_scale, val_scale, test_scale, current_data_length))
        print("训练集{}:{}张".format(train_folder, train_num))
        print("验证集{}:{}张".format(val_folder, val_num))
        print("测试集{}:{}张".format(test_folder, test_num))


if __name__ == '__main__':
    src_data_folder = "/home/hadoop/output_frames10/"
    target_data_folder = "/home/hadoop/splitData_frames10/"
    data_set_split(src_data_folder, target_data_folder)

划分结果示例:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.yolov8分类任务训练

2.1.配环境

就不赘述了。
在这里插入图片描述

2.2.训练命令:

yolo classify train data="splitData_frames10" model=yolov8s-cls.pt epochs=100 device=0,1,2,3 batch = 128

开始训练
在这里插入图片描述

2.3.训练结果

示例图:
在这里插入图片描述
推理示例图:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1676817.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【教程】Jetson安装PyQt5和CUDA版OpenCV

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;请不吝给个[点赞、收藏、关注]哦~ 安装PyQt5 注意目前似乎只支持Python3.6&#xff01;&#xff01;&#xff01; sudo apt install pyqt5* -y sudo apt-get install python3-pyqt…

Java | Leetcode Java题解之第89题格雷编码

题目&#xff1a; 题解&#xff1a; class Solution {public List<Integer> grayCode(int n) {List<Integer> ret new ArrayList<Integer>();for (int i 0; i < 1 << n; i) {ret.add((i >> 1) ^ i);}return ret;} }

每日一题12:Pandas:数据重塑-融合

一、每日一题 解答&#xff1a; import pandas as pddef meltTable(report: pd.DataFrame) -> pd.DataFrame:reshaped_report report.melt(id_varsproduct, var_namequarter, value_namesales)return reshaped_report 题源&#xff1a;Leetcode 二、总结 melt()函数是Pa…

Python 机器学习 基础 之 监督学习 [线性模型] 算法 的简单说明

Python 机器学习 基础 之 监督学习 [线性模型] 算法 的简单说明 目录 Python 机器学习 基础 之 监督学习 [线性模型] 算法 的简单说明 一、简单介绍 二、监督学习 算法 说明前的 数据集 说明 三、监督学习 之 线性模型 算法 1、用于回归的线性模型 2、线性回归&#xff0…

SpringCloud------Feign,Geteway

Feign 所以我们使用一门新的技术&#xff1a;声明式的http客户端Feign 第一步&#xff1a;引入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency> …

Vue 封装axios

【一】准备工作 &#xff08;1&#xff09;安装必要插件 安装Axios&#xff0c;这是必要的。默认最新版 npm install axios -S 或 cnpm install axios -S安装elementui-plus&#xff0c;用于提示信息 npm install element-plus --save # 或 cnpm install element-plus --s…

Selenium自动操作鼠标的方法及示例(鼠标左右键单击、左键双击、拖动等)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

五分钟“手撕”时间复杂度与空间复杂度

目录 一、算法效率 什么是算法 如何衡量一个算法的好坏 算法效率 二、时间复杂度 时间复杂度的概念 大O的渐进表示法 推导大O阶方法 常见时间复杂度计算举例 三、空间复杂度 常见时间复杂度计算举例 一、算法效率 什么是算法 算法(Algorithm)&#xff1a;就是定…

BakedSDF: Meshing Neural SDFs for Real-Time View Synthesis 论文阅读

&#xff08;水一篇博客&#xff09; 项目主页 BakedSDF: Meshing Neural SDFs for Real-Time View Synthesis 作者介绍 是 Mildenhall 和 Barron 参与的工作&#xff08;都是谷歌的&#xff09;&#xff0c;同时一作是 Lipman 的学生&#xff0c;VolSDF 的一作。本文引用…

234.回文链表

给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为 回文链表 。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,2,1] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;head …

项目管理-案例重点知识(风险管理)

项目管理 : 每天进步一点点~ 活到老&#xff0c;学到老 ヾ(◍∇◍)&#xff89;&#xff9e; 何时学习都不晚&#xff0c;加油 二、风险管理 案例重点 重点内容&#xff1a; &#xff08;1&#xff09;风险划分 &#xff08;2&#xff09;SWOT 分析&#xff0c;提示清单 …

5.10.10 用于图像识别的深度残差学习

1. 介绍 深度卷积神经网络为图像分类带来了一系列突破。深度网络自然地以端到端的多层方式集成低/中/高级特征和分类器&#xff0c;并且特征的“级别”可以通过堆叠层的数量&#xff08;深度&#xff09;来丰富。 学习更好的网络是否像堆叠更多层一样容易&#xff1f; 这个问…

RK3568平台开发系列讲解(SPI篇)SPI数据的传输

🚀返回专栏总目录 文章目录 一、数据结构1.1、spi_transfer 结构体1.2、spi_message二、数据发送程序分析沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 参考资料: spi_transferspi_message一、数据结构 spi 数据传输主要使用了 spi_message 和 spi_transfer 结构…

【计网】TCP中的滑动窗口

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;日常聊聊 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 正文 工作原理如下&#xff1a; 结语 我的其他博客 正文 TCP&#xff08;传输控制协议&#xff09;中的滑动窗口是一种用于流量控制和拥…

数字集成电路物理设计[陈春章]——知识总结与精炼01

第一章 集成电路物理设计方法 1.1 数字集成电路设计挑战 1.2 数字集成电路设计流程 前两节内容讲述的是数字集成电路发展与流程&#xff0c;知识体系比较宏观和简单&#xff0c;请读者自行了解即可。 1.3 数字集成电路设计收敛 实现设计收敛任务&#xff1a;①数据系统;②优…

SQL——SERVER的建表主要操作

目录 一&#xff1a;数据存储问题 1.表的相关数据 2.表&#xff0c;字段&#xff0c;记录 二&#xff1a;建表 1.创建表头 2. 数据类型 3.保存数据 4.数据冗余 5.使用命令重置表 7.设置主键 一&#xff1a;数据存储问题 1.表的相关数据 表是数据库的基本单位&…

FreeRTOS学习 -- 列表和列表项

列表和列表项是 FreeRTOS 的一个数据结构&#xff0c;FreeRTOS 大量使用到了列表和列表项。 一、什么是列表和列表项 1、列表 列表是 FreeRTOS 中的一个数据结构&#xff0c;被用来跟踪 FreeRTOS 中的任务。与列表相关的全部东西都在文件 list.c 和 list.h中。 List_t 结构体…

web入门——导航栏

本专栏内容代码来自《响应式web&#xff08;HTML5CSS3Bootstrap&#xff09;》教材。 导航栏 实现代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content&…

【JavaEE】Spring Web MVC入门:掌握Spring的MVC框架基础

目录 Spring Web MVC什么是Spring Web MVCMVC 定义什么是Spring MVC 学习Spring MVC1. 项目准备2. 建立连接 Spring Web MVC 什么是Spring Web MVC 官⽅对于 Spring MVC 的描述是这样的&#xff1a; Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架&#xff0c;从⼀…

2024年小学生古诗文大会备考:吃透历年真题和知识点(持续)

根据往年的安排&#xff0c;2024年小学生古诗文大会预计这个月就将启动。该如何备考2024年小学生古诗文大会呢&#xff1f;根据往期的经验&#xff0c;只要吃透这些真题和背后的知识点&#xff0c;通过上海小学生古诗文大会的初选&#xff08;初赛&#xff09;一点问题都没有。…