COCO 數據集的使用

1 簡介

微軟發佈的 COCO 數據庫是一個大型圖像數據集, 專爲對象檢測、分割、人體關鍵點檢測、語義分割和字幕生成而設計。html

COCO 數據庫的網址是:python

  • MS COCO 數據集主頁:http://mscoco.org/
  • Github 網址:https://github.com/Xinering/cocoapi
  • 關於 API 更多的細節在網站: http://mscoco.org/dataset/#download

COCO API 提供了 Matlab, Python 和 Lua 的 API 接口. 該 API 接口能夠提供完整的圖像標籤數據的加載, parsing 和可視化。此外,網站還提供了數據相關的文章, 教程等。git

在使用 COCO 數據庫提供的 API 和 demo 以前, 須要首先下載 COCO 的圖像和標籤數據(類別標誌、類別數量區分、像素級的分割等 ):github

  • 圖像數據下載到 coco/images/ 文件夾中
  • 標籤數據下載到 coco/annotations/ 文件夾中

下面咱們來探討一下如何利用 Python 來使用 COCO 數據集?數據庫


COCO API 對 WIndows 系統不是太友好,首先我先是 fork 了 COCO API,而後下載到本地,並切換到:D:\API\cocoapi\PythonAPIjson

cd D:\API\cocoapi\PythonAPI

打開 Makefile 能夠看到 API 的安裝和使用說明。api

在 Windows 下直接運行 python setup.py build_ext --inplace 會報錯:數組

Windows 中 (通常須要安裝 visual studio)有許多的坑,參考 Windows 10 編譯 Pycocotools 踩坑記 暴力刪掉參數 Wno-cppWno-unused-function,以下圖所示:app

這樣,咱們即可以使用 pycocotools,不過每次你想要調用 pycocotools 都須要先載入局部環境:dom

import sys
sys.path.append('D:\API\cocoapi\PythonAPI')   # 將你的 `pycocotools` 所在路徑添加到系統環境

若是你不想這麼麻煩,你能夠直接將 pycocotools 安裝在你的主環境下:

先切換到包所在路徑

cd D:\API\cocoapi\PythonAPI

而後,運行

python setup.py build_ext install
rd build   # 刪除

在 Linux 下,不須要上面這麼多編譯步驟,咱們直接在終端輸入下列命令便可正常使用 COCO API:

pip3 install -U Cython
pip3 install -U pycocotools

下面你即可載入 pycocotools 了。

2 COCO API

COCO API 能夠幫助你載入、解析和可視化 annotations。 該 API 支持 multiple annotation 格式 (詳情見 data format). 更多關於 API 的細節可參考 coco.py,同時你也能夠查看 Python API demo

COCO API 的記號說明:

COCO

3 MASK API

