如何使用Python分析姿態估計數據集COCO?
# 遍歷所有圖像
for img_id, img_fname, w, h, meta in get_meta(coco):
images_data.append({
'image_id': int(img_id),
'path': img_fname,
'width': int(w),
'height': int(h)
})
# 遍歷所有元數據
for m in meta:
persons_data.append({
'image_id': m['image_id'],
'is_crowd': m['iscrowd'],
'bbox': m['bbox'],
'area': m['area'],
'num_keypoints': m['num_keypoints'],
'keypoints': m['keypoints'],
})
# 創建帶有圖像路徑的數據幀
images_df = pd.DataFrame(images_data)
images_df.set_index('image_id', inplace=True)
# 創建與人相關的數據幀
persons_df = pd.DataFrame(persons_data)
persons_df.set_index('image_id', inplace=True)
return images_df, persons_df
我們使用get_meta函數構造兩個數據幀—一個用于圖像路徑,另一個用于人的元數據。在一個圖像中可能有多個人,因此是一對多的關系。在下一步中,我們合并兩個表(left join操作)并將訓練集和驗證集組合,另外,我們添加了一個新列source,值為0表示訓練集,值為1表示驗證集。這樣的信息是必要的,因為我們需要知道應該在哪個文件夾中搜索圖像。如你所知,這些圖像位于兩個文件夾中:train2017/和val2017/images_df, persons_df = convert_to_df(train_coco)
train_coco_df = pd.merge(images_df, persons_df, right_index=True, left_index=True)
train_coco_df['source'] = 0
images_df, persons_df = convert_to_df(val_coco)
val_coco_df = pd.merge(images_df, persons_df, right_index=True, left_index=True)
val_coco_df['source'] = 1
coco_df = pd.concat([train_coco_df, val_coco_df], ignore_index=True)
最后,我們有一個表示整個COCO數據集的數據幀。圖像中有多少人現在我們可以執行第一個分析。COCO數據集包含多個人的圖像,我們想知道有多少圖像只包含一個人。代碼如下:# 計數
annotated_persons_df = coco_df[coco_df['is_crowd'] == 0]
crowd_df = coco_df[coco_df['is_crowd'] == 1]
print("Number of people in total: " + str(len(annotated_persons_df)))
print("Number of crowd annotations: " + str(len(crowd_df)))
persons_in_img_df = pd.DataFrame({
'cnt': annotated_persons_df['path'].value_counts()
})
persons_in_img_df.reset_index(level=0, inplace=True)
persons_in_img_df.rename(columns = {'index':'path'}, inplace = True)
# 按cnt分組,這樣我們就可以在一張圖片中得到帶有注釋人數的數據幀
persons_in_img_df = persons_in_img_df.groupby(['cnt']).count()
# 提取數組
x_occurences = persons_in_img_df.index.values
y_images = persons_in_img_df['path'].values
# 繪圖
plt.bar(x_occurences, y_images)
plt.title('People on a single image ')
plt.xticks(x_occurences, x_occurences)
plt.xlabel('Number of people in a single image')
plt.ylabel('Number of images')
plt.show()
結果圖表:

如你所見,大多數COCO圖片都包含一個人。但也有相當多的13個人的照片,讓我們舉幾個例子:

好吧,甚至有一張圖片有19個注解(非人群):

