制作自己的coco关键点数据集

制作自己的coco关键点数据集

1、将我们需要标注的图片进行重命名,由于coco数据集图片的名称是12位数字,形式如 00000000001。代码如下:

import os
from tqdm import tqdm
import codecs
import json
for root, _, path in os.walk(<保存图片的文件夹路径>):
    for s in tqdm(path):
        os.renames('<保存图片的文件夹路径>/{}'.format(s), 'dataset_new/%012d.jpg' %int(s.split('.')[0]))

2、使用labelme标注软件进行数据集的标注。(labelme是专门用来标注的软件)直接pip install 即可。

使用labelme进行关键点标注前,我们需要明确我们需要的关节点有哪些,例如coco数据集中关键点如下:

一共17个关节点

一共是17 个关节点,注意使用labelme标注的时候,序号是从1开始的,最后就是标注啦,数据集的标注自认为是最浪费时间的,但是我们一定得仔细,否则后面的训练就会很麻烦!标注后会生成对应的json文件,如下:json数据

3、将label标注数据集进行格式转换,转换成coco格式

最后因为目前的大多数网络都是用的coco数据集,因此我们需要将数据集转换成coco数据集格式,在标注之前我们同样需要将json文件的名称改为 000000000011 这种格式,代码参见以上。转换代码如下:
import numpy as np
import json
import glob
import codecs
import os

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)


class tococo(object):
    def __init__(self, jsonfile, save_path, a):
        self.images = []
        self.categories = [
            {
                "supercategory": "person",
                "id": 1,
                "name": "person",
                "keypoints":
                    [
                        "nose",
                        "left_ear",
                        "right_ear",
                        "left_shoulder",
                        "right_shoulder",
                        "left_elbow",
                        "right_elbow",
                        "left_wrist",
                        "right_wrist"
                    ],
                "skeleton": [
                    [6, 8],
                    [4, 6],
                    [2, 4],
                    [1, 2],
                    [3, 1],
                    [5, 3],
                    [7, 5],
                    [9, 7],
                ]
            }
        ]
        self.annotations = []
        self.jsonfile = os.listdir(jsonfile)
        self.save_path = save_path  # 保存json的路径
        self.class_id = a  # class  我们的类别只有一个 person
        self.coco = {}
        self.path = jsonfile

    def labelme_to_coco(self):
        for num, json_file in enumerate(self.jsonfile):
            json_file = os.path.join(self.path, json_file)
            data = codecs.open(json_file, 'r')
            data = json.load(data)
            self.images.append(self.get_images(json_file[-17:-4] + 'jpg', data["imageHeight"], data["imageWidth"]))
            shapes = data["shapes"]
            annotation = {}  # 一个annotation代表一张图片中的所有samples
            num_keypoints = 0
            keypoints = [0] * 3 * 9  #这里是我们标注的关节点个数
            flag = 0
            for shape in shapes:
                if shape['shape_type'] == 'rectangle' or shape["label"] == '90' or shape["label"] == '99':
                    bbox = []
                    temp = shape["points"]
                    try:
                        x_min = min(temp[0][0], temp[1][0])
                    except IndexError as e:
                        print('class: {}, image: {}'.format(self.class_id, int(json_file[-17:-5])))

                    x_max = max(temp[0][0], temp[1][0])
                    y_min = min(temp[0][1], temp[1][1])
                    y_max = max(temp[0][1], temp[1][1])
                    bbox.append(x_min)
                    bbox.append(y_min)
                    w = x_max - x_min + 1
                    h = y_max - y_min + 1
                    bbox.append(w)
                    bbox.append(h)
                    annotation['bbox'] = bbox
                    flag = flag + 1
                else:
                    idx = int(shape['label'])

                    try:
                        keypoints[(idx - 1) * 3 + 0] = shape['points'][0][0]
                        keypoints[(idx - 1) * 3 + 1] = shape['points'][0][1]
                        keypoints[(idx - 1) * 3 + 2] = 2
                        num_keypoints = num_keypoints + 1
                    except IndexError as e:
                        print('class: {}, image: {}'.format(self.class_id, int(json_file[-17:-5])))

            if flag == 0:
                print('{}\\{} does not contain bbox\n'.format(self.class_id, json_file))
            annotation['segmentation'] = [[]]
            annotation['num_keypoints'] = num_keypoints
            try:
                annotation['area'] = 0
            except ValueError as e:
                print(json_file[-17:-5])
                # print(w, h)
            annotation['iscrowd'] = 0
            annotation['keypoints'] = keypoints
            annotation['image_id'] = int(json_file[-17:-5])  # 对应的图片ID
            annotation['bbox'] = [0, 0, data['imageWidth'], data['imageHeight']]
            annotation['category_id'] = 1
            annotation['id'] = int(json_file[-17:-5])  # 对象id
            self.annotations.append(annotation)
            self.image_id = int(json_file[-17:-5])

        self.coco["images"] = self.images
        self.coco["categories"] = self.categories
        self.coco["annotations"] = self.annotations



    def get_images(self, filename, height, width):
        image = {}
        image["height"] = height
        image['width'] = width
        image["id"] = int(filename[-16:-4])
        image["file_name"] = filename
        return image

    def get_categories(self, name, class_id):
        category = {}
        category["supercategory"] = "person"
        category['id'] = class_id
        category['name'] = name
        return category

    def save_json(self):
        self.labelme_to_coco()
        coco_data = self.coco
        # 保存json文件
        json.dump(coco_data, open(self.save_path, 'w'), indent=4, cls=MyEncoder)  # indent=4 更加美观显示
        return self.image_id