COCO 爲每一個實例對象提供分割掩碼(segmentation masks)。這就產生了兩個挑戰: 緊湊地存儲掩碼和高效地執行掩碼計算。 MASK API 使用自定義運行長度編碼 (Run Length Encoding, RLE) 方案解決這兩個難題。RLE 表示的大小與掩碼的邊界像素數成正比, 而且能夠在 RLE 上直接有效地計算操做 (如面積、聯合或交集)。具體來講, 假設 shapes 至關簡單, RLE 表示形式爲 \(O(\sqrt{n}\), 其中 \(n\) 是對象中的像素數, 而一般計算量一樣是 \(O(\sqrt{n})\)。在解碼掩碼 (存儲爲陣列) 上進行相同操做的天然的計算量將是 \(O(n)\)

Mask API 提供了一個用於操做以 RLE 格式存儲的掩碼的接口。這個 API 被定義在 mask.py。最後, 大多數 ground truth masks 存儲爲多邊形 (至關緊湊), 這些多邊形在須要時轉換爲 RLE。

MASK

下面咱們來解讀一下 pycocoDemo.ipynb。因爲 COCO API 對 Windows 不是那麼友好,爲了不去調試各類 Bug,下面咱們先在 Linux 系統下來使用 COCO API。下面我是在 Jupyter Notebook 下運行代碼的。

4 pycocoDemo.ipynb 解讀

%matplotlib inline
import zipfile
import os
import numpy as np
import skimage.io as io
import matplotlib.pyplot as plt
import pylab
pylab.rcParams['figure.figsize'] = (8.0, 10.0)

# -------------------
try:       # pycocotools 已經加入了全局環境變量中
    from pycocotools.coco import COCO
except ModuleNotFoundError:
    import sys
    # 加載 COCO API 環境
    sys.path.append('D:\API\cocoapi\PythonAPI')
    from pycocotools.coco import COCO

root = 'E:/Data/coco'  # 你下載的 COCO 數據集所在目錄

# 查看 images 下的圖片
os.listdir(f'{root}/images')
['test2014.zip',
 'test2015.zip',
 'test2017.zip',
 'train2014.zip',
 'train2017.zip',
 'unlabeled2017.zip',
 'val2014.zip',
 'val2017.zip']

下面我以 val2017.zip 圖片數據集爲例,來講明下面的一些問題。

Z = zipfile.ZipFile(f'{root}/images/val2017.zip')
Z.namelist()[7]   # 查看一張圖片的文件名
'val2017/000000463918.jpg'

因爲 Z.read 函數返回的是 bytes,因此,咱們須要藉助一些其餘模塊來將圖片數據轉換爲 np.uint8 形式。

img_b = Z.read(Z.namelist()[7])
print(type(img_b))
<class 'bytes'>

方式1:np.frombuffer(img_b, 'B')

import numpy as np
import cv2

img_flatten = np.frombuffer(img_b, 'B')
img_cv = cv2.imdecode(img_flatten, cv2.IMREAD_ANYCOLOR)
print(img_cv.shape)
(359, 500, 3)

方式2:imageio.imread

import imageio
img_io = imageio.imread(img_b)
print(img_io.shape)
(359, 500, 3)

方式3:mxnet.image.imdecode

import mxnet as mx
img_mx = mx.image.imdecode(img_b)

下面咱們來看看這張圖片張什麼樣?

from matplotlib import pyplot as  plt

plt.subplot(231)
plt.imshow(cv2.cvtColor(img_cv, cv2.COLOR_BGR2RGB))
plt.title('OpenCV')
plt.axis('off')
plt.subplot(232)
plt.imshow(img_io)
plt.title('imageio')
plt.axis('off')
plt.subplot(233)
plt.imshow(img_io)
plt.title('MXNet')
plt.axis('off')
plt.show()

考慮到 OpenCV 的高效性,咱們採用方式1 來處理 images 下的圖片數據。

def buffer2array(Z, image_name):
    '''
    無需解壓,直接獲取圖片數據
    
    參數
    ===========
    Z:: 圖片數據是 ZipFile 對象
    '''
    buffer = Z.read(image_name)
    image = np.frombuffer(buffer, dtype="B")  # 將 buffer 轉換爲 np.uint8 數組
    img = cv2.imdecode(image, cv2.IMREAD_COLOR)
    return img


img = buffer2array(Z, Z.namelist()[8])
print('圖片的尺寸:', img.shape)
圖片的尺寸: (480, 640, 3)

4.1 獲取標籤信息(利用官方給定教程)

這裏有一個坑 (由 PIL 引起) import skimage.io as io 在 Windows 下可能會報錯,個人解決辦法是:

  • 先卸載 Pillow,而後從新安裝便可。

  • 插曲:PIL(Python Imaging Library)是Python一個強大方便的圖像處理庫,名氣也比較大。Pillow 是 PIL 的一個派生分支,但現在已經發展成爲比 PIL 自己更具活力的圖像處理庫。

dataDir = cocox.root
dataType = 'val2017'
annFile = '{}/annotations/instances_{}.json'.format(dataDir, dataType)
# initialize COCO api for instance annotations
coco=COCO(annFile)
loading annotations into memory...
Done (t=0.93s)
creating index...
index created!
COCO??

COCO 是一個類:

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.

4.2 COCO categories and supercategories

cats = coco.loadCats(coco.getCatIds())
nms = [cat['name'] for cat in cats]
print('COCO categories: \n{}\n'.format(' '.join(nms)))

nms = set([cat['supercategory'] for cat in cats])
print('COCO supercategories: \n{}'.format(' '.join(nms)))
COCO categories: 
person bicycle car motorcycle airplane bus train truck boat traffic light fire hydrant stop sign parking meter bench bird cat dog horse sheep cow elephant bear zebra giraffe backpack umbrella handbag tie suitcase frisbee skis snowboard sports ball kite baseball bat baseball glove skateboard surfboard tennis racket bottle wine glass cup fork knife spoon bowl banana apple sandwich orange broccoli carrot hot dog pizza donut cake chair couch potted plant bed dining table toilet tv laptop mouse remote keyboard cell phone microwave oven toaster sink refrigerator book clock vase scissors teddy bear hair drier toothbrush

COCO supercategories: 
appliance sports person indoor vehicle food electronic furniture animal outdoor accessory kitchen
# get all images containing given categories, select one at random
catIds = coco.getCatIds(catNms=['person', 'dog', 'skateboard'])
imgIds = coco.getImgIds(catIds=catIds)
imgIds = coco.getImgIds(imgIds=[335328])
img = coco.loadImgs(imgIds[np.random.randint(0, len(imgIds))])[0]
img
{'license': 4,
 'file_name': '000000335328.jpg',
 'coco_url': 'http://images.cocodataset.org/val2017/000000335328.jpg',
 'height': 640,
 'width': 512,
 'date_captured': '2013-11-20 19:29:37',
 'flickr_url': 'http://farm3.staticflickr.com/2079/2128089396_ddd988a59a_z.jpg',
 'id': 335328}

官方給的這個代碼須要將圖片數據集解壓:

# load and display image
# use url to load image
# I = io.imread(img['coco_url'])
I = io.imread('%s/images/%s/%s' % (dataDir, dataType, img['file_name']))
plt.axis('off')
plt.imshow(I)
plt.show()

咱們可使用 zipfile 模塊直接讀取圖片,而無須解壓:

image_names[-1]
'E:/Data/coco/images/val2017.zip'
val_z = zipfile.ZipFile(image_names[-1])
I = image.imdecode(val_z.read('%s/%s' % (dataType, img['file_name']))).asnumpy()
# 或者直接使用 I = buffer2array(val_z, val_z.namelist()[8])
plt.axis('off')
plt.imshow(I)
plt.show()

原圖

4.3 載入和展現 instance annotations

plt.imshow(I)
plt.axis('off')
annIds = coco.getAnnIds(imgIds=img['id'], catIds=catIds, iscrowd=None)
anns = coco.loadAnns(annIds)
coco.showAnns(anns)

coco api

4.4 載入人體關鍵點標註

初始化人體關鍵點標註(person keypoints annotations)的 COCO api

annFile = '{}/annotations/person_keypoints_{}.json'.format(dataDir, dataType)
coco_kps = COCO(annFile)
loading annotations into memory...
Done (t=0.43s)
creating index...
index created!

show:

plt.imshow(I)
plt.axis('off')
ax = plt.gca()
annIds = coco_kps.getAnnIds(imgIds=img['id'], catIds=catIds, iscrowd=None)
anns = coco_kps.loadAnns(annIds)
coco_kps.showAnns(anns)

人體關鍵點

4.5 載入和展現 caption annotations

annFile = '{}/annotations/captions_{}.json'.format(dataDir, dataType)
coco_caps = COCO(annFile)
loading annotations into memory...
Done (t=0.06s)
creating index...
index created!

show:

annIds = coco_caps.getAnnIds(imgIds=img['id'])
anns = coco_caps.loadAnns(annIds)
coco_caps.showAnns(anns)
plt.imshow(I)
plt.axis('off')
plt.show()
A couple of people riding waves on top of boards.
a couple of people that are surfing in water
A man and a young child in wet suits surfing in the ocean.
a man and small child standing on a surf board  and riding some waves
A young boy on a surfboard being taught to surf.

caption


5 更新

2018/11/29

我在 Github 上放置了一個倉庫:datasetsome,該倉庫存儲一些數據集處理相關的 API,若是感受對您有幫助,請給個 star。
你也能夠在線編輯:https://mybinder.org/v2/gh/DataLoaderX/datasetsome/master

除此以外,我還寫了一個 深度學習經常使用數據集 API

爲了令 Windows 系統也能夠更好的使用 COCO 數據集,我打算開發一個能夠適用於 Windows 和 Linux 系統是 API,同時利用 Python 的 ZipFile 模塊直接讀取 images 下的圖片數據以及 annotations 下的標註數據。(直接跳過解壓這一費時的步驟)該 API 的更新我放置在了 cocox。歡迎你們閱覽!

2018/11/30

COCO API 增長對 Windows 系統的支持

2018/12/3

COCO 數據集使用說明書 着重介紹了 cocoz.py

2018/12/13

自制 COCO api 直接讀取類 COCO 的標註數據的壓縮文件 改進 ImageZ,使其支持索引和切片以及迭代功能。爲了令其餘數據也可使用 ImageZ 類,我將 ImageZ 的輸入參數改成 images 所在路徑,其餘不變。同時,舉了一個 Kaggle 比賽的例子:Humpback Whale Identification 來講明 ImageZ 的通用性。

2018/12/23

利用 ImageAI 在 COCO 上學習目標檢測

2019/1/29

利用 ImageZ 與 MXNet 實戰 Kaggle 貓狗分類

2019/3/30

更多的項目更新

2019/4/1

2019/10/12

建立計算機視覺社區:動手實踐計算機視覺。本社區歡迎你們貢獻與計算機視覺相關的代碼或者文檔,同時也歡迎你們分享一些有意思的 idea 或者 issue。還能夠在 gitter@cv-actions 或者 GitPress@cv_actions 交流計算機視覺學習心得。

相關文章
相關標籤/搜索