2022/7/28

install node from source, then run VoTT

distribution 的 node 版本太舊 8.10.0,VoTT 說node 至少要 10 以上。
所以只好 install node from source.

先決定版本...
因為 kernel 版本太舊(4.15),所以只能用 v17 之前的版本。
因為 gcc 版本太舊 (7.5),所以只能用 v14之前的版本。
  --prefix=PREFIX       select the install prefix [default: /usr/local]
所以..
./configure --prefix=/home/myname/node14
make -j4
make install
然後再寫 PATH 的 env 到 node14/bin 就可以。

結果一樣,出現 Error:
error: no matching function for call to ‘v8::Value::ToBoolean(v8::Local<v8::Context>)’
所以版本再往前...
改 checkout v10.19.0 (ref ubuntu20.04 的版本)
一樣的 build install, 之後, 到 VoTT ,, npm ci, npm run start
OK。
但是因為 server 上已經有另一個 nodjs server 正在run,所以出的是那個 server 的內容。
修改 package.json,把 nf start -p 3000 改成 4000 之後就 OK 了。

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

2022/7/19

Fix Bluetooth Headset, Headphone function in ubuntu 20.04

想不到 ubuntu 20.04 的 pluseaudio 不 support bluetooth 的 hsp。
所以沒辦法用 bluetooth 的 microphone (因為一直用 A2DP profile)

這一篇 說,修改 /etc/pulse/default.pa。
在 module-bluetooth-discover.so 後面加上 headset=ofono

更完整的在: 但是ubuntu 20.04 找步道 ofono-phonesim
自己加:
sudo add-apt-repository ppa:smoser/bluetooth
sudo apt-get update
sudo apt-get install ofono-phonesim
至於這個說明,和這個說明,一樣修改 /etc/pulse/default.pa,加上 auto_switch=2,會讓 bluetooth 無法連線。

其他,最多,最方便(?)的大概就是用 pipewire 了,
這一篇 說:
PipeWire acts as a drop-in replacement for PulseAudio and offers an easy way to set up Bluetooth headsets. 
It includes out-of-the-box support for A2DP sink profiles using SBC/SBC-XQ, AptX, LDAC or AAC codecs, and HFP/HSP.
所以,大概可以安心用吧(?)
安裝一樣要用 ppa:
sudo add-apt-repository ppa:pipewire-debian/pipewire-upstream
sudo apt update
sudo apt install pipewire
sudo apt install libspa-0.2-bluetooth pipewire-audio-client-libraries

systemctl --user daemon-reload
systemctl --user --now disable pulseaudio.service pulseaudio.socket
systemctl --user mask pulseaudio

systemctl --user --now enable pipewire-media-session.service
然後 check service 是否...
$ pactl info
...
Server Name: PulseAudio (on PipeWire 0.3.32)
...
如果不 OK,可以..
systemctl --user restart pipewire

要 roll-back 的話,可以:
systemctl --user unmask pulseaudio

systemctl --user --now enable pulseaudio.service pulseaudio.socket
這一篇好像是最早的文章。

結果,切到 A2DP 是 OK,切到 HSP 沒聲音,phone 跟 mic 都沒聲音。
然後這一篇說,pipewire 新版的設定檔改位置了。

結果還是一樣,沒聲音。
最後是用外接 bt dongle 才成功。
所以猜是 buildin bt firmware 問題。

另外。
這樣就要 disable internal bt,use bt dongle

$ dmesg | grep Blue
[    5.531481] Bluetooth: Core ver 2.22
[    5.532182] Bluetooth: HCI device and connection manager initialized
[    5.532188] Bluetooth: HCI socket layer initialized
[    5.532190] Bluetooth: L2CAP socket layer initialized
[    5.532198] Bluetooth: SCO socket layer initialized
[    5.697901] Bluetooth: hci0: BCM: chip id 63
[    5.698891] Bluetooth: hci0: BCM: features 0x07
[    5.714899] Bluetooth: hci0: BCM20702A
[    5.714905] Bluetooth: hci0: BCM20702A1 (001.002.014) build 0000
[    5.719734] Bluetooth: hci0: BCM: firmware Patch file not found, tried:
[    5.719740] Bluetooth: hci0: BCM: 'brcm/BCM20702A1-0a5c-21f3.hcd'
[    5.719741] Bluetooth: hci0: BCM: 'brcm/BCM-0a5c-21f3.hcd'
[    6.303633] Bluetooth: BNEP (Ethernet Emulation) ver 1.3
[    6.303638] Bluetooth: BNEP filters: protocol multicast
[    6.303643] Bluetooth: BNEP socket layer initialized
[    7.276706] Bluetooth: RFCOMM TTY layer initialized
[    7.276717] Bluetooth: RFCOMM socket layer initialized
[    7.276724] Bluetooth: RFCOMM ver 1.11
在/lib/firmware/brcm/ 下真的沒找到 BCM-0a5c-21f3.hcd,只有 BCM-0bb4-0306.hcd
根據這邊 的說明:
This package intentended to provide firmware of Broadcom WIDCOMM® Bluetooth devices 
(including BCM20702, BCM20703, BCM43142 chipsets and other) for Linux kernel. 
Since February 2017, Broadcom ships their drivers directly to Windows Update service. 
依照 dmesg 的 filename : BCM2070A1-0a5c-21f3.hcd,download 下來, copy 到 /lib/firmware/brcm/ 後,reboot, dmesg 變成:
[    4.435281] Bluetooth: Core ver 2.22
[    4.435312] NET: Registered PF_BLUETOOTH protocol family
[    4.435314] Bluetooth: HCI device and connection manager initialized
[    4.435319] Bluetooth: HCI socket layer initialized
[    4.435322] Bluetooth: L2CAP socket layer initialized
[    4.435327] Bluetooth: SCO socket layer initialized
[    5.486378] Bluetooth: hci0: BCM: chip id 63
[    5.487374] Bluetooth: hci0: BCM: features 0x07
[    5.503384] Bluetooth: hci0: BCM20702A
[    5.503391] Bluetooth: hci0: BCM20702A1 (001.002.014) build 0000
[    5.508881] Bluetooth: hci0: BCM20702A1 'brcm/BCM20702A1-0a5c-21f3.hcd' Patch
[    5.942911] Bluetooth: BNEP (Ethernet Emulation) ver 1.3
[    5.942916] Bluetooth: BNEP filters: protocol multicast
[    5.942921] Bluetooth: BNEP socket layer initialized
[    6.593382] Bluetooth: hci0: Broadcom Bluetooth Device
[    6.593389] Bluetooth: hci0: BCM20702A1 (001.002.014) build 1761
[    6.958593] Bluetooth: RFCOMM TTY layer initialized
[    6.958602] Bluetooth: RFCOMM socket layer initialized
[    6.958609] Bluetooth: RFCOMM ver 1.11
然後 bt headphone 的 hsp 就正常了。

