2024/10/25

install pytorch with mcp support

開啟 ssh server 後就可以用 ssh 登入。
下載 Miniconda3-latest-MacOSX-arm64.sh, 執行。
最後一樣會修改 .zshrc
一樣刪掉,放到 condaenv.sh

一樣, 但是default python 好像是 3.13 太新。torchvision 安裝會有問題。
所以要指定
conda create -n pytorch python==3.11
完成後,進入 pytorch env, follow apple support的說明 (要用 nightly channel):
conda install pytorch torchvision torchaudio -c pytorch-nightly
測試:
>> import torch
>> torch.backends.mps.is_available()
True
所以有 support metal GPU

另外,mps 是 metal GPU
Neural Engine 是 pytorch-lightning

2024/10/23

SSD 筆記 (Single-Shot Detector)

ref: 和yolov1 一樣,重點在設計最後的 output label.

把 yolov1 的最後 NxN 格換成預先定義好的框
框的大小固定的話,要怎麼fit 到不同大小的 object ?
就把不同大小的 featuremap 來用。

經過 CNN, 和 stride=2 之後的 feature map 會縮小。
在縮小的 feature map 上,同樣大小的眶,框住的比例就變大了。

所以 SSD 會把多個 layer 的 fearture map 拿出來做 CNN, 都做出該層的 框框 location 和 confidence.

好複雜

和 Yolov1 一樣,就是在設計 output label 的解釋和格式,

conv.relu - conv.relu - maxpool - ...

這樣的 network 中的某幾層,讓 stride = 2,output feature map 的 size 就會變 1/2.
(所有的 conv 都會加 padding,讓stride=2 時,output size 不變)

在末端的幾層 feature 做 object detection

2024/10/20

Set battery charge limit in ubuntu 24.04

ref: 上次買的 lenovo legion 在 windows 7 下有電池充到 80% 的功能。
覺得這樣電池好像活得比較久,所以想在ubuntu 看看有沒有一樣的功能。

看起來是 tlp 這個 package
follow 說明
sudo apt install tlp tlp-rdw
sudo systemctl enable tlp
syudo systemctl start tlp
然後修改 /etc/tlp.conf
# Battery charge level below which charging will begin.
START_CHARGE_THRESH_BAT0=65
# Battery charge level above which charging will stop.
STOP_CHARGE_THRESH_BAT0=80
然後再啟動
$sudo tlp start
TLP started in battery mode (auto).

$ sudo tlp-stat -b
--- TLP 1.6.1 --------------------------------------------

+++ Battery Care
Plugin: asus
Supported features: none available
Driver usage:
* natacpi (asus_wmi) = inactive (laptop not supported)

+++ Battery Status: BAT1
/sys/class/power_supply/BAT1/manufacturer                   = GIGABYTE
/sys/class/power_supply/BAT1/model_name                     = Aorus 15
/sys/class/power_supply/BAT1/cycle_count                    =      0 (or not supported)
/sys/class/power_supply/BAT1/charge_full_design             =   6514 [mAh]
/sys/class/power_supply/BAT1/charge_full                    =   6514 [mAh]
/sys/class/power_supply/BAT1/charge_now                     =   6258 [mAh]
/sys/class/power_supply/BAT1/current_now                    =   1066 [mA]
/sys/class/power_supply/BAT1/status                         = Discharging

Charge                                                      =   96.1 [%]
Capacity                                                    =  100.0 [%]

看來沒效,因為 laptop not supported
NB 是 Gigabyte AORUS 15X, i9RTX4090
看來還是買 lenovo 還是 asus 比較保險。

不然就要參考:優化 Ubuntu 電池壽命
另外,這邊 有 support list: ASUS, MSI, LG,Lenovo, Samsung, SONY, Toshiba. Apple
--- 所以沒有 Acer 跟 Gigabyte,要用 ubuntu 的話,記得不要買這兩家的 NB

2024/10/19

Yolov1 筆記

ref:
原來yolov1 的 label 是: object 的中心是否在這個方格中心 ?
所以不是物件影像包含的方格,label 都會有值。
只有包含物件中心點的方格,label 會有值。

然後 label 的內容,就是:
  • 物件中心的位置
  • 物件的寬和高
  • 物件的種類

在 pytorch 2.4.1 上測試 ref 的 code 會有Error,所以修改了,放在
從這個實作可以看到,yolov1 的converlution layer 用了 resnet50 的,也就是普通的CNN,後面用 兩個 fully connection layer 轉成 output.
train 的時候直接用 pretain 好的 CNN 層,甚至 fix 住,不做grade, 只靠兩個 fully connection layer,就要生出設計的 label 格式:

