如何使用Python分析姿態(tài)估計(jì)數(shù)據(jù)集COCO?
# 計(jì)算邊框的比例因子
scale_x = bbox[:,2] / w
scale_y = bbox[:,3] / h
aspect_ratio = w / h
# 計(jì)算規(guī)模類別
scale_cat = pd.cut(scale_y,
bins=[0., 0.4, 0.6, 0.8, np.inf],
labels=['S', 'M', 'L', 'XL'])
return np.c_[X, scale_x, scale_y, scale_cat, aspect_ratio, keypoints]
# 用于添加新列的transformer對(duì)象
attr_adder = AttributesAdder(num_keypoints=17, ...)
coco_extra_attribs = attr_adder.transform(coco_df.values)
# 創(chuàng)建列發(fā)新列表
keypoints_cols = [['x'+str(idx), 'y'+str(idx), 'v'+str(idx)]
for idx, k in enumerate(range(num_keypoints))]
keypoints_cols = np.concatenate(keypoints_cols).tolist()
# 創(chuàng)建新的更豐富的數(shù)據(jù)z幀
coco_extra_attribs_df = pd.DataFrame(
coco_extra_attribs,
columns=list(coco_df.columns) +
["scale_x", "scale_y", "scale_cat", "aspect_ratio"] +
keypoints_cols,
index=coco_df.index)
38行代碼,我們?yōu)槊恳恍兄付ㄒ?guī)模類別(S、M、L或XL)。計(jì)算方法如下:如果scale_y在[0–0.4)范圍內(nèi),則類別為S如果scale_y在[0.4–0.6)范圍內(nèi),則類別為M如果scale_y在[0.6–0.8)范圍內(nèi),則類別為L如果scale_y在[0.8–1.0)范圍內(nèi),則類別為XL在第42行中,我們將原始列與新列進(jìn)行合并。第28行我們將關(guān)鍵點(diǎn)擴(kuò)展到單獨(dú)的列中。COCO數(shù)據(jù)集中的關(guān)鍵點(diǎn)數(shù)據(jù)由一個(gè)一維列表表示:[x0,y0,v0,x1,y1,…],我們可以把這個(gè)列轉(zhuǎn)換成一個(gè)矩陣:[num of rows]x[num of keypoints*3],然后,我們可以不需要任何額外的努力就可以返回它(第42行)。最后,我們創(chuàng)建一個(gè)新的數(shù)據(jù)幀(第58-63行)鼻子在哪里?我們通過檢查圖像中頭部位置的分布來找到鼻子的坐標(biāo),然后在標(biāo)準(zhǔn)化的二維圖表中畫一個(gè)點(diǎn)。
呈現(xiàn)此圖表的代碼如下:# 對(duì)水平圖像進(jìn)行關(guān)鍵點(diǎn)坐標(biāo)標(biāo)準(zhǔn)化
horiz_imgs_df = coco_extra_attribs_df[coco_extra_attribs_df['aspect_ratio'] >= 1.]
# 獲取平均寬度和高度-用于縮放關(guān)鍵點(diǎn)坐標(biāo)
avg_w = int(horiz_imgs_df['width'].mean())
avg_h(yuǎn) = int(horiz_imgs_df['height'].mean())
class NoseAttributesAdder(BaseEstimator, TransformerMixin):
def __init__(self, avg_w, avg_h(yuǎn), w_ix, h_ix, x1_ix, y1_ix, v1_ix):
self.a(chǎn)vg_w = avg_w
self.a(chǎn)vg_h(yuǎn) = avg_h(yuǎn)
self.w_ix = w_ix
self.h_ix = h_ix
self.x1_ix = x1_ix
self.y1_ix = y1_ix
self.v1_ix = v1_ix
def fit(self, X, y=None):
return self
def transform(self, X):
w = X[:, self.w_ix]
h = X[:, self.h_ix]
x1 = X[:, self.x1_ix]
y1 = X[:, self.y1_ix]
# 標(biāo)準(zhǔn)化鼻子坐標(biāo),提供平均寬度和高度
scale_x = self.a(chǎn)vg_w / w
scale_y = self.a(chǎn)vg_h(yuǎn) / h
nose_x = x1 * scale_x
nose_y = y1 * scale_y
return np.c_[X, nose_x, nose_y]
# 用于標(biāo)準(zhǔn)化鼻子坐標(biāo)列的transformer對(duì)象
w_ix = horiz_imgs_df.columns.get_loc('width')
h_ix = horiz_imgs_df.columns.get_loc('height')
x1_ix = horiz_imgs_df.columns.get_loc('x0') # 鼻子的x坐標(biāo)在'x0'列中
y1_ix = horiz_imgs_df.columns.get_loc('y0') # 鼻子的y坐標(biāo)在'y0'列中
v1_ix = horiz_imgs_df.columns.get_loc('v0') # 鼻頭的可見性
attr_adder = NoseAttributesAdder(avg_w, avg_h(yuǎn), w_ix, h_ix, x1_ix, y1_ix, v1_ix)
coco_noses = attr_adder.transform(horiz_imgs_df.values)
# 使用標(biāo)準(zhǔn)化的數(shù)據(jù)創(chuàng)建新數(shù)據(jù)幀
coco_noses_df = pd.DataFrame(
coco_noses,
columns=list(horiz_imgs_df.columns) + ["normalized_nose_x", "normalized_nose_y"],
index=horiz_imgs_df.index)
# 過濾-只有可見的鼻子
coco_noses_df = coco_noses_df[coco_noses_df["v0"] == 2]
coco_noses_df.plot(kind="scatter", x="normalized_nose_x",
y="normalized_nose_y", alpha=0.3).invert_yaxis()
與前面一樣,我們使用一個(gè)轉(zhuǎn)換器來添加新列。COCO數(shù)據(jù)集包含不同寬度和高度的圖像,我們必須標(biāo)準(zhǔn)化每個(gè)圖像中鼻子的x,y坐標(biāo),這樣我們就能在輸出圖表中畫出代表鼻子的點(diǎn)。我們首先確定所有圖像的平均寬度和高度(第7-8行)這里我們可以使用任何值,因?yàn)樗挥糜诖_定比例因子。在第40-44行,我們從dataframe中找到所需列的索引。隨后,我們執(zhí)行轉(zhuǎn)換(第46-47行)并創(chuàng)建一個(gè)新的數(shù)據(jù)幀,其中包含新的列normalized_nose_x和normalized_nose_y(第51-55行)最后一行繪制二維圖表,F(xiàn)在我們可以檢查一些圖像,例如,我們想檢查一些頭部位置非常接近圖像底邊的圖像,為了實(shí)現(xiàn)這一點(diǎn),我們通過列normalized_nose_y來過濾數(shù)據(jù)幀low_noses_df = coco_noses_df[coco_noses_df['normalized_nose_y'] > 430 ]
low_noses_df
以下是滿足此條件的示例圖像:
關(guān)鍵點(diǎn)數(shù)量具有特定數(shù)量關(guān)鍵點(diǎn)的邊界框的數(shù)量是附加的有用信息。
為什么要邊界框?邊界框有一個(gè)特殊的標(biāo)志iscrowd,用來確定內(nèi)容是應(yīng)該作為一個(gè)群組(沒有關(guān)鍵點(diǎn))還是一個(gè)人(應(yīng)該有關(guān)鍵點(diǎn))。一般來說,iscrowd是為包含許多人的小實(shí)例(例如網(wǎng)球比賽中的觀眾)的邊界框設(shè)置的。y_images = coco_extra_attribs_df['num_keypoints'].value_counts()
x_keypoints = y_images.index.values
# 繪圖
plt.figsize=(10,5)
plt.bar(x_keypoints, y_images)
plt.title('Histogram of keypoints')
plt.xticks(x_keypoints)
plt.xlabel('Number of keypoints')
plt.ylabel('Number of bboxes')
plt.show()
# 帶有若干關(guān)鍵點(diǎn)(行)的bboxes(列)百分比
kp_df = pd.DataFrame({
"Num keypoints %": coco_extra_attribs_df[
"num_keypoints"].value_counts() / len(coco_extra_attribs_df)
}).sort_index()
如你所見,在表中顯示相同的信息非常容易:
規(guī)模這是迄今為止最有價(jià)值的指標(biāo)。訓(xùn)練姿態(tài)估計(jì)深度神經(jīng)網(wǎng)絡(luò)模型對(duì)樣本中人的規(guī)模變化非常敏感,提供一個(gè)平衡的數(shù)據(jù)集是非常關(guān)鍵的,否則,模型可能會(huì)偏向于一個(gè)更具優(yōu)勢(shì)的規(guī)模。你還記得一個(gè)額外的屬性scale_cat嗎?現(xiàn)在我們要好好利用它。代碼:persons_df = coco_extra_attribs_df[coco_extra_attribs_df['num_keypoints'] > 0]
persons_df['scale_cat'].hist()
可以呈現(xiàn)以下圖表:
我們清楚地看到,COCO數(shù)據(jù)集包含了很多小人物——不到圖像總高度的40%。我們把它放到表格中:scales_props_df = pd.DataFrame({
"Scales": persons_df["scale_cat"].value_counts() / len(persons_df)
})
scales_props_df
COCO數(shù)據(jù)集的分層抽樣首先,分層抽樣定義為當(dāng)我們將整個(gè)數(shù)據(jù)集劃分為訓(xùn)練集/驗(yàn)證集等時(shí),我們希望確保每個(gè)子集包含相同比例的特定數(shù)據(jù)組。假設(shè)我們有1000人,男性占57%,女性占43%。我們不能只為訓(xùn)練集和驗(yàn)證集選取隨機(jī)數(shù)據(jù),因?yàn)樵谶@些數(shù)據(jù)子集中,一個(gè)組可能會(huì)被低估。,我們必須從57%的男性和43%的女性中按比例選擇。換句話說,分層抽樣在訓(xùn)練集和驗(yàn)證集中保持了57%的男性/43%的女性的比率。同樣,我們可以檢查COCO訓(xùn)練集和驗(yàn)證集中是否保持了不同規(guī)模的比率。persons_df = coco_extra_attribs_df[coco_extra_attribs_df['num_keypoints'] > 0]
train_df = persons_df[persons_df['source'] == 0]
val_df = persons_df[persons_df['source'] == 1]
scales_props_df = pd.DataFrame({
"Scales in train set %": train_df["scale_cat"].value_counts() / len(train_df),
"Scales in val set %": val_df["scale_cat"].value_counts() / len(val_df)
})
scales_props_df["Diff 100%"] = 100 *
np.a(chǎn)bsolute(scales_props_df["Scales in train set %"] -
scales_props_df["Scales in val set %"])
在第2-3行,我們將數(shù)據(jù)幀拆分為訓(xùn)練集和驗(yàn)證集的單獨(dú)數(shù)據(jù)幀,這與我們分別從person_keypoints_train2017.json和person_keypoints_val2017.json加載數(shù)據(jù)幀相同。接下來,我們用訓(xùn)練集和驗(yàn)證集中每個(gè)規(guī)模組的基數(shù)創(chuàng)建一個(gè)新的數(shù)據(jù)幀,此外,我們添加了一個(gè)列,其中包含兩個(gè)數(shù)據(jù)集之間差異的百分比。結(jié)果如下:
如我們所見,COCO數(shù)據(jù)集的分層非常好,訓(xùn)練集和驗(yàn)證集中的規(guī)模組之間只有很小的差異(1-2%),F(xiàn)在,讓我們檢查不同的組-邊界框中關(guān)鍵點(diǎn)的數(shù)量。train_df = coco_extra_attribs_df[coco_extra_attribs_df['source'] == 0]
val_df = coco_extra_attribs_df[coco_extra_attribs_df['source'] == 1]
kp_props_df = pd.DataFrame({
"Num keypoints in train set %": train_df["num_keypoints"].value_counts() /
len(train_df),
"Num keypoints in val set %": val_df["num_keypoints"].value_counts() /
len(val_df)
}).sort_index()
kp_props_df["Diff 100%"] = 100 *
np.a(chǎn)bsolute(kp_props_df["Num keypoints in train set %"] -
kp_props_df["Num keypoints in val set %"])
類似地,我們看到關(guān)鍵點(diǎn)的數(shù)量在COCO訓(xùn)練和驗(yàn)證集中是相等的,這很好!現(xiàn)在,你可以將所有數(shù)據(jù)集(MPII、COCO)合并到一個(gè)包中,然后自己進(jìn)行拆分,有一個(gè)很好的sklearn類:StratifiedShuffleSplit可用做這個(gè)事情?偨Y(jié)在本文中,分析了COCO數(shù)據(jù)集的結(jié)構(gòu),了解其中的內(nèi)容可以幫助你更好地決定增加或丟棄一些不相關(guān)的樣本。分析可以在Jupyter notebook上進(jìn)行。從COCO數(shù)據(jù)集中展示了一些或多或少有用的指標(biāo),比如圖像中人的分布、人的邊界框的規(guī)模、某些特定身體部位的位置。最后,描述了驗(yàn)證集分層的過程。github倉庫鏈接:https://github.com/michalfaber/dataset_toolkit
☆ END ☆如果看到這里,說明你喜歡這篇文章,請(qǐng)轉(zhuǎn)發(fā)、點(diǎn)贊。微信搜索「uncle_pn」,歡迎添加小編微信「 mthler」,每日朋友圈更新一篇高質(zhì)量博文!龗呙瓒S碼添加小編↓

