修改Egohands公开数据集,用于YOLOv5训练通用手部检测模型

〇、背景:

项目需要,需要利用摄像头对人手进行实时监测,最先考虑到的就是简单易用且高效的YOLOv5,很快找到了公开数据集:Egohands

EgoHands: A Dataset for Hands in Complex Egocentric Interactions | IU Computer Vision Lab

一、Egohands介绍:

EgoHands 数据集包含 48 个 Google Glass 视频,内容涉及两个人之间复杂的第一人称交互。该数据集的主要目的是提供更好的数据驱动方法来理解第一人称计算机视觉中的手。

我下载使用的是[Labeled Data]这个数据集,该存档包含所有带标签的帧,格式为 JPEG 文件 (720x1280px)。 48 个视频中的每个视频都有 100 个标记帧,总共 4,800 个帧。真实标签由每种手型的像素级掩码组成,并以 Matlab 文件形式提供。

由于数据集是用于MATLAB的,所以需要将其转化为YOLOv5可用。

二、数据集转化:

下面的程序主要用于参考,具体使用时需要根据自己情况进行修改。

1,使用程序自动下载、解压并归档数据集

import scipy.io as sio
import numpy as np
import os
import gc
import six.moves.urllib as urllib
import cv2
import time
import xml.etree.cElementTree as ET
import random
import shutil as sh
from shutil import copyfile
import zipfileimport csvdef save_csv(csv_path, csv_content):with open(csv_path, 'w') as csvfile:wr = csv.writer(csvfile)for i in range(len(csv_content)):wr.writerow(csv_content[i])def get_bbox_visualize(base_path, dir):image_path_array = []for root, dirs, filenames in os.walk(base_path + dir):for f in filenames:if(f.split(".")[1] == "jpg"):img_path = base_path + dir + "/" + fimage_path_array.append(img_path)#sort image_path_array to ensure its in the low to high order expected in polygon.matimage_path_array.sort()boxes = sio.loadmat(base_path + dir + "/polygons.mat")# there are 100 of these per folder in the egohands datasetpolygons = boxes["polygons"][0]# first = polygons[0]# print(len(first))pointindex = 0for first in polygons:index = 0font = cv2.FONT_HERSHEY_SIMPLEXimg_id = image_path_array[pointindex]img = cv2.imread(img_id)img_params = {}img_params["width"] = np.size(img, 1)img_params["height"] = np.size(img, 0)head, tail = os.path.split(img_id)img_params["filename"] = tailimg_params["path"] = os.path.abspath(img_id)img_params["type"] = "train"pointindex += 1boxarray = []csvholder = []for pointlist in first:pst = np.empty((0, 2), int)max_x = max_y = min_x = min_y = height = width = 0findex = 0for point in pointlist:if(len(point) == 2):x = int(point[0])y = int(point[1])if(findex == 0):min_x = xmin_y = yfindex += 1max_x = x if (x > max_x) else max_xmin_x = x if (x < min_x) else min_xmax_y = y if (y > max_y) else max_ymin_y = y if (y < min_y) else min_y# print(index, "====", len(point))appeno = np.array([[x, y]])pst = np.append(pst, appeno, axis=0)cv2.putText(img, ".", (x, y), font, 0.7,(255, 255, 255), 2, cv2.LINE_AA)hold = {}hold['minx'] = min_xhold['miny'] = min_yhold['maxx'] = max_xhold['maxy'] = max_yif (min_x > 0 and min_y > 0 and max_x > 0 and max_y > 0):boxarray.append(hold)labelrow = [tail,np.size(img, 1), np.size(img, 0), "hand", min_x, min_y, max_x, max_y]csvholder.append(labelrow)cv2.polylines(img, [pst], True, (0, 255, 255), 1)cv2.rectangle(img, (min_x, max_y),(max_x, min_y), (0, 255, 0), 1)csv_path = img_id.split(".")[0]if not os.path.exists(csv_path + ".csv"):cv2.putText(img, "DIR : " + dir + " - " + tail, (20, 50),cv2.FONT_HERSHEY_SIMPLEX, 0.75, (77, 255, 9), 2)cv2.imshow('Verifying annotation ', img)save_csv(csv_path + ".csv", csvholder)print("===== saving csv file for ", tail)cv2.waitKey(2)  # close window when a key press is detecteddef create_directory(dir_path):if not os.path.exists(dir_path):os.makedirs(dir_path)# combine all individual csv files for each image into a single csv file per folder.def generate_label_files(image_dir):header = ['filename', 'width', 'height','class', 'xmin', 'ymin', 'xmax', 'ymax']for root, dirs, filenames in os.walk(image_dir):for dir in dirs:csvholder = []csvholder.append(header)loop_index = 0for f in os.listdir(image_dir + dir):if(f.split(".")[1] == "csv"):loop_index += 1#print(loop_index, f)csv_file = open(image_dir + dir + "/" + f, 'r')reader = csv.reader(csv_file)for row in reader:csvholder.append(row)csv_file.close()os.remove(image_dir + dir + "/" + f)save_csv(image_dir + dir + "/" + dir + "_labels.csv", csvholder)print("Saved label csv for ", dir, image_dir +dir + "/" + dir + "_labels.csv")# Split data, copy to train/test folders
def split_data_test_eval_train(image_dir):create_directory("images")create_directory("images/train")create_directory("images/test")data_size = 4000loop_index = 0data_sampsize = int(0.1 * data_size)test_samp_array = random.sample(range(data_size), k=data_sampsize)for root, dirs, filenames in os.walk(image_dir):for dir in dirs:for f in os.listdir(image_dir + dir):if(f.split(".")[1] == "jpg"):loop_index += 1print(loop_index, f)if loop_index in test_samp_array:os.rename(image_dir + dir +"/" + f, "images/test/" + f)os.rename(image_dir + dir +"/" + f.split(".")[0] + ".csv", "images/test/" + f.split(".")[0] + ".csv")else:os.rename(image_dir + dir +"/" + f, "images/train/" + f)os.rename(image_dir + dir +"/" + f.split(".")[0] + ".csv", "images/train/" + f.split(".")[0] + ".csv")print(loop_index, image_dir + f)print(">   done scanning director ", dir)os.remove(image_dir + dir + "/polygons.mat")os.rmdir(image_dir + dir)print("Train/test content generation complete!")generate_label_files("images/")def generate_csv_files(image_dir):for root, dirs, filenames in os.walk(image_dir):for dir in dirs:get_bbox_visualize(image_dir, dir)print("CSV generation complete!\nGenerating train/test/eval folders")split_data_test_eval_train("egohands/_LABELLED_SAMPLES/")# rename image files so we can have them all in a train/test/eval folder.
def rename_files(image_dir):print("Renaming files")loop_index = 0for root, dirs, filenames in os.walk(image_dir):for dir in dirs:for f in os.listdir(image_dir + dir):if (dir not in f):if(f.split(".")[1] == "jpg"):loop_index += 1os.rename(image_dir + dir +"/" + f, image_dir + dir +"/" + dir + "_" + f)else:breakgenerate_csv_files("egohands/_LABELLED_SAMPLES/")def extract_folder(dataset_path):print("Egohands dataset already downloaded.\nGenerating CSV files")if not os.path.exists("egohands"):zip_ref = zipfile.ZipFile(dataset_path, 'r')print("> Extracting Dataset files")zip_ref.extractall("egohands")print("> Extraction complete")zip_ref.close()rename_files("egohands/_LABELLED_SAMPLES/")def download_egohands_dataset(dataset_url, dataset_path):is_downloaded = os.path.exists(dataset_path)if not is_downloaded:print("> downloading egohands dataset. This may take a while (1.3GB, say 3-5mins). Coffee break?")opener = urllib.request.URLopener()opener.retrieve(dataset_url, dataset_path)print("> download complete")extract_folder(dataset_path);else:extract_folder(dataset_path)EGOHANDS_DATASET_URL = "http://vision.soic.indiana.edu/egohands_files/egohands_data.zip"
EGO_HANDS_FILE = "egohands_data.zip"download_egohands_dataset(EGOHANDS_DATASET_URL, EGO_HANDS_FILE)

