PaddleDetection 自定义训练目标检测

news2024/10/1 5:46:45

PaddleDetection是一个基于PaddlePaddle的目标检测端到端开发套件,在提供丰富的模型组件和测试基准的同时,注重端到端的产业落地应用,通过打造产业级特色模型|工具、建设产业应用范例等手段,帮助开发者实现数据准备、模型选型、模型训练、模型部署的全流程打通,快速进行落地应用。

  • 效果

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 官方文档:https://gitee.com/paddlepaddle/PaddleDetection

1.1 准备数据集

  • 官方支持VOCCoco数据集

1.1.1 LabelMe标注格式

  • 安装:
conda create –name=labelme python=3
conda activate labelme
pip install pyqt5
pip install labelme
  • 启动
labelme

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 打开进行标注

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 进行标注

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意:如果是多边形只支持COCO数据集,在转换VOC的过程中会报错,VOC数据集支持矩形

  • 这里我们需要大量的数据集进行标注,注意里面的图片需要每一个进行标注

1.1.2 数据集转换成COCO

  • 脚本
# _*_ coding: utf-8 _*_
"""
Time:     2024/9/29 下午8:47
Author:   EasonShu
Version:  V 0.1
File:     LableToCoCo.py
Describe: 
"""
#!/usr/bin/env python
# coding: utf-8
# Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import argparse
import glob
import json
import os
import os.path as osp
import shutil
import xml.etree.ElementTree as ET

import numpy as np
import PIL.ImageDraw
from tqdm import tqdm
import cv2

label_to_num = {}
categories_list = []
labels_list = []


class MyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, np.integer):
            return int(obj)
        elif isinstance(obj, np.floating):
            return float(obj)
        elif isinstance(obj, np.ndarray):
            return obj.tolist()
        else:
            return super(MyEncoder, self).default(obj)


def images_labelme(data, num):
    image = {}
    image['height'] = data['imageHeight']
    image['width'] = data['imageWidth']
    image['id'] = num + 1
    if '\\' in data['imagePath']:
        image['file_name'] = data['imagePath'].split('\\')[-1]
    else:
        image['file_name'] = data['imagePath'].split('/')[-1]
    return image


def images_cityscape(data, num, img_file):
    image = {}
    image['height'] = data['imgHeight']
    image['width'] = data['imgWidth']
    image['id'] = num + 1
    image['file_name'] = img_file
    return image


def categories(label, labels_list):
    category = {}
    category['supercategory'] = 'component'
    category['id'] = len(labels_list) + 1
    category['name'] = label
    return category


def annotations_rectangle(points, label, image_num, object_num, label_to_num):
    annotation = {}
    seg_points = np.asarray(points).copy()
    seg_points[1, :] = np.asarray(points)[2, :]
    seg_points[2, :] = np.asarray(points)[1, :]
    annotation['segmentation'] = [list(seg_points.flatten())]
    annotation['iscrowd'] = 0
    annotation['image_id'] = image_num + 1
    annotation['bbox'] = list(
        map(float, [
            points[0][0], points[0][1], points[1][0] - points[0][0], points[1][
                1] - points[0][1]
        ]))
    annotation['area'] = annotation['bbox'][2] * annotation['bbox'][3]
    annotation['category_id'] = label_to_num[label]
    annotation['id'] = object_num + 1
    return annotation


def annotations_polygon(height, width, points, label, image_num, object_num,
                        label_to_num):
    annotation = {}
    annotation['segmentation'] = [list(np.asarray(points).flatten())]
    annotation['iscrowd'] = 0
    annotation['image_id'] = image_num + 1
    annotation['bbox'] = list(map(float, get_bbox(height, width, points)))
    annotation['area'] = annotation['bbox'][2] * annotation['bbox'][3]
    annotation['category_id'] = label_to_num[label]
    annotation['id'] = object_num + 1
    return annotation


