COCO数据集图片标注小工具

最近深度学习,用到COCO数据集,需要对图片进行一些标注例如:添加矩形框并标注类型、添加字幕、添加人体关键点、添加关键物体的掩膜(mask)、添加关键物体的外轮廓等。经过在网上的搜索整理,做出了自认为比较实用的的小工具,特进行记录并共享给网友。

import os, time
from pycocotools.coco import COCO
from random import random
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image, ImageDraw, ImageFont
import cv2

def pic_caption(coco, pic_id, i_path, s_path, position,color_n, t_size, delay_t):
    print("make captions.......................................................")
    ann_ids = coco.getAnnIds(imgIds=pic_id)
    # 根据annotations idx信息获取所有标注信息
    targets = coco.loadAnns(ann_ids)
    # get image file name
    path = coco.loadImgs(pic_id)[0]['file_name']
    # read image
    img = Image.open(os.path.join(i_path, path)).convert('RGB')
    width, height = img.size
    draw = ImageDraw.Draw(img)
    x = 0
    n = 0
    for ann in targets:
        font = ImageFont.truetype('arial.ttf', size=t_size)
        if "up" in position:
            draw.text((x, 0 + n * (t_size + 3)), ann['caption'], fill=color_n, font=font)  # 定义文字内容,fill 为字体颜色(r,g,b)
        elif "down" in position:
            draw.text((x, height - (n+1) * (t_size + 3)), ann['caption'], fill=color_n, font=font)  # 定义文字内容,fill 为字体颜色(r,g,b)
        n += 1
    plt.figure(path)
    plt.imshow(img)
    plt.show(block=False)
    plt.ion()
    plt.pause(delay_t)
    plt.close()
    img.save(s_path + path[:-4]  + '_caption'+ '.jpg')  # 另存加上了框框的图片


def pic_rect(coco, pic_id, i_path, s_path, color_n, t_size, delay_t):
    print("make rectangle.......................................................")
    coco_classes = dict([(v["id"], v["name"]) for k, v in coco.cats.items()])
    # 获取对应图像id的所有annotations idx信息
    ann_ids = coco.getAnnIds(imgIds=pic_id)
    # 根据annotations idx信息获取所有标注信息
    targets = coco.loadAnns(ann_ids)
    # get image file name
    path = coco.loadImgs(pic_id)[0]['file_name']
    # read image
    img = Image.open(os.path.join(i_path, path)).convert('RGB')
    draw = ImageDraw.Draw(img)
    # draw box to image
    color_list = ['red', 'blue', 'green', 'yellow', 'orange', 'pink', 'brown', 'navy', 'gold', 'tomato', 'maroon',
                  'red', 'blue', 'green', 'yellow', 'orange', 'pink', 'brown', 'navy', 'gold', 'tomato', 'maroon',
                  'red', 'blue', 'green', 'yellow', 'orange', 'pink', 'brown', 'navy', 'gold', 'tomato', 'maroon',
                  'red', 'blue', 'green', 'yellow', 'orange', 'pink', 'brown', 'navy', 'gold', 'tomato', 'maroon',
                  'red', 'blue', 'green', 'yellow', 'orange', 'pink', 'brown', 'navy', 'gold', 'tomato', 'maroon',
                  'red', 'blue', 'green', 'yellow', 'orange', 'pink', 'brown', 'navy', 'gold', 'tomato', 'maroon', ]
    n = 0
    for target in targets:
        x, y, w, h = target["bbox"]
        x1, y1, x2, y2 = x, y, int(x + w), int(y + h)
        draw.rectangle((x1, y1, x2, y2), outline=color_list[n],
                       width=3)  # outline  是外框颜色,可自己定义,这里是循环调用了一个数组,whdth为框线的粗细。
        font = ImageFont.truetype('arial.ttf', size=t_size)  # 定义字体,文字大小
        draw.text((x1, y1), coco_classes[target["category_id"]], fill=color_n, font=font)  # 定义文字内容,fill 为字体颜色(r,g,b)
        n += 1

    plt.figure(path)
    plt.imshow(img)
    plt.show(block=False)
    plt.ion()
    plt.pause(delay_t)
    plt.close()
    img.save(s_path  + path[:-4] + '_rect'+ '.jpg')  # 另存加上了框框的图片