在data_deal文件夹中,train_labels.csv与test_labels.csv是解压后的标注文件,下面需要针对csv文件进行转化

2,csv文件转为txt文件

#-*- coding:utf-8
import pandas as pd
import  ospath_dir = './'
# csvPath = path_dir + 'train_labels.csv'
csvPath = path_dir + 'test_labels.csv'
if not os.path.exists(csvPath):print('Not that files:%s'%csvPath)# txtPath = path_dir+'train_labels.txt'
txtPath = path_dir+'test_labels.txt'
data = pd.read_csv(csvPath, encoding='utf-8')with open(txtPath,'a+', encoding='utf-8') as f:for line in data.values:f.write((str(line[0])+'\t'+str(line[1])+','+str(line[2])+'\t'+str(line[4])+','+str(line[5])+','+str(line[6])+','+str(line[7])+'\t'+str(line[3])+'\n'))

转换完成后形成两个txt文件,下一步需要将txt文件进行拆分

3,拆分txt文件

import ostxt_path='./train_txt/'
with open('./train_labels.txt') as f:lines=f.readlines()for line in lines:line=line.strip()words=line.split('\t')file_name=words[0]img_size=words[1]coordinate=words[2]label=words[3]with open(txt_path+file_name[:-3]+'txt','a') as f1:f1.write(coordinate+','+label+'\n')

