2023/4/24

opencv perspective transform

ref:
(550,807), (943,807),(1749,945),(8,945)
(0,0), (600,0), (600,800),(0,800)
車道線選上面四點。
自己決定 mapping 到 600x800 的矩形。
然後用:

pts1 = np.float32([[550,807],[943,807],[1749,945],[8,945]])
pts2 = np.float32([[  0,  0],[600,  0],[ 600,800],[0,800]])

matrix = cv2.getPerspectiveTransform(pts1,pts2)
得到 perspective matrix

然後用 warpPerspective( ) 把 source image , 轉換..
result = cv2.warpPerspective(frame,matrix,(600,900))
因為我們選四個點的時候,沒有選到照片的最底端。
所以 warpPerspective( ) 最後一個 destinate image size,長度要比 mapping 的 800 還多一些...才能把沒被包進去的下面部份也納入。


完整的程式就是:
import cv2
import numpy as np

frame = cv2.imread('p1.png')

pts1 = np.float32([[550,807],[943,807],[1749,945],[8,945]])
pts2 = np.float32([[  0,  0],[600,  0],[ 600,800],[0,800]])

matrix = cv2.getPerspectiveTransform(pts1,pts2)
result = cv2.warpPerspective(frame,matrix,(600,900))

cv2.imshow('result',result)

cv2.waitKey(0)

另外,如果要把整個 video 都做 mapping 的話:
import cv2
import numpy as np
import sys
import os

input_file = sys.argv[1]
print(input_file)
path, filename = os.path.split(input_file)
filename, ext = os.path.splitext(filename)
output_file = filename + '_ipm' + ext
print(output_file)
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_file,fourcc,30.0,(600,900))

pts1 = np.float32([[550,807],[943,807],[1749,945],[8,945]])
pts2 = np.float32([[  0,  0],[600,  0],[ 600,800],[0,800]])
matrix = cv2.getPerspectiveTransform(pts1,pts2)

cap = cv2.VideoCapture(input_file)
while(cap.isOpened()):
        ret, frame = cap.read()
        if not ret:
                break

        result = cv2.warpPerspective(frame,matrix,(600,900))
        out.write(result)

cap.release()
cv2.destroyAllWindows()

另外,得到 perspective transform matrix 後,如果要知道 某一點 transform 後的位置。
相乘完,還要 scale
import numpy as np

with open('matrix.npy','rb') as f:
    matrix = np.load(f)
    
Point = np.float32([100,60,1]) 
PPoint = matrix.dot(Point)
PPoint /= PPoint[2]    // Scalse 

TransformPoint = PPoint[:2]

2023/4/20

AWS IOT

ref: 就是像 mqtt broker 一樣的東西。
在 AWS 服務上,已經啟動,所以只要取得和他 (IOT broker) 溝通的 url 就可以。
到 aws iot core 管理網頁(Settings),就會知道你的帳號的 endpoint 位址是什麼。
可以 ping 看看...

aws iot 是 mqtt over tls,所以需要 一個 pem.
aws iot console 頁面會自動幫你產生一組 ca pem, pub/priv key.
在左邊 "security -- certificate" ,右邊就會出現在所有的 certification,
用 add certificate -- create new 就會新產生一組。
之後的 download 頁面,把每一個 key, cert, pem file 都 download 下來,只有這一次機會,頁面關掉就沒了。

之後的 certification 頁面就會多出這一個 entry.

AWS IOT 的各個 topic 的 sub/pub/con 都是可以設定/限制的,用 Policy (一個 json file)
進入 某格 certfication entry 後,用 attach policies 來決定讓這個 cert 用那一個 policy .

如果沒有現成的 policy,就要 create 一個,一樣,左邊欄的 "Security -- Policy"
一個沒有任何限制的 policy json file 會是:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:*",
      "Resource": "*"
    }
  ]
}

上面列的 ref 中有 python + paho tls 的 example code.
把source 中的 key, crt, pem path 換成自己的 path, endpoint 也改成自己的 url,就可以 run 了。
他會向 test/date 送出 payload 是 date-time 的字串,所以用 aws iot console -- MQTT test client 的 subscribe 時,要把 MQTT payload display 改成 string,才會正常顯示 (default 是 json)

2023/4/6

deep sort : Simple Online and Realtime Tracking with a Deep Association Metric