發(fā)表評(píng)論
請(qǐng)輸入評(píng)論內(nèi)容...
請(qǐng)輸入評(píng)論/評(píng)論長度6~500個(gè)字
最新活動(dòng)更多
-
3月27日立即報(bào)名>> 【工程師系列】汽車電子技術(shù)在線大會(huì)
-
4月30日立即下載>> 【村田汽車】汽車E/E架構(gòu)革新中,新智能座艙挑戰(zhàn)的解決方案
-
5月15-17日立即預(yù)約>> 【線下巡回】2025年STM32峰會(huì)
-
即日-5.15立即報(bào)名>>> 【在線會(huì)議】安森美Hyperlux™ ID系列引領(lǐng)iToF技術(shù)革新
-
5月15日立即下載>> 【白皮書】精確和高效地表征3000V/20A功率器件應(yīng)用指南
-
5月16日立即參評(píng) >> 【評(píng)選啟動(dòng)】維科杯·OFweek 2025(第十屆)人工智能行業(yè)年度評(píng)選
推薦專題
- 1 UALink規(guī)范發(fā)布:挑戰(zhàn)英偉達(dá)AI統(tǒng)治的開始
- 2 北電數(shù)智主辦酒仙橋論壇,探索AI產(chǎn)業(yè)發(fā)展新路徑
- 3 降薪、加班、裁員三重暴擊,“AI四小龍”已折戟兩家
- 4 “AI寒武紀(jì)”爆發(fā)至今,五類新物種登上歷史舞臺(tái)
- 5 國產(chǎn)智駕迎戰(zhàn)特斯拉FSD,AI含量差幾何?
- 6 光計(jì)算迎來商業(yè)化突破,但落地仍需時(shí)間
- 7 東陽光:2024年扭虧、一季度凈利大增,液冷疊加具身智能打開成長空間
- 8 地平線自動(dòng)駕駛方案解讀
- 9 封殺AI“照騙”,“淘寶們”終于不忍了?
- 10 優(yōu)必選:營收大增主靠小件,虧損繼續(xù)又逢關(guān)稅,能否乘機(jī)器人東風(fēng)翻身?