拆分完成后,在两个文件夹中会生成对应的txt标签文件,但目前的格式还不是YOLOv5需要的格式,还需要进行进一步转换

4,转换txt文件

import osinput_folder = "./labels/train/"  # 替换为包含 txt 文件的文件夹路径
output_folder = "./labels_yolo/train/"  # 替换为输出转换后标签的文件夹路径image_width = 1280
image_height = 720if not os.path.exists(output_folder):os.makedirs(output_folder)for filename in os.listdir(input_folder):if filename.endswith(".txt"):with open(os.path.join(input_folder, filename), "r") as input_file:lines = input_file.readlines()output_lines = []for line in lines:xmin, ymin, xmax, ymax, class_name = line.strip().split(",")center_x = (int(xmin) + int(xmax)) / (2.0 * image_width)center_y = (int(ymin) + int(ymax)) / (2.0 * image_height)width = (int(xmax) - int(xmin)) / image_widthheight = (int(ymax) - int(ymin)) / image_heightyolo_line = f"0 {center_x:.6f} {center_y:.6f} {width:.6f} {height:.6f}"output_lines.append(yolo_line)output_filename = os.path.join(output_folder, filename)with open(output_filename, "w") as output_file:output_file.write("\n".join(output_lines))

至此,转换步骤结束,我们已经得到了完整的4800个图像和对应的txt标签,然后用于训练即可

三、YOLOv5训练

放着服务器不用,我拿闲置的2060跑了半宿,得到结果如下

 

 

 

 

 

四、直接下载修改好的数据集、标签和训练好的模型文件

我本来,想上传到CSDN资源里的,但我的压缩包1.3GB,CSDN最大只能上传1GB的文件,那这波积分是骗不到了,下面是123盘和百度网盘的链接,需要的朋友自取吧:

123云盘:https://www.123pan.com/s/wTqA-j00ph.html
提取码:oBH3
百度网盘: https://pan.baidu.com/s/1wT8K4xTutfqE3WXLanAxiA?pwd=nmdj 
提取码: nmdj

 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【人工智能前沿弄潮】—— SAM系列:SAM从提示生成物体mask

SAM从提示生成物体mask Segment Anything Model&#xff08;SAM&#xff09;根据指示所需的对象来预测对象掩码。该模型首先将图像转换为图像嵌入&#xff0c;从而可以从提示中高效地生成高质量的掩码。 SamPredictor类为模型提供了一个简单的接口来提示模型。用户可以首先使…