def get_bbox(height, width, points):
    polygons = points
    mask = np.zeros([height, width], dtype=np.uint8)
    mask = PIL.Image.fromarray(mask)
    xy = list(map(tuple, polygons))
    PIL.ImageDraw.Draw(mask).polygon(xy=xy, outline=1, fill=1)
    mask = np.array(mask, dtype=bool)
    index = np.argwhere(mask == 1)
    rows = index[:, 0]
    clos = index[:, 1]
    left_top_r = np.min(rows)
    left_top_c = np.min(clos)
    right_bottom_r = np.max(rows)
    right_bottom_c = np.max(clos)
    return [
        left_top_c, left_top_r, right_bottom_c - left_top_c,
        right_bottom_r - left_top_r
    ]


def deal_json(ds_type, img_path, json_path):
    data_coco = {}
    images_list = []
    annotations_list = []
    image_num = -1
    object_num = -1
    for img_file in os.listdir(img_path):
        img_label = os.path.splitext(img_file)[0]
        if img_file.split('.')[
                -1] not in ['bmp', 'jpg', 'jpeg', 'png', 'JPEG', 'JPG', 'PNG']:
            continue
        label_file = osp.join(json_path, img_label + '.json')
        print('Generating dataset from:', label_file)
        image_num = image_num + 1
        with open(label_file) as f:
            data = json.load(f)
            if ds_type == 'labelme':
                images_list.append(images_labelme(data, image_num))
            elif ds_type == 'cityscape':
                images_list.append(images_cityscape(data, image_num, img_file))
            if ds_type == 'labelme':
                for shapes in data['shapes']:
                    object_num = object_num + 1
                    label = shapes['label']
                    if label not in labels_list:
                        categories_list.append(categories(label, labels_list))
                        labels_list.append(label)
                        label_to_num[label] = len(labels_list)
                    p_type = shapes['shape_type']
                    if p_type == 'polygon':
                        points = shapes['points']
                        annotations_list.append(
                            annotations_polygon(data['imageHeight'], data[
                                'imageWidth'], points, label, image_num,
                                                object_num, label_to_num))

                    if p_type == 'rectangle':
                        (x1, y1), (x2, y2) = shapes['points']
                        x1, x2 = sorted([x1, x2])
                        y1, y2 = sorted([y1, y2])
                        points = [[x1, y1], [x2, y2], [x1, y2], [x2, y1]]
                        annotations_list.append(
                            annotations_rectangle(points, label, image_num,
                                                  object_num, label_to_num))
            elif ds_type == 'cityscape':
                for shapes in data['objects']:
                    object_num = object_num + 1
                    label = shapes['label']
                    if label not in labels_list:
                        categories_list.append(categories(label, labels_list))
                        labels_list.append(label)
                        label_to_num[label] = len(labels_list)
                    points = shapes['polygon']
                    annotations_list.append(
                        annotations_polygon(data['imgHeight'], data[
                            'imgWidth'], points, label, image_num, object_num,
                                            label_to_num))
    data_coco['images'] = images_list
    data_coco['categories'] = categories_list
    data_coco['annotations'] = annotations_list
    return data_coco


def voc_get_label_anno(ann_dir_path, ann_ids_path, labels_path):
    with open(labels_path, 'r') as f:
        labels_str = f.read().split()
    labels_ids = list(range(1, len(labels_str) + 1))

    with open(ann_ids_path, 'r') as f:
        ann_ids = [lin.strip().split(' ')[-1] for lin in f.readlines()]

    ann_paths = []
    for aid in ann_ids:
        if aid.endswith('xml'):
            ann_path = os.path.join(ann_dir_path, aid)
        else:
            ann_path = os.path.join(ann_dir_path, aid + '.xml')
        ann_paths.append(ann_path)

    return dict(zip(labels_str, labels_ids)), ann_paths


def voc_get_image_info(annotation_root, im_id):
    filename = annotation_root.findtext('filename')
    assert filename is not None
    img_name = os.path.basename(filename)

    size = annotation_root.find('size')
    width = float(size.findtext('width'))
    height = float(size.findtext('height'))

    image_info = {
        'file_name': filename,
        'height': height,
        'width': width,
        'id': im_id
    }
    return image_info