ref:
follow 他的 README,clong 下來。
依照 instruction run deep_sort_app.py 的話,需要 download Multi-Object-Tracking 數據集。
其中MOT16 的 sequence data,就在最下面..寫 "Download" 的地方..
Download 下來,解開到 MOT16 目錄下。

README 說明:" download pre-generated detections and the CNN checkpoint file from here."
下載 , 是 detections 目錄,放到 resources 目錄下。

不知道不是 python 版本的問題,tunple 的標示操作Error。
所以參考 這一篇,修改 linear_assignment.py:
diff --git a/deep_sort/linear_assignment.py b/deep_sort/linear_assignment.py
index 178456c..d24ec44 100644
--- a/deep_sort/linear_assignment.py
+++ b/deep_sort/linear_assignment.py
@@ -1,7 +1,7 @@
 # vim: expandtab:ts=4:sw=4
 from __future__ import absolute_import
 import numpy as np
-from sklearn.utils.linear_assignment_ import linear_assignment
+from scipy.optimize import linear_sum_assignment as linear_assignment
 from . import kalman_filter


@@ -55,16 +55,16 @@ def min_cost_matching(
     cost_matrix = distance_metric(
         tracks, detections, track_indices, detection_indices)
     cost_matrix[cost_matrix > max_distance] = max_distance + 1e-5
-    indices = linear_assignment(cost_matrix)
+    row_indices, col_indices = linear_assignment(cost_matrix)

     matches, unmatched_tracks, unmatched_detections = [], [], []
     for col, detection_idx in enumerate(detection_indices):
-        if col not in indices[:, 1]:
+        if col not in col_indices:
             unmatched_detections.append(detection_idx)
     for row, track_idx in enumerate(track_indices):
-        if row not in indices[:, 0]:
+        if row not in row_indices:
             unmatched_tracks.append(track_idx)
-    for row, col in indices:
+    for row, col in zip(row_indices,col_indices):
         track_idx = track_indices[row]
         detection_idx = detection_indices[col]
         if cost_matrix[row, col] > max_distance:
最前面是 linear_assignment package 位置改變
還會有 numpy int 的問題,最後用 python3.5成功(因為 conda 的 python3 最低只有到 3.5)
-- 其實是numpy 版本問題

然後依照說明 run:
python deep_sort_app.py \
    --sequence_dir=./MOT16/test/MOT16-06 \
    --detection_file=./resources/detections/MOT16_POI_test/MOT16-06.npy \
    --min_confidence=0.3 \
    --nn_budget=100 \
    --display=True
就可以看到 tracking 的結果。

之後, python 3.9.16, numpy 1.23.5 也可以順利執行修改過的 code。

README 後段,重新 detection,要使用 tensorflow。
原來應該是使用 tensorflow 1.X
改用 tensorflow 2.4.1 ,要修改
diff --git a/tools/freeze_model.py b/tools/freeze_model.py
index e89ad29..63b9fc5 100644
--- a/tools/freeze_model.py
+++ b/tools/freeze_model.py
@@ -1,7 +1,7 @@
 # vim: expandtab:ts=4:sw=4
 import argparse
-import tensorflow as tf
-import tensorflow.contrib.slim as slim
+import tensorflow.compat.v1 as tf
+import tf_slim as slim


 def _batch_norm_fn(x, scope=None):
@@ -193,6 +193,7 @@ def parse_args():

 def main():
     args = parse_args()
+    tf.disable_v2_behavior()

     with tf.Session(graph=tf.Graph()) as session:
         input_var = tf.placeholder(

之後,要 freeze model,除了要改 compat.v1,還要修改slim
diff --git a/tools/freeze_model.py b/tools/freeze_model.py
index e89ad29..63b9fc5 100644
--- a/tools/freeze_model.py
+++ b/tools/freeze_model.py
@@ -1,7 +1,7 @@
 # vim: expandtab:ts=4:sw=4
 import argparse
-import tensorflow as tf
-import tensorflow.contrib.slim as slim
+import tensorflow.compat.v1 as tf
+import tf_slim as slim


 def _batch_norm_fn(x, scope=None):
@@ -193,6 +193,7 @@ def parse_args():

 def main():
     args = parse_args()
+    tf.disable_v2_behavior()

     with tf.Session(graph=tf.Graph()) as session:
         input_var = tf.placeholder(

Bookmark: quantization

  • diffq: Differentiable Model Compression via Pseudo Quantization Noise