yolov1 設計的 output 的表示方式:
  • 7 x 7 的方塊
  • 每個方塊有一個 outputlabel 資料
  • output label 的內容是...
然後就把 VOC 的label Data轉成自己規定的格式,用這個格式去 train,讓中間的兩格 converlution layer train 出他要的結果。

所以可以說,yolo 的精隨,就是他發明的output labeling.
雖然只用了兩層 fully connection layer 就完成他要的轉換。但是這兩層各有 512 個 cell....

2024/10/4

vlc open rtsp fail, server side error message

[INFO  rtsp_demo.c:408:rtsp_new_client_connection] new rtsp client 10.42.0.1:47890 comming
[DEBUG rtsp_msg.c:865:rtsp_msg_parse_from_array]
SETUP rtsp://10.42.0.63:554/live/0 RTSP/1.0
CSeq: 0
Transport: RTP/AVP;unicast;client_port=9298-9299

[DEBUG rtsp_demo.c:950:rtsp_handle_SETUP]
[WARN  rtsp_demo.c:980:rtsp_handle_SETUP] rtsp urlpath:/live/0 err
[DEBUG rtsp_msg.c:998:rtsp_msg_build_to_array]
RTSP/1.0 461 Unsupported Transport
CSeq: 0
Date: Fri Oct  4 16:17:52 2024
Server: rtsp_demo

[INFO  rtsp_demo.c:408:rtsp_new_client_connection] new rtsp client 10.42.0.1:47902 comming
[DEBUG rtsp_demo.c:1158:rtsp_recv_msg] peer closed
[INFO  rtsp_demo.c:427:rtsp_del_client_connection] delete client 86 from 10.42.0.1
[DEBUG rtsp_msg.c:865:rtsp_msg_parse_from_array]
OPTIONS rtsp://10.42.0.63:554 RTSP/1.0
CSeq: 1
User-Agent: RealMedia Player Version 6.0.9.1235 (linux-2.0-libc6-i386-gcc2.95)
ClientChallenge: 9e26d33f2984236010ef6253fb1887f7
PlayerStarttime: [28/03/2003:22:50:23 00:00]
CompanyID: KnKV4M4I/B2FjJ1TToLycw==
GUID: 00000000-0000-0000-0000-000000000000
RegionData: 0
ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586

[WARN  rtsp_msg.c:888:rtsp_msg_parse_from_array] unknown line: ClientChallenge: 9e26d33f2984236010ef6253fb1887f7
[WARN  rtsp_msg.c:888:rtsp_msg_parse_from_array] unknown line: PlayerStarttime: [28/03/2003:22:50:23 00:00]
[WARN  rtsp_msg.c:888:rtsp_msg_parse_from_array] unknown line: CompanyID: KnKV4M4I/B2FjJ1TToLycw==
[WARN  rtsp_msg.c:888:rtsp_msg_parse_from_array] unknown line: GUID: 00000000-0000-0000-0000-000000000000
[WARN  rtsp_msg.c:888:rtsp_msg_parse_from_array] unknown line: RegionData: 0
[WARN  rtsp_msg.c:888:rtsp_msg_parse_from_array] unknown line: ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586
[DEBUG rtsp_demo.c:725:rtsp_handle_OPTIONS]
[DEBUG rtsp_msg.c:998:rtsp_msg_build_to_array]
RTSP/1.0 200 OK
CSeq: 1
Date: Fri Oct  4 16:17:53 2024
Public: OPTIONS, DESCRIBE, SETUP, PLAY, PAUSE, TEARDOWN
Server: rtsp_demo

[DEBUG rtsp_demo.c:1158:rtsp_recv_msg] peer closed
[INFO  rtsp_demo.c:427:rtsp_del_client_connection] delete client 87 from 10.42.0.1

OK 的版本,使用 ffplay
ffplay "rtsp://10.42.0.254/live/0"
server 端 log
[INFO  rtsp_demo.c:408:rtsp_new_client_connection] new rtsp client 10.42.0.1:35114 comming
[DEBUG rtsp_msg.c:865:rtsp_msg_parse_from_array]
OPTIONS rtsp://10.42.0.254:554/live/0 RTSP/1.0
CSeq: 1
User-Agent: Lavf60.16.100