def voc_get_coco_annotation(obj, label2id):
    label = obj.findtext('name')
    assert label in label2id, "label is not in label2id."
    category_id = label2id[label]
    bndbox = obj.find('bndbox')
    xmin = float(bndbox.findtext('xmin'))
    ymin = float(bndbox.findtext('ymin'))
    xmax = float(bndbox.findtext('xmax'))
    ymax = float(bndbox.findtext('ymax'))
    assert xmax > xmin and ymax > ymin, "Box size error."
    o_width = xmax - xmin
    o_height = ymax - ymin
    anno = {
        'area': o_width * o_height,
        'iscrowd': 0,
        'bbox': [xmin, ymin, o_width, o_height],
        'category_id': category_id,
        'ignore': 0,
    }
    return anno


def voc_xmls_to_cocojson(annotation_paths, label2id, output_dir, output_file):
    output_json_dict = {
        "images": [],
        "type": "instances",
        "annotations": [],
        "categories": []
    }
    bnd_id = 1  # bounding box start id
    im_id = 0
    print('Start converting !')
    for a_path in tqdm(annotation_paths):
        # Read annotation xml
        ann_tree = ET.parse(a_path)
        ann_root = ann_tree.getroot()

        img_info = voc_get_image_info(ann_root, im_id)
        output_json_dict['images'].append(img_info)

        for obj in ann_root.findall('object'):
            ann = voc_get_coco_annotation(obj=obj, label2id=label2id)
            ann.update({'image_id': im_id, 'id': bnd_id})
            output_json_dict['annotations'].append(ann)
            bnd_id = bnd_id + 1
        im_id += 1

    for label, label_id in label2id.items():
        category_info = {'supercategory': 'none', 'id': label_id, 'name': label}
        output_json_dict['categories'].append(category_info)
    output_file = os.path.join(output_dir, output_file)
    with open(output_file, 'w') as f:
        output_json = json.dumps(output_json_dict)
        f.write(output_json)


def widerface_to_cocojson(root_path):
    train_gt_txt = os.path.join(root_path, "wider_face_split", "wider_face_train_bbx_gt.txt")
    val_gt_txt = os.path.join(root_path, "wider_face_split", "wider_face_val_bbx_gt.txt")
    train_img_dir = os.path.join(root_path, "WIDER_train", "images")
    val_img_dir = os.path.join(root_path, "WIDER_val", "images")
    assert train_gt_txt
    assert val_gt_txt
    assert train_img_dir
    assert val_img_dir
    save_path = os.path.join(root_path, "widerface_train.json")
    widerface_convert(train_gt_txt, train_img_dir, save_path)
    print("Wider Face train dataset converts sucess, the json path: {}".format(save_path))
    save_path = os.path.join(root_path, "widerface_val.json")
    widerface_convert(val_gt_txt, val_img_dir, save_path)
    print("Wider Face val dataset converts sucess, the json path: {}".format(save_path))


def widerface_convert(gt_txt, img_dir, save_path):
    output_json_dict = {
        "images": [],
        "type": "instances",
        "annotations": [],
        "categories": [{'supercategory': 'none', 'id': 0, 'name': "human_face"}]
    }
    bnd_id = 1  # bounding box start id
    im_id = 0
    print('Start converting !')
    with open(gt_txt) as fd:
        lines = fd.readlines()

    i = 0
    while i < len(lines):
        image_name = lines[i].strip()
        bbox_num = int(lines[i + 1].strip())
        i += 2
        img_info = get_widerface_image_info(img_dir, image_name, im_id)
        if img_info:
            output_json_dict["images"].append(img_info)
            for j in range(i, i + bbox_num):
                anno = get_widerface_ann_info(lines[j])
                anno.update({'image_id': im_id, 'id': bnd_id})
                output_json_dict['annotations'].append(anno)
                bnd_id += 1
        else:
            print("The image dose not exist: {}".format(os.path.join(img_dir, image_name)))
        bbox_num = 1 if bbox_num == 0 else bbox_num
        i += bbox_num
        im_id += 1
    with open(save_path, 'w') as f:
        output_json = json.dumps(output_json_dict)
        f.write(output_json)