def pic_mask(coco, pic_id, i_path, s_path, str=' ', delay_t=1):
    print("make mask.......................................................")
    # 需要画图的是第num副图片, 对应的json路径和图片路径,
    # str = ' '为类别字符串,输入必须为字符串形式 'str',若为空,则返回所有类别id
    catIds = coco.getCatIds(catNms=['str'])  # 获取指定类别 id
    path = coco.loadImgs(pic_id)[0]['file_name']  # 加载图片,loadImgs() 返回的是只有一个内嵌字典元素的list, 使用[0]来访问这个元素
    image = cv2.imread(os.path.join(i_path, path))
    annIds = coco.getAnnIds(imgIds=pic_id, catIds=catIds, iscrowd=None)
    anns = coco.loadAnns(annIds)
    zeros = np.zeros((image.shape), dtype=np.uint8)
    alpha = 1
    beta = 0.6
    gamma = 0
    for ann in anns:
        segs = ann['segmentation']
        if 'list' in type(segs).__name__:
            for seg in segs:
                poly = []
                c_out = (250, 0, 0)
                c_in = (int(random() * 255), int(random() * 255), int(random() * 255))
                for i in range(int(len(seg) / 2)):
                    poly.append([seg[i * 2], seg[i * 2 + 1]])
                poly_ = np.reshape(np.array(poly), [-1, 1, 2]).astype(np.int32)
                image = cv2.polylines(np.array(image), [poly_], True, c_out, 2, )
                mask = cv2.fillPoly(zeros, [poly_], color=c_in, )
                mask_img = cv2.addWeighted(image, alpha, mask, beta, gamma)
        else:
            pass
    cv2.imshow(path, mask_img)
    cv2.waitKey(delay_t * 1000)
    cv2.destroyAllWindows()
    cv2.imwrite(s_path + path[:-4] + '_mask' + '.png', mask_img)