[DEBUG rtsp_demo.c:725:rtsp_handle_OPTIONS]
[DEBUG rtsp_msg.c:998:rtsp_msg_build_to_array]
RTSP/1.0 200 OK
CSeq: 1
Date: Fri Jan  1 12:16:08 2021
Public: OPTIONS, DESCRIBE, SETUP, PLAY, PAUSE, TEARDOWN
Server: rtsp_demo

[DEBUG rtsp_msg.c:865:rtsp_msg_parse_from_array]
DESCRIBE rtsp://10.42.0.254:554/live/0 RTSP/1.0
Accept: application/sdp
CSeq: 2
User-Agent: Lavf60.16.100

[DEBUG rtsp_demo.c:746:rtsp_handle_DESCRIBE]
[DEBUG rtsp_msg.c:998:rtsp_msg_build_to_array]
RTSP/1.0 200 OK
CSeq: 2
Date: Fri Jan  1 12:16:08 2021
Server: rtsp_demo
Content-Type: application/sdp
Content-Length: 479

v=0
o=- 0 0 IN IP4 0.0.0.0
s=rtsp_demo
t=0 0
a=control:rtsp://10.42.0.254:554/live/0
a=range:npt=0-
m=video 0 RTP/AVP 96
c=IN IP4 0.0.0.0
a=rtpmap:96 H265/90000
a=fmtp:96 sprop-vps=QAEMAf//AWAAAAMAgAAAAwAAAwCWvAk=;sprop-sps=QgEBAWAAAAMAgAAAAwAAAwCWoAEgIAURY2+7ymbgICAggAAAAwCAAAAMhA==;sprop-pps=RAHAcoaNQTZA
a=control:rtsp://10.42.0.254:554/live/0/track1
m=audio 0 RTP/AVP 97
c=IN IP4 0.0.0.0
a=rtpmap:97 PCMA/8000/2
a=control:rtsp://10.42.0.254:554/live/0/track2
[DEBUG rtsp_msg.c:865:rtsp_msg_parse_from_array]
SETUP rtsp://10.42.0.254:554/live/0/track1 RTSP/1.0
Transport: RTP/AVP/TCP;unicast;interleaved=0-1
CSeq: 3
User-Agent: Lavf60.16.100

[DEBUG rtsp_demo.c:950:rtsp_handle_SETUP]
[INFO  rtsp_demo.c:894:rtsp_new_rtp_connection] new rtp over tcp for video ssrc:2234567c peer_addr:10.42.0.1 interleaved:0-1
[DEBUG rtsp_msg.c:998:rtsp_msg_build_to_array]
RTSP/1.0 200 OK
CSeq: 3
Date: Fri Jan  1 12:16:08 2021
Session: 1234567A
Transport: RTP/AVP/TCP;ssrc=2234567C;interleaved=0-1
Server: rtsp_demo

[DEBUG rtsp_msg.c:865:rtsp_msg_parse_from_array]
SETUP rtsp://10.42.0.254:554/live/0/track2 RTSP/1.0
Transport: RTP/AVP/TCP;unicast;interleaved=2-3
CSeq: 4
User-Agent: Lavf60.16.100
Session: 1234567A

[DEBUG rtsp_demo.c:950:rtsp_handle_SETUP]
[INFO  rtsp_demo.c:894:rtsp_new_rtp_connection] new rtp over tcp for audio ssrc:2234567d peer_addr:10.42.0.1 interleaved:2-3
[DEBUG rtsp_msg.c:998:rtsp_msg_build_to_array]
RTSP/1.0 200 OK
CSeq: 4
Date: Fri Jan  1 12:16:08 2021
Session: 1234567A
Transport: RTP/AVP/TCP;ssrc=2234567D;interleaved=2-3
Server: rtsp_demo

[DEBUG rtsp_msg.c:865:rtsp_msg_parse_from_array]
PLAY rtsp://10.42.0.254:554/live/0 RTSP/1.0
Range: npt=0.000-
CSeq: 5
User-Agent: Lavf60.16.100
Session: 1234567A

[DEBUG rtsp_demo.c:1037:rtsp_handle_PLAY]
[DEBUG rtsp_msg.c:998:rtsp_msg_build_to_array]
RTSP/1.0 200 OK
CSeq: 5
Date: Fri Jan  1 12:16:08 2021
Session: 1234567A
Server: rtsp_demo

[ntp.c][rkipc_ntp_update]:connect error
[DEBUG rtsp_msg.c:865:rtsp_msg_parse_from_array]
OPTIONS rtsp://10.42.0.254:554/live/0 RTSP/1.0
CSeq: 6
User-Agent: Lavf60.16.100
Session: 1234567A