def get_widerface_image_info(img_root, img_relative_path, img_id):
    image_info = {}
    save_path = os.path.join(img_root, img_relative_path)
    if os.path.exists(save_path):
        img = cv2.imread(save_path)
        image_info["file_name"] = os.path.join(os.path.basename(
            os.path.dirname(img_root)), os.path.basename(img_root),
            img_relative_path)
        image_info["height"] = img.shape[0]
        image_info["width"] = img.shape[1]
        image_info["id"] = img_id
    return image_info


def get_widerface_ann_info(info):
    info = [int(x) for x in info.strip().split()]
    anno = {
        'area': info[2] * info[3],
        'iscrowd': 0,
        'bbox': [info[0], info[1], info[2], info[3]],
        'category_id': 0,
        'ignore': 0,
        'blur': info[4],
        'expression': info[5],
        'illumination': info[6],
        'invalid': info[7],
        'occlusion': info[8],
        'pose': info[9]
    }
    return anno


def main():
    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument(
        '--dataset_type',
        help='the type of dataset, can be `voc`, `widerface`, `labelme` or `cityscape`')
    parser.add_argument('--json_input_dir', help='input annotated directory')
    parser.add_argument('--image_input_dir', help='image directory')
    parser.add_argument(
        '--output_dir', help='output dataset directory', default='./')
    parser.add_argument(
        '--train_proportion',
        help='the proportion of train dataset',
        type=float,
        default=1.0)
    parser.add_argument(
        '--val_proportion',
        help='the proportion of validation dataset',
        type=float,
        default=0.0)
    parser.add_argument(
        '--test_proportion',
        help='the proportion of test dataset',
        type=float,
        default=0.0)
    parser.add_argument(
        '--voc_anno_dir',
        help='In Voc format dataset, path to annotation files directory.',
        type=str,
        default=None)
    parser.add_argument(
        '--voc_anno_list',
        help='In Voc format dataset, path to annotation files ids list.',
        type=str,
        default=None)
    parser.add_argument(
        '--voc_label_list',
        help='In Voc format dataset, path to label list. The content of each line is a category.',
        type=str,
        default=None)
    parser.add_argument(
        '--voc_out_name',
        type=str,
        default='voc.json',
        help='In Voc format dataset, path to output json file')
    parser.add_argument(
        '--widerface_root_dir',
        help='The root_path for wider face dataset, which contains `wider_face_split`, `WIDER_train` and `WIDER_val`.And the json file will save in this path',
        type=str,
        default=None)
    args = parser.parse_args()
    try:
        assert args.dataset_type in ['voc', 'labelme', 'cityscape', 'widerface']
    except AssertionError as e:
        print(
            'Now only support the voc, cityscape dataset and labelme dataset!!')
        os._exit(0)

    if args.dataset_type == 'voc':
        assert args.voc_anno_dir and args.voc_anno_list and args.voc_label_list
        label2id, ann_paths = voc_get_label_anno(
            args.voc_anno_dir, args.voc_anno_list, args.voc_label_list)
        voc_xmls_to_cocojson(
            annotation_paths=ann_paths,
            label2id=label2id,
            output_dir=args.output_dir,
            output_file=args.voc_out_name)
    elif args.dataset_type == "widerface":
        assert args.widerface_root_dir
        widerface_to_cocojson(args.widerface_root_dir)
    else:
        try:
            assert os.path.exists(args.json_input_dir)
        except AssertionError as e:
            print('The json folder does not exist!')
            os._exit(0)
        try:
            assert os.path.exists(args.image_input_dir)
        except AssertionError as e:
            print('The image folder does not exist!')
            os._exit(0)
        try:
            assert abs(args.train_proportion + args.val_proportion \
                    + args.test_proportion - 1.0) < 1e-5
        except AssertionError as e:
            print(
                'The sum of pqoportion of training, validation and test datase must be 1!'
            )
            os._exit(0)

        # Allocate the dataset.
        total_num = len(glob.glob(osp.join(args.json_input_dir, '*.json')))
        if args.train_proportion != 0:
            train_num = int(total_num * args.train_proportion)
            out_dir = args.output_dir + '/train'
            if not os.path.exists(out_dir):
                os.makedirs(out_dir)
        else:
            train_num = 0
        if args.val_proportion == 0.0:
            val_num = 0
            test_num = total_num - train_num
            out_dir = args.output_dir + '/test'
            if args.test_proportion != 0.0 and not os.path.exists(out_dir):
                os.makedirs(out_dir)
        else:
            val_num = int(total_num * args.val_proportion)
            test_num = total_num - train_num - val_num
            val_out_dir = args.output_dir + '/val'
            if not os.path.exists(val_out_dir):
                os.makedirs(val_out_dir)
            test_out_dir = args.output_dir + '/test'
            if args.test_proportion != 0.0 and not os.path.exists(test_out_dir):
                os.makedirs(test_out_dir)
        count = 1
        for img_name in os.listdir(args.image_input_dir):
            if count <= train_num:
                if osp.exists(args.output_dir + '/train/'):
                    shutil.copyfile(
                        osp.join(args.image_input_dir, img_name),
                        osp.join(args.output_dir + '/train/', img_name))
            else:
                if count <= train_num + val_num:
                    if osp.exists(args.output_dir + '/val/'):
                        shutil.copyfile(
                            osp.join(args.image_input_dir, img_name),
                            osp.join(args.output_dir + '/val/', img_name))
                else:
                    if osp.exists(args.output_dir + '/test/'):
                        shutil.copyfile(
                            osp.join(args.image_input_dir, img_name),
                            osp.join(args.output_dir + '/test/', img_name))
            count = count + 1

        # Deal with the json files.
        if not os.path.exists(args.output_dir + '/annotations'):
            os.makedirs(args.output_dir + '/annotations')
        if args.train_proportion != 0:
            train_data_coco = deal_json(args.dataset_type,
                                        args.output_dir + '/train',
                                        args.json_input_dir)
            train_json_path = osp.join(args.output_dir + '/annotations',
                                       'instance_train.json')
            json.dump(
                train_data_coco,
                open(train_json_path, 'w'),
                indent=4,
                cls=MyEncoder)
        if args.val_proportion != 0:
            val_data_coco = deal_json(args.dataset_type,
                                      args.output_dir + '/val',
                                      args.json_input_dir)
            val_json_path = osp.join(args.output_dir + '/annotations',
                                     'instance_val.json')
            json.dump(
                val_data_coco,
                open(val_json_path, 'w'),
                indent=4,
                cls=MyEncoder)
        if args.test_proportion != 0:
            test_data_coco = deal_json(args.dataset_type,
                                       args.output_dir + '/test',
                                       args.json_input_dir)
            test_json_path = osp.join(args.output_dir + '/annotations',
                                      'instance_test.json')
            json.dump(
                test_data_coco,
                open(test_json_path, 'w'),
                indent=4,
                cls=MyEncoder)


