流程:
标注-训练-预测-标注-训练
标注文件保存为voc格式
1,labelimg的安装(python>3.0)
pip install labelImg
labelimg
打包成单独的exe文件
先进入labelimg包的目录
C:\Users\Administrator\AppData\Local\Programs\Python\Python310\Lib\site-packages\labelImg
不知道的可以用
# 查询pip的目录
where pip
pip install pyinstaller
pyinstaller --hidden-import=pyqt5 --hidden-import=lxml -F -n "labelImg" -c labelImg.py -p ./libs -p ./
打包之后在同目录的dist下面
2,labelme的安装
标注文件保存为json格式
conda create --name=labelme python=3
conda activate labelme
pip install labelme
labelme
附带
voc转json代码:
# --- utf-8 ---
# --- function: 将Labeling标注的格式转化为Labelme标注格式,并读取imageData ---
import os
import glob
import shutil
import xml.etree.ElementTree as ET
import json
from base64 import b64encode
from json import dumps
def get(root, name):
return root.findall(name)
# 检查读取xml文件是否出错
def get_and_check(root, name, length):
vars = root.findall(name)
if len(vars) == 0:
raise NotImplementedError('Can not fing %s in %s.' % (name, root.tag))
if length > 0 and len(vars) != length:
raise NotImplementedError('The size of %s is supposed to be %d, but is %d.' % (name, length, len(vars)))
if length == 1:
vars = vars[0]
return vars
def convert(xml_file, json_file, save_dir, name, data):
# 定义通过Labelme标注后生成的json文件
json_dict = {"version": "3.16.2",
"flags": {},
"shapes": [],
"imagePath": "",
"imageData": None,
"imageHeight": 0,
"imageWidth": 0
}
# img_name = xml_file.split('.')[0]
img_path = name + '.jpg'
json_dict["imagePath"] = img_path
tree = ET.parse(xml_file) # 读取xml文件
root = tree.getroot()
size = get_and_check(root, 'size', 1) # 读取xml中<>size<>字段中的内容
# 读取二进制图片,获得原始字节码
with open(data, 'rb') as jpg_file:
byte_content = jpg_file.read()
# 把原始字节码编码成base64字节码
base64_bytes = b64encode(byte_content)
# 把base64字节码解码成utf-8格式的字符串
base64_string = base64_bytes.decode('utf-8')
# 用字典的形式保存数据
json_dict["imageData"] = base64_string
# 获取图片的长宽信息
width = int(get_and_check(size, 'width', 1).text)
height = int(get_and_check(size, 'height', 1).text)
json_dict["imageHeight"] = height
json_dict["imageWidth"] = width
# 当标注中有多个目标时全部读取出来
for obj in get(root, 'object'):
# 定义图片的标注信息
img_mark_inf = {"label": "", "points": [], "group_id": None, "shape_type": "rectangle", "flags": {}}
category = get_and_check(obj, 'name', 1).text # 读取当前目标的类别
img_mark_inf["label"] = category
bndbox = get_and_check(obj, 'bndbox', 1) # 获取标注宽信息
xmin = float(get_and_check(bndbox, 'xmin', 1).text)
ymin = float(get_and_check(bndbox, 'ymin', 1).text)
xmax = float(get_and_check(bndbox, 'xmax', 1).text)
ymax = float(get_and_check(bndbox, 'ymax', 1).text)
img_mark_inf["points"].append([xmin, ymin])
img_mark_inf["points"].append([xmax, ymax])
# print(img_mark_inf["points"])
json_dict["shapes"].append(img_mark_inf)
# print("{}".format(json_dict))
save = save_dir +'/'+ json_file # json文件的路径地址
json_fp = open(save, 'w') #
json_str = json.dumps(json_dict, indent=4) # 缩进,不需要的可以将indent=4去掉
json_fp.write(json_str) # 保存
json_fp.close()
# print("{}, {}".format(width, height))
def do_transformation(xml_dir, save_path):
cnt = 0
for fname in os.listdir(xml_dir):
name = fname.split(".")[0] # 获取图片名字
path = os.path.join(xml_dir, fname) # 文件路径
save_json_name = name + '.json'
data = img +'/'+ name + '.jpg' # xml文件对应的图片路径
convert(path, save_json_name, save_path, name, data)
cnt += 1
if __name__ == '__main__':
img = r"D:\zsh\biaozhu\basketball_count\F_field\labelimg\voc\JPEGImages" # xml对应图片文件夹
xml_path = r"D:\zsh\biaozhu\basketball_count\F_field\labelimg\voc\Annotations" # xml文件夹
save_json_path = r"D:\zsh\biaozhu\basketball_count\F_field\labelimg\voc\json" # 存放json文件夹
if not os.path.exists(save_json_path):
os.makedirs(save_json_path)
do_transformation(xml_path, save_json_path)
# xml = "2007_000039.xml"
# xjson = "2007_000039.json"
# convert(xml, xjson)
1,用labelimg标注voc格式的标注数据
2,生成数据集,分为训练集和验证集
生成脚本:
import glob
import random
import multiprocessing
def process_file(file_name):
output = glob.glob('dataset/' + dir + '/images/' + file_name + '.???')[0]
output.replace('\\', '/').split('/')[-1]
return './images/' + output + ' ./annotations/' + file_name + '.xml\n'
dir = '6.19_gray_court_voc'
num_processes = multiprocessing.cpu_count() * 1.5 # 指定使用的进程数为 CPU 数量的两倍
path = 'dataset/' + dir
tmp = []
for i in glob.glob(path + '/annotations/*.xml'):
name = i.replace('\\', '/').split('/')[-1][:-4]
tmp.append(name)
random.shuffle(tmp)
train = tmp[:int(len(tmp) * 0.8)]
val = tmp[int(len(tmp) * 0.8):]
print('train:', len(train), 'val:', len(val))
# Create a pool of worker processes with specified number of processes
pool = multiprocessing.Pool(processes=num_processes)
with open('dataset/' + dir + '/train.txt', 'w', encoding='utf-8') as f:
# Process train data using multiple processes
results = pool.map(process_file, train)
f.writelines(results)
with open('dataset/' + dir + '/valid.txt', 'w', encoding='utf-8') as f:
# Process validation data using multiple processes
results = pool.map(process_file, val)
f.writelines(results)
# Close the pool of worker processes
pool.close()
pool.join()
运行后目录下生成train.txt,val.txt
创建label_list.txt,写入标注数据的类别
目录:
person
---images
---xx.jpg
---annotation
---xx.xml
---train.txt
---val.txt
---label_list.txt
github主页:一些常用的清洗数据的脚本
https://github.com/zsh123abc/Data_analysis_related_py
1,安装docker
# 下载地址
https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe
安装到除c盘外的其他盘
docker的默认安装路径:C:\Program Files\Docker
用管理员打开cmd
# 通过软连接把实际储存移到E盘中
mklink C:\Program Files\Docker E:\Docker
双击运行docker.exe
2,拉paddle镜像
docker pull paddlepaddle/paddle:2.5.2-gpu-cuda12.0-cudnn8.9-trt8.6
3,下载PPaddleDetection 2.6 源码
git clone --branch 2.6 https://github.com/PaddlePaddle/PaddleDetection.git
3,gpu启动docker容器
docker run -it --privileged=true --name paddle_test --gpus all -d -p 8040:8040 -v E:\PaddleDetection:/PaddleDetection paddlepaddle/paddle:2.5.2-gpu-cuda12.0-cudnn8.9-trt8.6 /bin/bash
把标注数据集的文件夹放到
/PaddleDetection/dataset/voc
修改配置文件:
cd /PaddleDetection
# cp一份
cp configs/datasets/voc.yml configs/datasets/test_voc.yml
vi configs/datasets/test_voc.yml
test_voc.yml
metric: VOC
map_type: 11point
num_classes: 20 #类别数量
TrainDataset:
name: VOCDataSet
dataset_dir: dataset/voc #数据集目录
anno_path: trainval.txt
label_list: label_list.txt
data_fields: ['image', 'gt_bbox', 'gt_class', 'difficult']
EvalDataset:
name: VOCDataSet
dataset_dir: dataset/voc #数据集目录
anno_path: test.txt
label_list: label_list.txt
data_fields: ['image', 'gt_bbox', 'gt_class', 'difficult']
TestDataset:
name: ImageFolder
anno_path: dataset/voc/label_list.txt #类别名文件
修改配置文件:
/PaddleDetection/configs/picodet/legacy_model/picodet_s_320_voc.yml
picodet_s_320_voc.yml
_BASE_: [
'../../datasets/voc.yml',
'../../runtime.yml',
'_base_/picodet_esnet.yml',
'_base_/optimizer_300e.yml',
'_base_/picodet_320_reader.yml',
]
pretrain_weights: https://paddledet.bj.bcebos.com/models/pretrained/ESNet_x0_75_pretrained.pdparams
weights: output/picodet_s_320_coco/model_final
find_unused_parameters: True
use_ema: true
cycle_epoch: 40
snapshot_epoch: 10
ESNet:
scale: 0.75
feature_maps: [4, 11, 14]
act: hard_swish
channel_ratio: [0.875, 0.5, 0.5, 0.5, 0.625, 0.5, 0.625, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
CSPPAN:
out_channels: 96
PicoHead:
conv_feat:
name: PicoFeat
feat_in: 96
feat_out: 96
num_convs: 2
num_fpn_stride: 4
norm_type: bn
share_cls_reg: True
feat_in_chan: 96
EvalReader:
collate_batch: false
python -m tools/train.py -c configs/picodet/legacy_model/picodet_s_320_voc.yml
单机多卡
python -m paddle.distributed.launch \
--selected_gpus='0,1,2' \
--log_dir=./test_voc/ \
tools/train.py \
-c configs/picodet/legacy_model/picodet_s_320_voc.yml \
--use_vdl=true \
--vdl_log_dir=vdl_dir/scratch_log \
--eval>test_voc.log 2>&1 &
多机多卡
python -m paddle.distributed.launch \
--cluster_node_ips=192.168.100.1,192.168.100.2 \
--node_ip=192.168.100.1 \
--started_port=6170 \
--selected_gpus=0 \
--log_dir=./ping-pang \
tools/train.py -c configs/picodet/legacy_model/picodet_s_320_voc.yml --use_vdl=true --vdl_log_dir=vdl_dir/scratch_log --eval>scratch.log 2>&1&
可视化训练,visualdl安装
pip install --upgrade visualdl
在训练命令中加入
--use_vdl=true \
--vdl_log_dir=vdl_dir/scratch_log \
启用,指定log文件夹
visualdl --logdir ./scratch_log --port 8080
浏览器输入
http://127.0.0.1:8080
python tools/export_model.py \
-c configs/picodet/legacy_model/picodet_s_320_voc.yml \
-o weights=output/test_voc/best_model.pdparams \
--output_dir=inference_model
优化模型,转换格式,方便移动端部署
paddle_lite_opt --valid_targets=arm \
--model_file=inference_model/test_voc/model.pdmodel \
--param_file=inference_model/test_voc/model.pdiparams \
--optimize_out=inference_model/test_voc/test_voc
图片预测
python deploy/python/infer.py \
--model_dir=inference_model/test_voc \
--output=output/test_img_output \
--image_file=output/img_test.jpg \
--threshold=0.5 \
--device=GPU
多张图片预测
python deploy/python/infer.py \
--model_dir=inference_model/test_voc \
--output=output/test_images_output \
--image_dir=output/images_test \
--threshold=0.5
--device=GPU
视频预测
python deploy/python/infer.py \
--model_dir=inference_model/test_voc \
--video_file=dataset/test_video \
--output=output/test_video_output \
--threshold=0.5 \
--device=GPU
附带 批量运行视频脚本
find dataset/court_video_test/628_video/ -type f -name "*.mp4" -exec sh -c 'python deploy/python/infer.py --model_dir=inference_model/test_voc --video_file="{}" --output=output/test_video_output --threshold=0.5 --device=GPU' \;
生成预标注 --save_results 保存推理结果,需要修改推理源码,保存推理结果至json文件
python deploy/python/infer.py \
--model_dir=inference_model/test_voc \
--output=output/test_json_output \
--image_dir=dataset/test_images \
--threshold=0.5 \
--device=GPU \
--save_results
参考paddle github官网项目
git clone https://github.com/PaddlePaddle/Paddle-Lite-Demo/tree/develop/object_detection/android/app/cxx/picodet_detection_demo
1,下载 Android Stuido
官网地址:https://developer.android.com/studio
2,下载JDK,SDK,NDK,CMake
参考网址:https://developer.android.com/studio/projects/install-ndk?hl=zh-cn