
ZD-1
羽球情蒐大數據—
基於電腦視覺之羽球比賽技術數據自動化分析與標註
工作內容
工作環境介紹
校內專業實習過程中,因為設備有達到跑虛擬環境及訓練模型的最低需求,所以專題製作過程中不需要進實驗室,主要是在宿舍、教室內或者自己家中進行校內專業實習的工作。
實習之初是每周一17:00於R1602B針對當周的學習進度與專題進度進行討論。暑假後,改為於每周二15:00於R1505B及每周五15:00於線上Teams與教授Meeting。
工作詳述
主題查找
實習開始的前三週,我們各自發想校內專業實習的題目,並在Meeting時與教授報告想法和期望的成果展現
,老師以專業的角度對我們的提案進行了可行性分析和預計功能執行的解說。同時,老師也提醒我們要思考資料的來源,以及這些資料和研究是否涉及隱私權和道德倫理的問題,這些方面是我們在初期討論時未曾考慮到的重要因素。
起初,我們主要是往影像辨識應用於結帳、影像辨識應用於體育領域及車禍預測,作為研究領域思考方向,但由於在資料獲取方面都有相當的困難度,老師也提供另一個想法 - AI-CUP的比賽資訊,經過討論後我們決定以AI-CUP比賽中的羽球影像辨識作為專題主題,並先嘗試做出成果雛型,再決定是否參加比賽。
學習影像辨識基礎知識
由於從我們決定主題(04/17)到比賽報名截止(05/02)僅有不到一個月的時間,且我們得從完全沒有接觸過影像辨識、使用過模型到能成功做出一個可用的辨識模型,老師給予我們方向:能完成越多比賽評分項目越好,就算來不及參加比賽,還是繼續研究比賽題目,並精進我們的研究成果。也算是讓我們稍微鬆了一口氣。
學習模式主要為每周Meeting教授會給我們幾篇論文或影像辨識套件的實際操作,進行基礎知識的學習及練習,並於下周Meeting與教授報告學習成果或碰到的問題。
剛開始我們先從基礎的OpenCV(Open Computer Vision Library)與CNN(Convolutional Neural Network卷積神經網路)自行學習,了解影像辨識的基礎及圖片是如何透過程式呈現、讀取及如何進行後續各種影像處理。
影像辨識模型學習
了解基礎運作的邏輯後,教授指派了四篇論文VIT(Vision transformer)、PVT(Pyramid Vision Transformer)、PVTv2、Swin transformer,以及人體姿態辨識 OpenPose、YoloV7,幫助我們認識影像辨識模型,並嘗試透過虛擬環境Anaconda把相對應的模型建立起來,其中OpenPose跟YoloV7的模型都有成功建立並使用,也從實驗中發現OpenPose與YoloV7在同時偵測多人骨幹的部分,無法達到我們預期的目標,因此後來我們選擇使用YoloV8進行骨幹的偵測。

YoloV7實際試跑預訓練集

YoloV8骨幹偵測結果
為了收集場地相關資訊及羽球相關資訊,我們主要分為場地相關的處理、羽球相關的處理與球員骨幹相關的處理,三個 方向進行。
場地線處理
為了得知羽球比賽是否最終是否出界,場地的資訊是非常重要的,因此我們主要是先將比賽影片切成一幀幀座前處理,從中不斷嘗試找出最佳的效果後,再利用程式讀取場地線的區域計算白點數,並讓程式依據場地線白點總數,自動調整最佳閥值,最後發現二值化處理效果較佳,因此利用cv2.threshold()二值化處理,之後進行霍夫直線偵測畫出處理結果。

二值化處理

處理結果
過程中有遇到特定場地偵測雜訊太多的問題,主要是透過侵蝕膨脹cv2.erode()/cv2.dilate()進行解決,消除雜訊過的區域只留下場地線。

雜訊太多的範例

侵蝕膨脹後的結果
最後在利用程式找到比賽所需的直線並留下,透過切一 到兩條水平線,從左往右找有紅點的位置,跳過第一條垂直於水平線之邊界,因為第一個邊界並非單打的邊界,留下第二條垂直線即為單打的左側邊界,右側及上下兩側也同理,最終可留下完整的場地線。

最終場地結果
羽球處理
為了判斷球形、打擊幀、預測球落點、贏家是誰等等,羽球位置的資訊不可少,為了獲取此資訊,我們嘗試自行開發羽球偵測的程式。
主要是利用absdiff()圖片相減,取得圖片中有移動的部分,例如:球員、羽球。此時理想上結果圖中會有兩個人與兩顆球;再利用YoloV8的Segment取得圖片中人物的遮罩,將遮罩兩兩聯集,獲得能覆蓋圖片相減結果的人物遮罩,再將兩者做差集運算,以將圖片相減結果中的人物雜訊盡量刪除,只保留羽球。