if __name__ == '__main__':
    main()
  • 执行转换命令
python  LableToCoCo.py --dataset_type labelme --json_input_dir H:\Datas\ --image_input_dir H:\Datas\ --output_dir H:\Datas\Data_CoCo\ --train_proportion 0.8  --val_proportion 0.2 --test_proportion 0.0
  • json_input_dir:标注的Json文件地址
  • image_input_dir:图片数据
  • output_dir:输出路径
  • train_proportion:训练数据集比例
  • val_proportion:验证数据集比例
  • test_proportion:测试数据集比例

生成的数据目录

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1.2 开发环境搭建

  • 下载地址:https://gitee.com/paddlepaddle/PaddleDetection

  • 导入Pychar中,安装环境依赖,注意飞浆的环境

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1.2.1 查看配置文件

建议先看一编配置文件的信息

  • 参考文档:https://gitee.com/paddlepaddle/PaddleDetection/blob/release/2.7/docs/tutorials/config_annotation/faster_rcnn_r50_fpn_1x_coco_annotation.md
  • https://gitee.com/paddlepaddle/PaddleDetection/blob/release/2.7/docs/tutorials/config_annotation/ppyolo_r50vd_dcn_1x_coco_annotation.md

1.3 配置训练文件

  • 这里我已PP-PicoDet 超轻量实时目标检测模型为例

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • configs/picodet/picodet_l_640_coco_lcnet.yml

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 修改数据集配置文件:
metric: COCO
num_classes: 2