数据结构日记之《队列的定义》

队列的定义 一、队列的定义和特点二、队列的抽象数据类型定义三、例子 一、队列的定义和特点 队列 (queue) 是一种 先进先出(First In First Out, FIFO) 的线性表。它只允许在表的一端进行插入&#xff0c;而在另一端删除元素。这和日常生活中的排队是一致的&#xff0c;最早进…

uniapp+vue3项目中使用vant-weapp

创建项目 通过vue-cli命令行创建项目 Vue3/Vite版要求 node 版本^14.18.0 || >16.0.0 uni-app官网 (dcloud.net.cn) npx degit dcloudio/uni-preset-vue#vite my-vue3-project打开项目 点击顶部菜单栏终端/新建终端 执行安装依赖指令 yarn install 或 npm install 安装vant…

【uniapp】使用Vs Code开发uniapp:

文章目录 一、使用命令行创建uniapp项目&#xff1a;二、安装插件与配置&#xff1a;三、编译和运行:四、修改pinia&#xff1a; 一、使用命令行创建uniapp项目&#xff1a; 二、安装插件与配置&#xff1a; 三、编译和运行: 该项目下的dist》dev》mp-weixin文件导入微信开发者…

Redisson可重入锁原理

微信公众号访问地址&#xff1a;Redisson可重入锁原理 推荐文章&#xff1a; 1、使用原生Redis命令实现分布式锁 ​ 2、为什么引入Redisson分布式锁&#xff1f; 3、SpringBoot整合多数据源&#xff0c;并支持动态新增与切换&#xff08;详细教程&#xff09; 4、SpringBo…

3D Web轻量化引擎HOOPS Communicator如何实现对BIM桌面端的支持?

HOOPS Communicator是一款简单而强大的工业级高性能3D Web轻量化渲染开发包&#xff0c;其主要应用于Web领域&#xff0c;主要加载其专有的SCS、SC、SCZ格式文件&#xff1b;HOOPS还拥有另一个桌面端开发包HOOPS Visualize&#xff0c;主要加载HSF、HMF轻量化格式文件。两者虽然…

【QPSK信号生成】生成正交相移键控信号研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Kubernetes集群部署(第二篇)

安装flannel Master 节点NotReady 的原因就是因为没有使用任何的网络插件&#xff0c;此时Node 和Master的连接还不正常。目前最流行的Kubernetes 网络插件有Flannel、Calico、Canal、Weave 这里选择使用flannel。 flannel提取链接&#xff1a;https://pan.baidu.com/s/1fLJKh…

EXPLAIN使用分析

系列文章目录 文章目录 系列文章目录一、type说明二、MySQL中使用Show Profile1.查看当前profiling配置2.在会话级别修改profiling配置3.查看profile记录4.要深入查看某条查询执行时间的分布 一、type说明 我们只需要注意一个最重要的type 的信息很明显的提现是否用到索引&…

云原生之深入解析Redis的原理分析与环境部署

一、Redis 简介 ① 什么是 Redis &#xff1f; REmote DIctionary Server&#xff08;Redis&#xff09;是一个由 Salvatore Sanfilippo 写的 key-value 存储系统&#xff0c;是跨平台的非关系型数据库。Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可…

在java中如何使用openOffice进行格式转换,word,excel,ppt,pdf互相转换

1.首先需要下载并安装openOffice,下载地址为&#xff1a; Apache OpenOffice download | SourceForge.net 2.安装后&#xff0c;可以测试下是否可用&#xff1b; 3.build.gradle中引入依赖&#xff1a; implementation group: com.artofsolving, name: jodconverter, version:…

mac ssh连接另一台window虚拟机vm

vmware配置端口映射 编辑(E) > 虚拟网络编辑器(N)... > NAT设置(S)... window防火墙&#xff0c;入站规则添加5555端口 控制面板 > 系统和安全 > Windows 防火墙>高级设置>入站规则>新建规则... tips windows查看端口命令&#xff1a;netstat -ano | f…