所以..
  • 安裝 pipewire
  • download .hcd
才能讓 ubuntu 20.04 的 bluetooth headphone 功能恢復正常。

其他的 ref:

ref: 一直要到 ubuntu 22.10 才會內建 pipewire.

2022/7/18

fisheye photo

大概就是參考這個人的,有寫出一般 wide angle, lens distortion 的 correction 跟 fisheye 的。
然後這邊 剛好有人寫了一樣的sourece code,放在 github
實際上會遇到像這樣這樣 的問題。
我把黑邊修掉(crop) 後才約略可以用。
最後這一個人用180 的鏡頭順利remap 出可以用的。

覺得是 remap,不是 undistortion,是要 prject 到另一格平面,例如 panorama或是 cylindre。不是 distortion 的問題。

有關一般fisheye 跟 Rectlinear 鏡的說明/計算/解釋,在這裡

opencv 有關各種 camera 的 calibration 說明: 然後有一個日本人寫了方便的各種 camera calibration, undistort 的 code
這個 是一個中國人寫的,主要是把四顆 fisheye 拼成 surround view
這個 是把 fisheye un-warp 成各種 perspective view
是把 fisheye 轉成 panoramic, spherical or perspective projection


  • 另外看到的,很有趣但是無關的是這個,一步一步教你做image stitch
  • 這一篇論文也是,做 surround view 拼街,其中有說明 Brightness Uniformity and Image Blending 的作法
  • 這一篇論文則是把 fisheye dewarp/unwarp 之後,再用 yolov3 辨識

Bookmark : augmentation with albumentation : bonding box transform

2022/7/8

ssl tunnel . and tensorboard

tensorboard default 是在 local 服務。
要給 remote view 雖然可以設定,但是有點麻煩。
簡單就用 ssl tunnel。把 tensorboard server 的 local port 傳到remote 的機器。
這樣 remote 的機器就可子藉由開啟 自己的 port 看到 tensorboard server 的 port 了。

ref: 因為 tensorboard 服務的 port是 6006,所以把 tensorboard server 的 localhost:6006 轉到我自己的 16006 port:
ssh -L 16006:127.0.0.1:6006 user@server
這樣,自己這邊開啟: localhost:16006 就可以看到 server 上 tensorboard 的輸出了。
其實在啟動 tensorboard 的時候,加上 host ip 就可以讓其他(所有人)看到輸出了:
tensorboard --host 0.0.0.0 --logdir ./logs/fit/
但是如果要加上login 檢查,就只好用ssl tunner.

2022/7/1

linux-pam, pam_securetty.so

touch /etc/pam_debug 就可以把 PAM 的 debug message 放到 system log 中。-- authpriv

manual 有:
       pam_securetty is a PAM module that allows root logins only if the
       user is logging in on a "secure" tty, as defined by the listing
       in /etc/securetty. pam_securetty also checks to make sure that
       /etc/securetty is a plain file and not world writable. It will
       also allow root logins on the tty specified with console= switch
       on the kernel command line and on ttys from the
       /sys/class/tty/console/active.

build-from source:

git clone https://github.com/linux-pam/linux-pam
版本都很舊,有些 am, config 的格式都錯,最後 checkout v1.5.2 才build OK

需要 flex
然後 document 有問題,所以要 disable。
./autogen,sh
./configure --help | less
./configure --enable-static=yes --enable-debug --disable-doc
make


securetty_perform_check
#define SECURETTY_FILE "/etc/securetty"
if (stat(SECURETTY_FILE. &ttyfileinfo)
..
#define CONSOLEACTIVE_FILE "/sys/class/tty/console/active"
最後一個檢查是盤排除 /sys/class/tty/console/activat 所寫得 tty。
所以只要 /sys/class/tty/console/activate 內寫的 tty,就一定不會被 pam_securetty block

source code 另外有 noconsole 這個 option,可以 bypass 後面的 console/active 檢查。只依照 /etc/securetty 的內容。
cat /etc/pam.d/login
 
#%PAM-1.0
auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so debug noconsole
..