def pic_person_key_point(coco, img_id, i_path, s_path, delay_t):
    print("make person_keypoint.......................................................")
    catIds = coco.getCatIds(catNms=['person'])
    aColor = [(0, 255, 0, 0), (255, 0, 0, 0), (0, 0, 255, 0), (0, 255, 255, 0)]
    path = coco.loadImgs(img_id)[0]['file_name']
    matImg = Image.open('%s/%s' % (i_path, path)).convert('RGB')
    draw = ImageDraw.Draw(matImg)
    # # 通过输入图片的id、类别的id、实例的面积、是否是人群来得到图片的注释id
    annIds = coco.getAnnIds(imgIds=img_id, catIds=catIds, iscrowd=None)
    # # 通过注释的id,得到注释的信息
    anns = coco.loadAnns(annIds)
    if len(anns) != 0:
        for ann in anns:
            sks = np.array(coco.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:
                c = aColor[np.random.randint(0, 4)]
                if np.all(v[sk] > 0):
                    # 画点之间的连接线
                    draw.line([(x[sk][0], y[sk][0]), (x[sk][1], y[sk][1])], c, 3)
            for i in range(x.shape[0]):
                draw.ellipse((x[i] - 3, y[i] - 3, x[i] + 3, y[i] + 3), fill=(0, 255, 0), outline=(255, 0, 0))
        plt.figure(path)
        plt.imshow(matImg)
        plt.show(block=False)
        plt.ion()
        plt.pause(delay_t)
        plt.close()
        matImg.save(s_path + path[:-4]  + '_pkp'+ '.jpg')  # 另存加上了框框的图片


def pic_polygon(coco, pic_id, i_path, s_path, str=' ', delay_t=1):
    print("make polygon.......................................................")
    # str = ' '为类别字符串,输入必须为字符串形式 'str',若为空,则返回所有类别id
    catIds = coco.getCatIds(catNms=['str'])  # 获取指定类别 id
    path = coco.loadImgs(pic_id)[0]['file_name']  # 加载图片,loadImgs() 返回的是只有一个内嵌字典元素的list, 使用[0]来访问这个元素
    image = cv2.imread(os.path.join(i_path, path))
    annIds = coco.getAnnIds(imgIds=pic_id, catIds=catIds, iscrowd=None)
    anns = coco.loadAnns(annIds)
    for ann in anns:
        segs = ann['segmentation']
        if 'list' in type(segs).__name__:
            for seg in segs:
                poly = []
                c_out = (int(random() * 100), int(random() * 100), int(random() * 100))
                for i in range(int(len(seg) / 2)):
                    poly.append([seg[i * 2], seg[i * 2 + 1]])
                poly_ = np.reshape(np.array(poly), [-1, 1, 2]).astype(np.int32)
                image = cv2.polylines(np.array(image), [poly_], True, c_out, 3, )

        else:
            pass
    cv2.imshow(path, image)
    cv2.waitKey(delay_t * 1000)
    cv2.destroyAllWindows()
    cv2.imwrite(s_path + path[:-4] + '_poly' + '.jpg', image)


if __name__ == "__main__":
    year = 2014
    pic_path = 'val'

    cap_file = 'C:/coco_data/annotations/captions_' + pic_path + str(year) + '.json'
    json_file = 'C:/coco_data/annotations/instances_' + pic_path + str(year) + '.json'
    pkp_file = 'C:/coco_data/annotations/person_keypoints_' + pic_path + str(year) + '.json'
    img_path = 'C:/coco_data/' + pic_path + str(year)
    save_path = 'C:/coco_data/result_test/'

    ids = [559665,391895,60623,483108,384213,386164,223648,403385,294832,462565,436141,192440,1146,394240, ]
    delay = 1

    coco_j = COCO(json_file)
    coco_c = COCO(cap_file)
    coco_p = COCO(pkp_file)

    for id in ids:
        print(id, '    ', coco_j.loadImgs(id)[0]['file_name'])
        pic_person_key_point(coco_p, id, img_path, save_path, delay_t=delay)
        pic_caption(coco_c, id, img_path, save_path, position="down",color_n=(0, 0, 255), t_size=18, delay_t=delay)
        pic_mask(coco_j, id, img_path, save_path, str='', delay_t=delay)
        pic_rect(coco_j, id, img_path, save_path, color_n=(0, 0, 255), t_size=18, delay_t=delay)
        pic_polygon(coco_j, id, img_path, save_path, str='', delay_t=delay)

运行结果图片如下:

<think>好的,我现在要处理用户关于COCO数据集标注格式和下载的问题。首先,用户提供的引用内容提到了三种标注类型:目标实例、关键点和图像描述,使用JSON格式。我需要根据这些信息来组织回答,同时确保符合系统级指令的要求,比如使用正确的LaTeX格式和生成相关问题。 首先,用户想知道如何下载标注文件或了解其格式。根据引用内容,COCO标注文件是JSON结构,包含多个标注类型。我需要分点说明每种类型的具体结构,比如object instances中的categories、images、annotations等部分。同时,要提到每个字段的含义,例如image_id、bbox、category_id等。 接下来,下载方式部分,我需要确认官方网站的地址是否正确,用户可能需要直接访问COCO的官网获取最新链接。另外,GitHub数据仓库也是一个可靠的来源,需要提供具体的URL,比如https://github.com/cocodataset/cocoapi。此外,通过API工具下载的方法可能对用户有帮助,特别是使用Python脚本的情况,这里需要给出示例代码,并确保代码正确无误。 在格式说明部分,必须详细解释每个JSON字段,例如categories中的id和name,images中的file_name、height、width,annotations中的id、bbox、area等。特别是bbox的格式,要明确是[x_top_left, y_top_left, width, height]。此外,segmentation字段可能需要区分多边形和RLE格式,特别是对于crowd的情况。 用户可能对具体的示例感兴趣,所以需要提供一个简化的JSON示例,展示不同部分的结构,比如一个包含两个类别和几个图像及标注的例子。这样可以帮助用户更直观地理解格式。 关于注意事项,版本差异和标注类型是需要强调的,不同年份的数据集可能有变化,用户需要根据需求选择正确的版本和标注类型。此外,文件大小也是一个实际问题,特别是对于网络状况不好的用户,可能需要提前了解文件大小。 生成的相关问题需要围绕用户可能进一步关心的点,比如与其它数据集的区别、标注工具、处理方法和常见错误,这些都能帮助用户更深入地使用COCO数据集。 最后,检查所有LaTeX格式是否正确,确保行内公式使用$...$,独立公式使用$$...$$,虽然在这个问题中可能用不到数学公式,但需要留意是否有需要的地方。同时,引用标识要正确添加,用户提供的引用[1]和[2]要放在适当的位置,比如在介绍标注类型时引用[^1],在结构说明时引用[^2]。 总结一下,回答的结构应该是先介绍标注格式,分类型详细说明,然后提供下载方式,接着给出格式说明和示例,最后注意事项和相关问题。确保每个部分清晰,符合用户的需求,并且信息准确可靠。</think>以下是对COCO数据集标注文件格式及下载方式的详细说明: ### 一、COCO数据集标注格式 COCO数据集采用JSON格式存储标注信息,包含3种核心标注类型[^1]: 1. **目标实例(Object Instances)** - 包含$80$个物体类别 - 标注字段:`categories`(类别定义)、`images`(图像元数据)、`annotations`(物体位置信息) - 边界框使用$[x_{\text{top-left}}, y_{\text{top-left}}, width, height]$格式 2. **关键点检测(Keypoints)** - 包含$17$个人体关键点 - 每个关键点标注包括坐标$(x,y)$和可见性状态$v \in \{0,1,2\}$ 3. **图像描述(Captions)** - 每张图像对应$5$条文字描述 - 使用自然语言描述图像内容 ### 二、标注文件下载方式 1. **官方网站下载** - 访问[cocodataset.org](https://cocodataset.org) - 选择需要的年份版本(2014/2017/2020) - 下载标注文件如`annotations_trainval2017.zip` 2. **GitHub数据仓库** ```bash git clone https://github.com/cocodataset/cocoapi ``` 包含标注文件示例和解析工具 3. **通过API工具下载** ```python from pycocotools.coco import COCO coco = COCO('annotations/instances_train2017.json') ``` ### 三、标注格式详细说明 以目标实例为例,JSON结构包含: ```json { "info": {"description": "COCO 2017 Dataset"}, "licenses": [{"id": 1, "name": "CC BY 4.0"}], "categories": [ {"id": 1, "name": "person", "supercategory": "living"}, {"id": 2, "name": "bicycle", "supercategory": "vehicle"} ], "images": [ {"id": 1, "file_name": "000001.jpg", "width": 640, "height": 480} ], "annotations": [ { "id": 1, "image_id": 1, "category_id": 1, "bbox": [100, 200, 50, 80], "area": 4000, "iscrowd": 0 } ] } ``` ### 四、注意事项 1. **版本差异**:2014版包含$82,783$张训练图,2017版扩充到$118,000$张 2. **标注类型**:`panoptic`(全景分割)标注需要单独下载 3. **文件大小**:完整标注文件约$25$GB(含图像)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值