json_path = r'J:\keypoint_own/label_val'   #保存json的文件夹路径
c = tococo(json_path, save_path='val.json', a=1)  #我们将我们的左右json文件合成为一个json文件,这是最后json文件的名称
image_id = c.save_json()

4、使用coco api验证我们转换后的格式是否正确,代码如下:

# !/usr/bin python3                                 
# encoding    : utf-8 -*-                            
# @author     :   liangjian                               
# @software   : PyCharm      
# @file       :   0408.py
# @Time       :   2021/4/8 21:51
import skimage.io as io
import pylab
import time as time
import json
import numpy as np
from collections import defaultdict
import itertools
import matplotlib.pyplot as plt
from matplotlib.collections import PatchCollection


def _isArrayLike(obj):
    return hasattr(obj, '__iter__') and hasattr(obj, '__len__')


class COCO:
    def __init__(self, annotation_file=None):
        """
        Constructor of Microsoft COCO helper class for reading and visualizing annotations.
        :param annotation_file (str): location of annotation file
        :param image_folder (str): location to the folder that hosts images.
        :return:
        """
        # load dataset
        self.dataset, self.anns, self.cats, self.imgs = dict(), dict(), dict(), dict()
        self.imgToAnns, self.catToImgs = defaultdict(list), defaultdict(list)
        if not annotation_file == None:
            print('loading annotations into memory...')
            tic = time.time()
            dataset = json.load(open(annotation_file, 'r'))
            assert type(dataset) == dict, 'annotation file format {} not supported'.format(type(dataset))
            print('Done (t={:0.2f}s)'.format(time.time() - tic))
            self.dataset = dataset
            self.createIndex()

    def createIndex(self):
        # create index
        print('creating index...')
        anns, cats, imgs = {}, {}, {}
        imgToAnns, catToImgs = defaultdict(list), defaultdict(list)
        if 'annotations' in self.dataset:
            for ann in self.dataset['annotations']:
                imgToAnns[ann['image_id']].append(ann)
                anns[ann['id']] = ann

        if 'images' in self.dataset:
            for img in self.dataset['images']:
                imgs[img['id']] = img

        if 'categories' in self.dataset:
            for cat in self.dataset['categories']:
                cats[cat['id']] = cat

        if 'annotations' in self.dataset and 'categories' in self.dataset:
            for ann in self.dataset['annotations']:
                catToImgs[ann['category_id']].append(ann['image_id'])

        print('index created!')

        # create class members
        self.anns = anns
        self.imgToAnns = imgToAnns
        self.catToImgs = catToImgs
        self.imgs = imgs
        self.cats = cats

    def getCatIds(self, catNms=[], supNms=[], catIds=[]):
        """
        filtering parameters. default skips that filter.
        :param catNms (str array)  : get cats for given cat names
        :param supNms (str array)  : get cats for given supercategory names
        :param catIds (int array)  : get cats for given cat ids
        :return: ids (int array)   : integer array of cat ids
        """
        catNms = catNms if _isArrayLike(catNms) else [catNms]
        supNms = supNms if _isArrayLike(supNms) else [supNms]
        catIds = catIds if _isArrayLike(catIds) else [catIds]

        if len(catNms) == len(supNms) == len(catIds) == 0:
            cats = self.dataset['categories']

        else:
            cats = self.dataset['categories']
            # print(' ')
            # print('keypoints的cat就只有人1种')
            # print(cats)
            cats = cats if len(catNms) == 0 else [cat for cat in cats if cat['name'] in catNms]
            cats = cats if len(supNms) == 0 else [cat for cat in cats if cat['supercategory'] in supNms]
            cats = cats if len(catIds) == 0 else [cat for cat in cats if cat['id'] in catIds]
            # print(cats)
        ids = [cat['id'] for cat in cats]
        return ids

    def loadCats(self, ids=[]):
        """
        Load cats with the specified ids.
        :param ids (int array)       : integer ids specifying cats
        :return: cats (object array) : loaded cat objects
        """
        if _isArrayLike(ids):
            return [self.cats[id] for id in ids]
        elif type(ids) == int:
            return [self.cats[ids]]

    def getImgIds(self, imgIds=[], catIds=[]):
        '''
        Get img ids that satisfy given filter conditions.
        :param imgIds (int array) : get imgs for given ids
        :param catIds (int array) : get imgs with all given cats
        :return: ids (int array)  : integer array of img ids
        '''
        imgIds = imgIds if _isArrayLike(imgIds) else [imgIds]
        catIds = catIds if _isArrayLike(catIds) else [catIds]

        if len(imgIds) == len(catIds) == 0:
            ids = self.imgs.keys()
        else:
            ids = set(imgIds)
            for i, catId in enumerate(catIds):
                if i == 0 and len(ids) == 0:
                    ids = set(self.catToImgs[catId])
                else:
                    ids &= set(self.catToImgs[catId])
        return list(ids)

    def loadImgs(self, ids=[]):
        """
        Load anns with the specified ids.
        :param ids (int array)       : integer ids specifying img
        :return: imgs (object array) : loaded img objects
        """
        if _isArrayLike(ids):
            return [self.imgs[id] for id in ids]
        elif type(ids) == int:
            return [self.imgs[ids]]

    def getAnnIds(self, imgIds=[], catIds=[], areaRng=[], iscrowd=None):
        """
        Get ann ids that satisfy given filter conditions. default skips that filter
        :param imgIds  (int array)     : get anns for given imgs
               catIds  (int array)     : get anns for given cats
               areaRng (float array)   : get anns for given area range (e.g. [0 inf])
               iscrowd (boolean)       : get anns for given crowd label (False or True)
        :return: ids (int array)       : integer array of ann ids
        """
        imgIds = imgIds if _isArrayLike(imgIds) else [imgIds]
        catIds = catIds if _isArrayLike(catIds) else [catIds]

        if len(imgIds) == len(catIds) == len(areaRng) == 0:
            anns = self.dataset['annotations']
        else:
            # 根据imgIds找到所有的ann
            if not len(imgIds) == 0:
                lists = [self.imgToAnns[imgId] for imgId in imgIds if imgId in self.imgToAnns]
                anns = list(itertools.chain.from_iterable(lists))
            else:
                anns = self.dataset['annotations']
            # 通过各类条件如catIds对anns进行筛选
            anns = anns if len(catIds) == 0 else [ann for ann in anns if ann['category_id'] in catIds]
            anns = anns if len(areaRng) == 0 else [ann for ann in anns if
                                                   ann['area'] > areaRng[0] and ann['area'] < areaRng[1]]
        if not iscrowd == None:
            ids = [ann['id'] for ann in anns if ann['iscrowd'] == iscrowd]
        else:

            ids = [ann['id'] for ann in anns]
        return ids

    def loadAnns(self, ids=[]):
        """
        Load anns with the specified ids.
        :param ids (int array)       : integer ids specifying anns
        :return: anns (object array) : loaded ann objects
        """
        if _isArrayLike(ids):
            return [self.anns[id] for id in ids]
        elif type(ids) == int:
            return [self.anns[ids]]

    def showAnns(self, anns):
        """
        Display the specified annotations.
        :param anns (array of object): annotations to display
        :return: None
        """
        if len(anns) == 0:
            return 0
        if 'segmentation' in anns[0] or 'keypoints' in anns[0]:
            datasetType = 'instances'
        elif 'caption' in anns[0]:
            datasetType = 'captions'
        else:
            raise Exception('datasetType not supported')
        if datasetType == 'instances':
            ax = plt.gca()
            ax.set_autoscale_on(False)
            polygons = []
            color = []
            for ann in anns:
                c = (np.random.random((1, 3)) * 0.6 + 0.4).tolist()[0]
                # if 'segmentation' in ann:
                #     if type(ann['segmentation']) == list:
                #         # polygon
                #         for seg in ann['segmentation']:
                #             poly = np.array(seg).reshape((int(len(seg)/2), 2))
                #             polygons.append(Polygon(poly))
                #             color.append(c)
                #     else:
                #         # mask
                #         t = self.imgs[ann['image_id']]
                #         if type(ann['segmentation']['counts']) == list:
                #             rle = maskUtils.frPyObjects([ann['segmentation']], t['height'], t['width'])
                #         else:
                #             rle = [ann['segmentation']]
                #         m = maskUtils.decode(rle)
                #         img = np.ones( (m.shape[0], m.shape[1(余下全部)], 3(from 1, 10张取一张)) )
                #         if ann['iscrowd'] == 1(余下全部):
                #             color_mask = np.array([2.0,166.0,101.0])/255
                #         if ann['iscrowd'] == 0:
                #             color_mask = np.random.random((1(余下全部), 3(from 1, 10张取一张))).tolist()[0]
                #         for i in range(3(from 1, 10张取一张)):
                #             img[:,:,i] = color_mask[i]
                #         ax.imshow(np.dstack( (img, m*0.5) ))
                if 'keypoints' in ann and type(ann['keypoints']) == list:
                    # turn skeleton into zero-based index
                    sks = np.array(self.loadCats(ann['category_id'])[0]['skeleton']) - 1
                    kp = np.array(ann['keypoints'])
                    x = kp[0::3]
                    y = kp[1::3]
                    v = kp[2::3]
                    for sk in sks:
                        if np.all(v[sk] > 0):
                        #     # 画点之间的连接线
                            plt.plot(x[sk], y[sk], linewidth=1, color=c)
                    # 画点
                    plt.plot(x[v > 0], y[v > 0], 'o', markersize=4, markerfacecolor=c, markeredgecolor='k',
                             markeredgewidth=1)
                    plt.plot(x[v > 1], y[v > 1], 'o', markersize=4, markerfacecolor=c, markeredgecolor=c,
                             markeredgewidth=1)
            p = PatchCollection(polygons, facecolor=color, linewidths=0, alpha=0.4)
            ax.add_collection(p)
            p = PatchCollection(polygons, facecolor='none', edgecolors=color, linewidths=2)
            ax.add_collection(p)
        elif datasetType == 'captions':
            for ann in anns:
                print(ann['caption'])


