1 簡介
微軟發布的 COCO 數據庫是一個大型圖像數據集, 專為對象檢測、分割、人體關鍵點檢測、語義分割和字幕生成而設計。
COCO 數據庫的網址是:
- 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 和可視化。此外,網站還提供了數據相關的文章, 教程等。
在使用 COCO 數據庫提供的 API 和 demo 之前, 需要首先下載 COCO 的圖像和標簽數據(類別標志、類別數量區分、像素級的分割等 ):
- 圖像數據下載到
coco/images/文件夾中 - 標簽數據下載到
coco/annotations/文件夾中
下面我們來探討一下如何利用 Python 來使用 COCO 數據集?
COCO API 對 WIndows 系統不是太友好,首先我先是 fork 了 COCO API,然后下載到本地,並切換到:D:\API\cocoapi\PythonAPI。
cd D:\API\cocoapi\PythonAPI
打開 Makefile 可以看到 API 的安裝和使用說明。
在 Windows 下直接運行 python setup.py build_ext --inplace 會報錯:

Windows 中 (一般需要安裝 visual studio)有許多的坑,參考 Windows 10 編譯 Pycocotools 踩坑記 暴力刪掉參數 Wno-cpp 和 Wno-unused-function,如下圖所示:

這樣,我們便可以使用 pycocotools,不過每次你想要調用 pycocotools 都需要先載入局部環境:
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 的記號說明:

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。

下面我們來解讀一下 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)

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.

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
2018/12/3
COCO 數據集使用說明書 着重介紹了 cocoz.py。
2018/12/13
自制 COCO api 直接讀取類 COCO 的標注數據的壓縮文件 改進 ImageZ,使其支持索引和切片以及迭代功能。為了令其他數據也可以使用 ImageZ 類,我將 ImageZ 的輸入參數改為 images 所在路徑,其他不變。同時,舉了一個 Kaggle 比賽的例子:Humpback Whale Identification 來說明 ImageZ 的通用性。
2018/12/23
2019/1/29
利用 ImageZ 與 MXNet 實戰 Kaggle 貓狗分類
2019/3/30
更多的項目更新
2019/4/1
- 利用 ImageZ 與 AnnZ:Faster RCNN 學習與實現
- GitHub:meet 求點贊。
2019/10/12
創建計算機視覺社區:動手實踐計算機視覺。本社區歡迎大家貢獻與計算機視覺相關的代碼或者文檔,同時也歡迎大家分享一些有意思的 idea 或者 issue。還可以在 gitter@cv-actions 或者 GitPress@cv_actions 交流計算機視覺學習心得。
2020/01/01
programming項目記錄本人自學的些許筆記。在 book 放置了我的第一本書,該書記錄了如何使用 Git 去管理項目以及如何使用 Python 處理數據集,訓練神經網絡,做符號運算。同時也介紹了 MXNet 與 TensorFlow2 的基本使用。介紹了如何設計屬於自己的深度學習環境和 GitHub 社區。您亦可以下載 tutorials 觀看。
本篇博文已經被收錄到了 book。