TrainDataset:
  name: COCODataSet
  # 刚才转换的数据集路径
  image_dir: H:\train_data\Data_CoCo\train
  # 转换的配置文件
  anno_path: H:\train_data\Data_CoCo\annotations\instance_train.json
  dataset_dir: H:\train_data\Data_CoCo
  data_fields: ['image', 'gt_bbox', 'gt_class', 'is_crowd']

EvalDataset:
  name: COCODataSet
  image_dir: H:\train_data\Data_CoCo\val
  anno_path: H:\train_data\Data_CoCo\annotations\instance_val.json
  dataset_dir: H:\train_data\Data_CoCo
  allow_empty: true

TestDataset:
  name: ImageFolder
  anno_path: H:\train_data\Data_CoCo\annotations\instance_val.json # also support txt (like VOC's label_list.txt)
  dataset_dir: H:\train_data\Data_CoCo # if set, anno_path will be 'dataset_dir/anno_path'
  • 其他配置文件不懂参考官网

1.3.1 开始训练

  • 命令
python tools/train.py -c configs/picodet/picodet_l_640_coco_lcnet.yml --eval

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 可视化训练过程
visualdl --logdir ./output --port 8080

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • CMD 窗口定位到这

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 浏览器查看情况:http://localhost:8080

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们来关注几个参数:

bbox-mAP

bbox-mAP (mean Average Precision for bounding boxes) 是目标检测任务中一个常用的性能度量指标。mAP 的范围是从 0 到 1,或者以百分比表示时从 0% 到 100%。

  • 当 mAP 值为 0 时,意味着模型的预测结果与真实标签完全不匹配。
  • 当 mAP 值为 1 或 100% 时,意味着模型的预测结果与真实标签完美匹配。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

loss

在机器学习和深度学习中,损失(loss)值越低通常意味着模型的性能越好。这是因为损失函数是用来衡量模型预测结果与实际目标之间的差距的指标。一个较低的损失值表明模型的预测更加接近真实值,从而说明模型在训练数据上的拟合程度更好。

1.3.2 验证模型

python tools/eval.py -c configs/picodet/picodet_l_640_coco_lcnet.yml -o weights=output/best_model.pdparams

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1.3.3 测试模型

python tools/infer.py -c configs/picodet/picodet_l_640_coco_lcnet.yml --infer_img=H:\PaddleDetection\demo\test9.png -o weights=output/best_model.pdparams  --draw_threshold=0.1

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 查看效果还不错,最后导出模型

1.3.4 导出模型

python tools/export_model.py -c configs/picodet/picodet_l_640_coco_lcnet.yml --output_dir=./inference_model -o weights=output/best_model 

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1.3.5 测试导出的模型

python deploy/python/infer.py --threshold=0.1 --model_dir=./inference_model/picodet_l_640_coco_lcnet --image_file=H:\PaddleDetection\demo\test8.png --device=GPU

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

yml --infer_img=H:\PaddleDetection\demo\test9.png -o weights=output/best_model.pdparams --draw_threshold=0.1


[外链图片转存中...(img-z5MWzSNf-1727681583587)]

[外链图片转存中...(img-3WWLCZby-1727681583587)]

- 查看效果还不错,最后导出模型

### 1.3.4 导出模型