[DEBUG rtsp_demo.c:725:rtsp_handle_OPTIONS]
[DEBUG rtsp_msg.c:998:rtsp_msg_build_to_array]
RTSP/1.0 200 OK
CSeq: 6
Date: Fri Jan  1 12:16:38 2021
Session: 1234567A
Public: OPTIONS, DESCRIBE, SETUP, PLAY, PAUSE, TEARDOWN
Server: rtsp_demo

2024/10/3

struct Node {
    std::string key;
    int value;
    std::vector<Node> children;

    REFLECT()       // Enable reflection for this type
};
REFLEC( ) 是:
define REFLECT() \
    friend struct reflect::DefaultResolver; \
    static reflect::TypeDescriptor_Struct Reflection; \
    static void initReflection(reflect::TypeDescriptor_Struct*);

所以是在 structure 中增加一個 static variable 和 一個function
Reflection,
initReflection()
然後還有宣告
/ Define Node's type descriptor
REFLECT_STRUCT_BEGIN(Node)
REFLECT_STRUCT_MEMBER(key)
REFLECT_STRUCT_MEMBER(value)
REFLECT_STRUCT_MEMBER(children)
REFLECT_STRUCT_END()
就是依序把Node struct 的 member 宣告一下。
這部份解開就是
    reflect::TypeDescriptor_Struct Node::Reflection{type::initReflection}; 
    void Node::initReflection(reflect::TypeDescriptor_Struct* typeDesc) { 
        using T = Node; 
        typeDesc->name = "Node"; 
        typeDesc->size = sizeof(Node); 
        typeDesc->members = {
        
            {"key",      offsetof(Node, key),      reflect::TypeResolver<std:tring>::get()},
            {"value",    offsetof(Node, value),    reflect::TypeResolver<int>::get()},
            {"children", offsetof(Node, children), reflect::TypeResolver<std:vector<Node>>::get()},
            
        };
    }
main( ) 在告完 Node 變數後,就呼叫:
   reflect::TypeDescriptor* typeDesc = reflect::TypeResolver<Node>::get();
看一下 reflect::TypeResolver<Node>::get*(),template 展開
struct TypeResolver {
    static TypeDescriptor* get() {
        return DefaultResolver::get<Node>();
    }
};
DefaultResolver:get 也是 template:
// This version is called if T has a static member named "Reflection":
    template <typename T, typename std::enable_if<IsReflected<T>::value, int>::type = 0>
    static TypeDescriptor* get() {
        return &T::Reflection;
    }

    // This version is called otherwise:
    template <typename T, typename std::enable_if<!IsReflected<T>::value, int>::type = 0>
    static TypeDescriptor* get() {
        return getPrimitiveDescriptor<T>();
    }
先解開
template <typename T, typename std::enable_if<IsReflected<T>::value, int>::type = 0>
用 std::enable_if 來區分要用那一個
std::enable_if<IsReflected<T>::value, int>::type = 0
enable_if 的 boolean 是 IsRlected<T>::value
IfReflected 是
    struct IsReflected {
        enum { value = (sizeof(func<T>(nullptr)) == sizeof(char)) };
    };
value 的值是 true or false:
(sizeof(func<T>(nullptr)) == sizeof(char)) 
func<T>(nullptr) 有兩個定義,由 T 沒有 member variable : Reflection 決定。Node 有,所以func 是..
template <typename T> static char func(decltype(&T::Reflection));
所以是sizeof(char),所以 value 是 true,也就是 IsReflected<Node>::value 是 true
配合 std::enable_if 用...
   template <typename T, typename std::enable_if<IsReflected<T>::value, int>::type = 0>
    static TypeDescriptor* get() {
        return &T::Reflection;
    }
所以是main( ) 中呼叫 :: get( ) 會回傳,Node::Reflection

之後 typeDesc->dump(&node);
就是 static reflect::TypeDescriptor_Struct 的 dump() :
    virtual void dump(const void* obj, int indentLevel) const override {
        std::cout << name << " {" << std::endl;
        for (const Member& member : members) {
            std::cout << std::string(4 * (indentLevel + 1), ' ') << member.name << " = ";
            member.type->dump((char*) obj + member.offset, indentLevel + 1);
            std::cout << std::endl;
        }
        std::cout << std::string(4 * indentLevel, ' ') << "}";
    }