pylab.rcParams['figure.figsize'] = (8.0, 10.0)

annFile = r'J:\keypoint_own\val.json'     #转换之后的json文件路径
img_prefix = 'J:\keypoint_own\pic_val'	#图片文件夹路径

# initialize COCO api for instance annotations
coco = COCO(annFile)

# getCatIds(catNms=[], supNms=[], catIds=[])
# 通过输入类别的名字、大类的名字或是种类的id,来筛选得到图片所属类别的id
catIds = coco.getCatIds(catNms=['person'])
# getImgIds(imgIds=[], catIds=[])
# 通过图片的id或是所属种类的id得到图片的id
imgIds = coco.getImgIds(catIds=catIds)
# imgIds = coco.getImgIds(imgIds=[1407])

# loadImgs(ids=[])
# 得到图片的id信息后,就可以用loadImgs得到图片的信息了
# 在这里我们随机选取之前list中的一张图片
img = coco.loadImgs(imgIds[np.random.randint(0, len(imgIds))])[0]
I = io.imread('%s/%s' % (img_prefix, img['file_name']))
plt.imshow(I)
plt.axis('off')
ax = plt.gca()

# getAnnIds(imgIds=[], catIds=[], areaRng=[], iscrowd=None)
# 通过输入图片的id、类别的id、实例的面积、是否是人群来得到图片的注释id
annIds = coco.getAnnIds(imgIds=img['id'], catIds=catIds, iscrowd=None)