```bash
python tools/export_model.py -c configs/picodet/picodet_l_640_coco_lcnet.yml --output_dir=./inference_model -o weights=output/best_model 

[外链图片转存中…(img-7HHwypk7-1727681583588)]

[外链图片转存中…(img-dtv76KMR-1727681583588)]

1.3.5 测试导出的模型

python deploy/python/infer.py --threshold=0.1 --model_dir=./inference_model/picodet_l_640_coco_lcnet --image_file=H:\PaddleDetection\demo\test8.png --device=GPU

[外链图片转存中…(img-TT94vKns-1727681583588)]

[外链图片转存中…(img-5Zi8MUhB-1727681583588)]

到此我们的模型训练到此结束,对拍摄很正的效果很好,对于倾斜的目标不是很有效,目前需要补充数据集

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

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

相关文章

制造企业各部门如何参与生产成本控制与管理?

​国内制造业的分量可不轻&#xff0c;从日常生活用品到高端工业设备&#xff0c;中国制造几乎涵盖了各个领域。 不过很多制造业企业在管理方面确实存在一些难题&#xff1a;成本控制不容易&#xff0c;产品质量并不稳定&#xff0c;生产周期也常常较长。 一、中国制造业生产管…

基于SpringBoot+Vue+MySQL的考勤管理系统

系统展示 管理员界面 用户界面 系统背景 随着企业规模的扩大和管理的精细化&#xff0c;传统的考勤方式已经无法满足现代企业的需求。纸质签到、人工统计不仅效率低下&#xff0c;还容易出错。因此&#xff0c;开发一套基于SpringBootVueMySQL的考勤管理系统显得尤为重要。该系…

基于微信小程序医院应急设备管理系统(源码+定制+解答)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

通过ChatGPT 提示词设定60种不同的写作风格

为 ChatGPT 编写正确的提示可以对您获得的响应类型产生很大影响。 您选择的写作风格会影响答案的语气、深度和清晰度。 本指南将帮助您发现 60 多种不同的写作风格,您可以与 ChatGPT 一起使用,以获得更多个性化 ChatGPT Prompt 中的写作风格是什么? ChatGPT 提示中的写作…

html空单元格的占位

先上代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title></head><body> <H1>我的WEB页面</H1><table border"2px" bgcolor"#7fffd4&…

Docker Compose 搭建 nacos 集群

主机准备 IProle192.168.142.155slave02192.168.142.156slave192.168.142.157master192.168.142.158slave03 在 slave03 上面准备 mysql services:mysql:image: mysql:8.0.31container_name: mysqlrestart: alwaysports:- 3306:3306volumes:- /data/nacos/nacos.sql:/data/n…

vue基于Spring Boot框架的高校实验室预约管理系统

目录 毕设制作流程功能和技术介绍系统实现截图开发核心技术介绍&#xff1a;使用说明开发步骤编译运行代码执行流程核心代码部分展示可行性分析软件测试详细视频演示源码获取 毕设制作流程 &#xff08;1&#xff09;与指导老师确定系统主要功能&#xff1b; &#xff08;2&am…

在java后端发送HTTPClient请求

简介 HttpClient遵循http协议的客户端编程工具包支持最新的http协议 部分依赖自动传递依赖了HttpClient的jar包 明明项目中没有引入 HttpClient 的Maven坐标&#xff0c;但是却可以直接使用HttpClient原因是&#xff1a;阿里云的sdk依赖中传递依赖了HttpClient的jar包 发送get请…

HTB:Archetype[WriteUP]

使用OpenVPN连接HTB服务器并启动靶机 靶机IP&#xff1a;10.129.95.187 分配IP&#xff1a;10.10.16.22 1.Which TCP port is hosting a database server? 使用nmap对靶机进行扫描&#xff1a;nmap -sC -sV -T4 -Pn {TARGET_IP} 通过nmap扫描结果可见&#xff1a; 1433 端口用…

C++ | Leetcode C++题解之第448题找到所有数组中消失的数字

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<int> findDisappearedNumbers(vector<int>& nums) {int n nums.size();for (auto& num : nums) {int x (num - 1) % n;nums[x] n;}vector<int> ret;for (int i 0; i < n;…

有效的字母异位词【字符串哈希】

题目 题解&#xff1a; 1.排序&#xff1a; #include<algorithm>class Solution{public:bool isAnagram(string s,string t){sort(s.begin(),s.end());sort(t.begin(),t.end());return st;} } 时间复杂度O(nlogn) 2.哈希表 #include<algorithm>int hash1[100]; …

旅游推荐|旅游推荐系统|基于Springboot+VUE的旅游推荐系统设计与实现(源码+数据库+文档)

旅游推荐系统 目录 基于java的旅游推荐系统设计与实现 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道师&#xf…

B端:常见通用模块有哪些,CRM除了通用模块,有哪些个性模块?

我经常把B端系统的功能模块分为通用模块和个性模块&#xff0c;通用模块是大部分系统都具备的功能&#xff0c;通用模块员工、日程、审批、代办等等&#xff0c;就是OA&#xff0c;通用模块生产、订单、物料、车间、设备、成本等等就是MES&#xff0c;这么说大家都晓得了吧&…

【pytorch】pytorch入门5:最大池化层(Pooling layers )

文章目录 前言一、定义概念 缩写二、参数三、最大池化操作四、使用步骤总结参考文献 前言 使用 B站小土堆课程 一、定义概念 缩写 池化&#xff08;Pooling&#xff09;是深度学习中常用的一种操作&#xff0c;用于降低卷积神经网络&#xff08;CNN&#xff09;或循环神经网…

Vue diff 算法介绍

首先我们来了解一下&#xff1a;diff 是什么&#xff1f; 通俗的讲&#xff0c;diff 就是比较两棵树&#xff0c;render 会生成两颗树&#xff0c;一棵新树 newVnode&#xff0c;一棵旧树 oldVnode&#xff0c;然后两棵树进行对比更新找差异就是 diff&#xff0c;全称 differe…

【cpp/c++ summary 工具】 Hunter 包管理器

Hunter 是一个跨平台cpp包管理器,点击查看支持的所有包的列表。 查看cmake是否满足 查看cmake是否满足Hunter版本要求&#xff1a; ubuntuDESKTOP-D7DRBER:~/CODE/mycpp/hunter-simple-master$ cmake --version cmake version 3.16.3CMake suite maintained and supported b…

88E1111使用技巧

一、88E1111简介 88E1111这款芯片是Marvel公司的产品&#xff0c;算是早期产品&#xff0c;但是市面上通用量较高&#xff0c;目前仍在大量使用&#xff0c;当然该公司也推出新产品&#xff0c;如88E1512&#xff0c;后续会有续篇&#xff0c;本篇文章重点讲述88E1111。 88E1…

66 使用注意力机制的seq2seq_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录动机加入注意力总结代码定义注意力解码器训练小结练习 我们来真的看一下实际应用中&#xff0c;key&#xff0c;value&#xff0c;query是什么东西&#xff0c;但是取决于应用场景不同&#xff0c;这三个东西会产生变化。先将放在seq2seq这个…

使用 SSH 连接 Docker 服务器:IntelliJ IDEA 高效配置与操作指南

使用 SSH 连接 Docker 服务器&#xff1a;IntelliJ IDEA 高效配置与操作指南 本文详细介绍了如何在 2375 端口未开放的情况下&#xff0c;通过 SSH 连接 Docker 服务器并在 Idea 中进行开发。通过修改用户权限、生成密钥对以及配置 SSH 访问&#xff0c;用户可以安全地远程操作…

Ubuntu 系统崩了,如何把数据拷下来

问题描述&#xff1a; Linux系统中安装输入法后&#xff0c;重启后&#xff0c;导致系统无法进入&#xff0c;进入 recovery mode下的resume 也启动不了&#xff0c;所以决定将需要的东西复制到U盘 解决方案&#xff1a; 1.重启ubuntu&#xff0c;随即点按Esc进入grub菜单&am…