圖片相減結果
遮罩聯集結果
兩者差集結果
後續再將兩者差集的結果,兩兩做聯集bitwise_and(),以得到兩個結果圖片中重複的羽球,但過程中因為影片切成幀的問題,使前處理的幀會有重複的問題,導致圖片相減會有全黑的結果圖,因此需透過人工輸入重複圖片的編號以排除碰到全黑的幀,此時得到各幀中羽球,再將其結果做膨脹侵蝕cv2.erode()/cv2.dilate()處理,盡量把殘留的雜訊刪除,後透過cv2.findContours()找出每幀符合大小閥值的白點,即可取得羽球座標並存入CSV檔中,再將原圖根據座標進行標註,後續也利用座標進行斜率的計算以達到打擊幀的判斷。

兩者差集結果

兩者聯集結果

最終結果
但由於此自行開發的羽球偵測程式,會因為雜訊太多或影像處理過程目標物被去掉的問題導致偵測不完全,與教授討論後,決定以TrackNet做為主要羽球偵測的工具,使用TrackNet模型過程中也發現模型結果在部分幀中效果,不如我們自行開發的羽球偵測程式,最終決定以自行開發的羽球偵測程式做為修正Tracknet模型偵測結果的解決方案。

TrackNet偵測結果
羽球標記錯誤

自行開發程式之偵測結果
羽球標記正確
球員骨幹處理
骨幹的偵測主要是透過YoloV8的Pose進行偵測,有17個人體關節點keypoints座標,該座標可用於判斷打擊是否繞頭、是否反手、還有部分球型的判斷。
最終是我們的完整流程圖:

實習期間完成的進度
1.打擊幀判斷
-
利用TrackNet模型對比賽畫面進行偵測,並結合上述自行開發之羽球偵測程式,修正TrackNet偵測不精確或未偵測到的幀,及CSV檔中的座標
-
以前一幀與目前幀的座標計算向量A,與目前幀與下一幀的座標計算向量B
-
計算兩向量的方向夾角
-
變化超過角度變化閥值,則判斷為打擊幀
2.判斷打擊者
-
根據上述打擊幀的判斷,若有判斷出第一個打擊幀,可進入打擊者的判斷
-
打擊者的判斷,執行計算打擊幀與下一幀之羽球方向的變化,以此判斷是從A(上方)或B(下方)打擊出去
-
計算完會將Flag調成0,後續打擊者的判斷會根據打擊幀進行交替互換
3.打擊動作是否繞頭
-
利用前面提到的Yolov8骨幹偵測獲取的關鍵點,我們採用肘關節、手腕、肩膀三個座標點來作判斷
-
判斷手肘、手腕形成向量A, 手肘,肩膀形成向量B
-
計算兩向量在打擊幀時的夾角 => 與打擊幀往前推5張比較
-
觀察是否角度有變小 or 從變小再到接近180度的狀況 => 判斷為RoundHead

打擊者擊球動作繞頭範例
4.打擊動作是否反手
-
利用前面提到的Yolov8骨幹偵測獲取的關鍵點,我們採用左右手腕、肩膀、髖部六個座標點來作判斷
-
首先判斷球員是在上方or下方的球員
-
球員在下方 => 背對我們, 反之則是面對
-
判斷手腕是否跨過左右髖部x座標/2與左右肩膀x座標/2連成一線
-
觀察打擊幀前3幀判斷是否為側身(反手)動作 => 符合即為反手

反手打擊範例
5.預測球的落點
-
A打擊幀的預測落點,會抓取下一個打擊幀的羽球座標
-
另外抓取打擊幀,前三幀的座標的XY變化量
-
判斷前三幀的變化量是否超過閥值,若超過閥值,會將預測變化量之倍數調低;反之,調高倍數
-
將打擊幀的羽球座標加上預測變化量,即可得出A打擊幀的預測落點座標

預測落點,圖中空心紅圈
6.標註出兩邊球員位置
-
利用前面提到的Yolov8骨幹偵測獲取的關鍵點,我們採用慣用腳的腳踝座標
-
利用高斯混合模型取得的影子圖進行疊圖
-
從此腳踝座標畫圓,由圓心往下半部尋找影子
-
直到找到灰色為止就進行標註

原骨幹偵測圖

高斯混合模型取得影子圖
7.判斷打擊球形
-
利用前面提到的Yolov8骨幹偵測獲取的關鍵點,採用AB打者的左右腳踝
-
如果判斷為打擊幀,會比較當幀之打擊者的左右腳踝座標,若在打擊者的腳踝座標靠近場地中縣,會判斷為net shot
-
若為第一個打擊幀,只會進行short/long service的判斷
-
透過計算第一個打擊幀至下一個打擊幀,中間差距的幀數判斷,若幀數少就判斷為short service;反之,long service

NetShot範例,可見打者的腳踝在靠近場地中線處
8.判斷最終贏家
-
偵測落地幀,透過比較羽球位置,連續超過6次位置變化未超過閥值,即判斷為落地
-
檢查落地座標是否在,之前提到的場地縣座標內
-
讀取最後一個打者,並判斷是否出界。若為界內打為最後一個打者獲勝,反之為另一位打者獲勝。

出界範例