# loadAnns(ids=[])
# 通过注释的id,得到注释的信息
anns = coco.loadAnns(annIds)
print('anns:', anns)

coco.showAnns(anns)
plt.imshow(I)
plt.axis('off')
plt.show()
如果我们能在最后的验证代码中能够显示出我们标注好的图片即为成功啦,当然,这只是数据集的制作,后面还有还长的路要走,各位加油!
  • 10
    点赞
  • 95
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 94
    评论
为了制作yolov8关键点数据集,你需要完成以下步骤: 1. 首先,你需要将coco格式的JSON文件转换成yolo的txt文件。你可以使用coco2yolo.py脚本来完成这个转换。这个脚本会将coco格式的JSON文件中的关键点数据转换成yolo格式的txt文件。 2. 接下来,你需要更改yaml数据文件,将训练、验证和测试图像的路径设置为正确的路径。你还需要在yaml文件中定义类别的名称和对应的编号。 3. 下载包含实例和语义分割标签的训练和验证图像。这些图像可以从百度网盘中获取。训练图像包括1411张原始图像、1411张实例标签和1411张语义标签。验证图像包括458张原始图像、458张实例标签和458张语义标签。 4. 将所有的训练图像放置在一个文件夹中,创建iSAID/train/文件夹。将所有的验证图像放置在另一个文件夹中,创建iSAID/val/文件夹。 5. 最后,你可以对图像进行切割并生成相应的标签。 这样,你就完成了yolov8关键点数据集制作。 #### 引用[.reference_title] - *1* [Yolopose关键点检测:自己标注数据集制作数据集(二)](https://blog.csdn.net/m0_57458432/article/details/128222620)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [YOLOv5训练大规模的遥感实例分割数据集 iSAID从切图到数据集制作及训练](https://blog.csdn.net/weixin_45798949/article/details/129443725)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 94
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Begin,again

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值