這個圖像的頂部區域不應該標記為一個人群嗎?是的,應該,但是,我們有多個沒有關鍵點的邊界框!這樣的注釋應該像對待人群一樣對待,這意味著它們應該被屏蔽。在這張圖片中,只有中間的3個方框有一些關鍵點。讓我們來優化查詢,以獲取包含有/沒有關鍵點的人圖像的統計信息,以及有/沒有關鍵點的人的總數:annotated_persons_nokp_df = coco_df[(coco_df['is_crowd'] == 0) & (coco_df['num_keypoints'] == 0)]
annotated_persons_kp_df = coco_df[(coco_df['is_crowd'] == 0) & (coco_df['num_keypoints'] > 0)]
print("Number of people (with keypoints) in total: " +
str(len(annotated_persons_kp_df)))
print("Number of people without any keypoints in total: " +
str(len(annotated_persons_nokp_df)))
persons_in_img_kp_df = pd.DataFrame({
'cnt': annotated_persons_kp_df[['path','source']].value_counts()
})
persons_in_img_kp_df.reset_index(level=[0,1], inplace=True)
persons_in_img_cnt_df = persons_in_img_kp_df.groupby(['cnt']).count()
x_occurences_kp = persons_in_img_cnt_df.index.values
y_images_kp = persons_in_img_cnt_df['path'].values
f = plt.figure(figsize=(14, 8))
width = 0.4
plt.bar(x_occurences_kp, y_images_kp, width=width, label='with keypoints')
plt.bar(x_occurences + width, y_images, width=width, label='no keypoints')
plt.title('People on a single image ')
plt.xticks(x_occurences + width/2, x_occurences)
plt.xlabel('Number of people in a single image')
plt.ylabel('Number of images')
plt.legend(loc = 'best')
plt.show()
現在我們可以看到區別是明顯的。

雖然COCO官方頁面上描述有25萬人擁有關鍵點,而我們只有156165個這樣的例子。他們可能應該刪除了“帶關鍵點”這幾個字。添加額外列一旦我們將COCO轉換成pandas數據幀,我們就可以很容易地添加額外的列,從現有的列中計算出來。我認為最好將所有的關鍵點坐標提取到單獨的列中,此外,我們可以添加一個具有比例因子的列。特別是,關于一個人的邊界框的規模信息是非常有用的,例如,我們可能希望丟棄所有太小規模的人,或者執行放大操作。為了實現這個目標,我們使用Python庫sklearn中的transformer對象。一般來說,sklearn transformers是用于清理、減少、擴展和生成數據科學模型中的特征表示的強大工具。我們只會用一小部分的api。代碼如下:from sklearn.base import BaseEstimator, TransformerMixin
class AttributesAdder(BaseEstimator, TransformerMixin):
def __init__(self, num_keypoints, w_ix, h_ix, bbox_ix, kp_ix):
"""
:param num_keypoints: 關鍵點的數量
:param w_ix: 包含圖像寬度的列索引
:param h_ix: 包含圖像高度的列索引
:param bbox_ix: 包含邊框數據的列索引
:param kp_ix: 包含關鍵點數據的列索引
"""
self.num_keypoints = num_keypoints
self.w_ix = w_ix
self.h_ix = h_ix
self.bbox_ix = bbox_ix
self.kp_ix = kp_ix
def fit(self, X, y=None):
return self
def transform(self, X):
# 檢索特定列
w = X[:, self.w_ix]
h = X[:, self.h_ix]
bbox = np.array(X[:, self.bbox_ix].tolist()) # to matrix
keypoints = np.array(X[:, self.kp_ix].tolist()) # to matrix
請輸入評論內容...
請輸入評論/評論長度6~500個字
最新活動更多
- 1 AI狂歡遇上油價破百,全球股市還能漲多久? | 產聯看全球
- 2 OpenAI深夜王炸!ChatGPT Images 2.0實測:中文穩、細節炸,設計師慌了
- 3 6000億美元估值錨定:字節跳動的“去單一化”突圍與估值重構
- 4 Tesla AI5芯片最新進展總結
- 5 連夜測了一波DeepSeek-V4,我發現它可能只剩“審美”這個短板了
- 6 熱點丨AI“瑜亮之爭”:既生OpenClaw,何生Hermes?
- 7 AI界的殺豬盤:9秒刪庫跑路,全員被封號,還繼續扣錢!
- 8 2026,人形機器人只贏了面子
- 9 DeepSeek降價90%:價格屠夫不是身份,是戰略
- 10 AI Infra產業鏈卡在哪里了?


分享













