2022/7/21

Video Labeling Tools

這個可以從影片開始 labeling,並且可以裝 objection detection 跟 tracking 的 module。
是 local, X, standalone 的。


這個安裝時要指定 opencv-contrib-python==4.1.2.30,這只有 python 3.7 才有。
ref:安裝 opencv-contrib-python

分成 server 和 client (GUI), server 的 requirements.txt,torch 版本太低 (0.4.1),所以拿掉,手動安裝 cuda 板。
-- 不行,cuda 版本需求numpy 版本,requirements 中的版本太低。有人修改到 torch 1.9.0 但是 run failed


這個有比較多人用,也可以半自動 detect,也可以吃video。
但是 export format 沒有 support yolov5 的 txt format,但是有很多人寫了python script,和nodejs script
他有copy - paste 功能,
Ctrl-A : 選擇這個 frame 所有的 box
Ctrl-C : 複製
right arrow : 到下一個 frame
Ctrl-V : 貼上所有的 box
因為 frame 到 frame 的差異很小,所以對video 很方便。

結果,沒有寫好的 vott_csv to yolo 的 script (因為太簡單?)。
所以..
vott_csv 的 head line 有列出 column 內容:
image xmin ymin xmax ymax label
yolov5 的 format 是:
label x_center y_center width height
並且是 normalize 後的數值(0~1 之間的小數)

vottcsv2yolo.py:
import csv
import os

W = 1920
H = 1080

file = open('../vott_target/vott-csv-export/tt2-export.csv')
csvreader = csv.reader(file)

header = next(csvreader)
rows = []
for row in csvreader:
    rows.append(row)

myrows = iter(rows)
filename=None;
yolofile=None;
while (a := next(myrows,None)) is not None:
    if a[0]!= filename:
        filename=a[0]
        if yolofile != None:
            yolofile.close()
        yolofile = open((filename.split('jpg')[0]+"txt"),'w')
    xmin = float(a[1])
    ymin = float(a[2])
    xmax = float(a[3])
    ymax = float(a[4])
    x_center = (xmax+xmin)/(W*2)
    y_center = (ymax+ymin)/(H*2)
    width = (xmax-xmin)/W
    height= (ymax-ymin)/H
    yolofile.write(f'0 {x_center:f} {y_center:f} {width:f} {height:f}\n')
if yolofile != None:
    yolofile.close()

然後使用 labelImg 看 yolov label 的結果:
follow labelImg 的說明:
conda create python=3 (結果是 3.10)
sudo apt-get install pyqt5-dev-tools
activate conda env for labelImg
git clone https://github.com/heartexlabs/labelImg.git
cd labelImg
git checkout v1.8.6
pip install -r requirements/requirements-linux-python3.txt
make qt5py3
然後要修改兩個地方:
~/labelImg$ git diff
diff --git a/labelImg.py b/labelImg.py
index 915ca04..3e72917 100755
--- a/labelImg.py
+++ b/labelImg.py
@@ -205,7 +205,7 @@ class MainWindow(QMainWindow, WindowMixin):
         self.file_dock.setFeatures(QDockWidget.DockWidgetFloatable)
 
         self.dock_features = QDockWidget.DockWidgetClosable | QDockWidget.DockWidgetFloatable
-        self.dock.setFeatures(self.dock.features() ^ self.dock_features)
+        self.dock.setFeatures(self.dock.features() ^ int(self.dock_features))
 
         # Actions
         action = partial(new_action, self)
diff --git a/libs/canvas.py b/libs/canvas.py
index fe355fb..d2d0e32 100644
--- a/libs/canvas.py
+++ b/libs/canvas.py
@@ -162,7 +162,7 @@ class Canvas(QWidget):
             return
 
         # Polygon copy moving.
-        if Qt.RightButton & ev.buttons():
+        if Qt.RightButton & int(ev.buttons()):
             if self.selected_shape_copy and self.prev_point:
                 self.override_cursor(CURSOR_MOVE)
                 self.bounded_move_shape(self.selected_shape_copy, pos)
@@ -173,7 +173,7 @@ class Canvas(QWidget):
             return
 
         # Polygon/Vertex moving.
-        if Qt.LeftButton & ev.buttons():
+        if Qt.LeftButton & int(ev.buttons()):
             if self.selected_vertex():
                 self.bounded_move_vertex(pos)
                 self.shapeMoved.emit()
不然開啟會有Error,還有移動滑鼠會有 Error,程式會自動關閉。

create mylabel folder, copy Vott label 好,export 的 jpg 過去。
把 run 完 vottcsv2yolo.py 的 txt 也 copy 過去。
寫好 classes.txt:
person
car
接著就可以開啟 labelImg:
cd labelImg 
python labelImg
Open Dir 到剛剛 create,放好 jpg, txt 的 folder。
data format 選 yolo
就可以看到 label 的結果了。


label and convert 完,要分成 train, valid 兩個 folder,可以參考:使用 scikit-learn 的 train_test_split() 拆分数据集
from sklearn.model_selection import train_test_split
import glob as glob
import os
import shutil

all_files = glob.glob('./*.txt')
train, valid = train_test_split(all_files,random_state=777,train_size=0.85)
print(f"train: {len(train)}, valid: {len(valid)}")

for file in train:
    shutil.move(file,f"./train/labels/{file}")
    jfile = file.replace('txt','jpg')
    shutil.move(jfile,f"./train/images/{jfile}")

for file in valid:
    shutil.move(file,f"./valid/labels/{file}")
    jfile = file.replace('txt','jpg')
    shutil.move(jfile,f"./valid/images/{jfile}")

labelImg補充:
ref:
python 3.10 才會有上面的 Error,=而且在 畫 box 時會有scroll error。
所以要用 python=3.9

之後的 requirement 也會不 match,要手動..
pip install pyqt5 lxml

沒有留言:

張貼留言