diff --git a/requirements.txt b/requirements.txt
index 50f7a13..57f184f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,9 @@
PyQt5 >= 5.13
python-vlc
PyQtGraph
-pyechart
+PyQtChart
influxdb
opencv-python
-pandas
\ No newline at end of file
+pandas
+psutil
+scipy
\ No newline at end of file
diff --git a/run.py b/run.py
index b1a3bda..587b069 100644
--- a/run.py
+++ b/run.py
@@ -6,6 +6,31 @@
# cotjdals5450@gmail.com (Seong Min Chae)
# 5jx2oh@gmail.com (Jongjin Oh)
-from src.__main__ import main
+import multiprocessing as mp
+from src.nd01 import clock, ND01MainWindow
-main()
+
+if __name__ == '__main__':
+ import sys
+ from PyQt5.QtWidgets import QApplication
+ print(f'Start time: {time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}')
+
+ mp.freeze_support()
+ q = Queue()
+ _q = Queue()
+
+ _producer = producer
+
+ p = Process(name='clock', target=clock, args=(q,), daemon=True)
+ _p = Process(name='producer', target=_producer, args=(_q,), daemon=True)
+
+ p.start()
+ _p.start()
+
+ os.makedirs(f'{JS06Settings.get("data_csv_path")}', exist_ok=True)
+ os.makedirs(f'{JS06Settings.get("target_csv_path")}', exist_ok=True)
+ os.makedirs(f'{JS06Settings.get("image_save_path")}', exist_ok=True)
+
+ app = QApplication(sys.argv)
+ window = ND01MainWindow(q, _q)
+ sys.exit(app.exec())
diff --git a/src/auto_file_delete.py b/src/auto_file_delete.py
new file mode 100644
index 0000000..ae11839
--- /dev/null
+++ b/src/auto_file_delete.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python3
+#
+# Copyright 2021-2022 9th grade 5th class.
+#
+# Authors:
+# 5jx2oh@gmail.com
+
+import os
+import psutil
+import shutil
+
+from PyQt5.QtWidgets import (QDialog, QApplication, QMessageBox)
+from PyQt5 import uic
+
+from model import JS08Settings
+
+
+def byte_transform(bytes, to, bsize=1024):
+ """
+ Unit conversion of byte received from shutil
+
+ :return: Capacity of the selected unit (int)
+ """
+ unit = {'KB': 1, 'MB': 2, 'GB': 3, 'TB': 4}
+ r = float(bytes)
+ for i in range(unit[to]):
+ r = r / bsize
+ return int(r)
+
+
+class FileAutoDelete(QDialog):
+
+ def __init__(self):
+ super().__init__()
+
+ ui_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
+ 'resources/auto_file_delete.ui')
+ uic.loadUi(ui_path, self)
+
+ # self.setFixedSize(self.width(), self.height())
+
+ drive = []
+ # Save all of the user's drives in drive variable.
+ for i in range(len(psutil.disk_partitions())):
+ drive.append(str(psutil.disk_partitions()[i])[18:19])
+
+ self.calendarWidget.activated.connect(self.showDate)
+
+ self.path = None
+ self.date = None
+ self.date_convert = None
+
+ self.exit_pushButton.clicked.connect(self.exit_click)
+
+ def exit_click(self):
+ self.close()
+
+ def showDate(self, date):
+ self.date = date.toString('yyMMdd')
+ self.date_convert = date.toString('yyyy/MM/dd')
+ self.check_file_date(os.path.join(JS08Settings.get('image_save_path'),
+ 'vista'))
+
+ def check_file_date(self, path: str):
+ is_old = []
+
+ for f in os.listdir(path):
+ print(f)
+ if int(f) <= int(self.date):
+ is_old.append(int(f))
+
+ if is_old:
+ dlg = QMessageBox.question(self, 'Warning', f'Delete folder before {self.date_convert} ?',
+ QMessageBox.Yes | QMessageBox.No)
+ if dlg == QMessageBox.Yes:
+ self.delete_select_date(path, is_old)
+ else:
+ QMessageBox.information(self, 'Information', 'There is no data before the selected date.')
+
+ def delete_select_date(self, path: str, folder: list):
+ """
+ Delete the list containing the folder name
+
+ :param path: Path to proceed with a auto-delete
+ :param folder: Data older than the date selected as the calendarWidget
+ """
+
+ for i in range(len(folder)):
+ a = os.path.join(path, str(folder[i]))
+ shutil.rmtree(a)
+ print(f'{a} delete complete.')
+
+
+if __name__ == "__main__":
+ import sys
+
+ app = QApplication(sys.argv)
+ window = FileAutoDelete()
+ window.show()
+ sys.exit(app.exec_())
diff --git a/src/cal_ext_coef.py b/src/cal_ext_coef.py
new file mode 100644
index 0000000..02e8d3e
--- /dev/null
+++ b/src/cal_ext_coef.py
@@ -0,0 +1,132 @@
+import itertools
+import os
+
+import numpy as np
+import pandas as pd
+import traceback
+import warnings
+
+import scipy
+from scipy.optimize import curve_fit
+
+curved_flag = True
+hanhwa_dist = []
+hanhwa_x = []
+hanhwa_r = []
+hanhwa_g = []
+hanhwa_b = []
+
+
+def select_max_rgb(r, g, b):
+ c_list = [r, g, b]
+
+ c_index = c_list.index(max(c_list))
+
+ if c_index == 0:
+ select_color = 'red'
+ elif c_index == 1:
+ select_color = 'green'
+ else:
+ select_color = 'blue'
+ # select_color = 'green'
+
+ return select_color
+
+
+def cal_curve(hanhwa: pd.DataFrame):
+ # hanhwa = pd.read_csv(f"{rgbsavedir}/{epoch}.csv")
+ # print(hanhwa)
+ global hanhwa_opt_r, hanhwa_opt_g, hanhwa_opt_b
+ hanhwa = hanhwa.sort_values(by=['distance'])
+ hanhwa_dist = hanhwa[['distance']].squeeze().to_numpy()
+ hanhwa_x = np.linspace(hanhwa_dist[0], hanhwa_dist[-1], 100, endpoint=True)
+ hanhwa_x.sort()
+ hanhwa_r = hanhwa[['r']].squeeze().to_numpy()
+ hanhwa_g = hanhwa[['g']].squeeze().to_numpy()
+ hanhwa_b = hanhwa[['b']].squeeze().to_numpy()
+
+ r1_init = hanhwa_r[0] * 0.7
+ g1_init = hanhwa_g[0] * 0.7
+
+ b1_init = hanhwa_b[0] * 0.7
+ r2_init = hanhwa_r[-1] * 1.3
+ g2_init = hanhwa_g[-1] * 1.3
+ b2_init = hanhwa_b[-1] * 1.3
+
+ select_color = select_max_rgb(r2_init, g2_init, b2_init)
+
+ r_ext_init = [r1_init, r2_init, 1]
+ g_ext_init = [g1_init, g2_init, 1]
+ b_ext_init = [b1_init, b2_init, 1]
+
+ try:
+ hanhwa_opt_r, hanhwa_cov_r = curve_fit(func, hanhwa_dist, hanhwa_r, p0=r_ext_init, maxfev=5000)
+ hanhwa_opt_g, hanhwa_cov_g = curve_fit(func, hanhwa_dist, hanhwa_g, p0=g_ext_init, maxfev=5000)
+ hanhwa_opt_b, hanhwa_cov_b = curve_fit(func, hanhwa_dist, hanhwa_b, p0=b_ext_init, maxfev=5000)
+
+ # hanhwa_opt_r, hanhwa_cov_r = curve_fit(func, hanhwa_dist, hanhwa_r, p0=r_ext_init)
+ # hanhwa_opt_g, hanhwa_cov_g = curve_fit(func, hanhwa_dist, hanhwa_g, p0=g_ext_init)
+ # hanhwa_opt_b, hanhwa_cov_b = curve_fit(func, hanhwa_dist, hanhwa_b, p0=b_ext_init)
+
+ except RuntimeError:
+ # Optimal parameters not found: Number of calls to function has reached maxfev = 5000.
+ # 이 에러는 타겟의 RGB에 대해 최적의 기울기를 찾지 못하여 발생하는 에러로,
+ # 타겟이 이상할 때 대게 발생함.
+
+ # print(traceback.format_exc())
+ pass
+
+ list1 = []
+ list2 = []
+ list3 = []
+
+ list1.append(hanhwa_opt_r[0])
+ list1.append(hanhwa_opt_g[0])
+ list1.append(hanhwa_opt_b[0])
+
+ list2.append(hanhwa_opt_r[1])
+ list2.append(hanhwa_opt_g[1])
+ list2.append(hanhwa_opt_b[1])
+
+ list3.append(hanhwa_opt_r[2])
+ list3.append(hanhwa_opt_g[2])
+ list3.append(hanhwa_opt_b[2])
+
+ # hanhwa_err_r = np.sqrt(np.diag(hanhwa_cov_r))
+ # hanhwa_err_g = np.sqrt(np.diag(hanhwa_cov_g))
+ # hanhwa_err_b = np.sqrt(np.diag(hanhwa_cov_b))
+
+ # print_result(hanhwa_opt_r, hanhwa_opt_g, hanhwa_opt_b, hanhwa_err_r, hanhwa_err_g, hanhwa_err_b)
+
+ # print(f"Red channel: {extcoeff_to_vis(hanhwa_opt_r[2], hanhwa_err_r[2], 3)} km")
+ # print(f"Green channel: {extcoeff_to_vis(hanhwa_opt_g[2], hanhwa_err_g[2], 3)} km")
+ # print(f"Blue channel: {extcoeff_to_vis(hanhwa_opt_b[2], hanhwa_err_b[2], 3)} km")
+
+ # os.makedirs(extsavedir, exist_ok=True)
+
+ return list1, list2, list3, select_color
+
+
+# @staticmethod
+def func(x, c1, c2, a):
+ warnings.filterwarnings('ignore')
+ return c2 + (c1 - c2) * np.exp(-a * x)
+
+
+# def print_result(opt_r, opt_g, opt_b, err_r, err_g, err_b):
+# print(f'Red channel: (',
+# f'C1: {opt_r[0]:.2f} ± {err_r[0]:.2f}, ',
+# f'C2: {opt_r[1]:.2f} ± {err_r[1]:.2f}, ',
+# f'alpha: {opt_r[2]:.2f} ± {err_r[2]:.2f})')
+# print(f'Green channel: (',
+# f'C1: {opt_g[0]:.2f} ± {err_g[0]:.2f}, ',
+# f'C2: {opt_g[1]:.2f} ± {err_g[1]:.2f}, ',
+# f'alpha: {opt_g[2]:.2f} ± {err_g[2]:.2f})')
+# print(f'Blue channel: (',
+# f'C1: {opt_b[0]:.2f} ± {err_b[0]:.2f}, ',
+# f'C2: {opt_b[1]:.2f} ± {err_b[1]:.2f}, ',
+# f'alpha: {opt_b[2]:.2f} ± {err_b[2]:.2f})')
+
+
+# def extcoeff_to_vis(optimal, error, coeff=3.912):
+# return coeff / (optimal + np.array((1, 0, -1)) * error)
diff --git a/src/calculation/curve_save.py b/src/calculation/curve_save.py
deleted file mode 100644
index 62bf6dd..0000000
--- a/src/calculation/curve_save.py
+++ /dev/null
@@ -1,124 +0,0 @@
-import itertools
-import os
-
-import numpy as np
-import pandas as pd
-
-import scipy
-from scipy.optimize import curve_fit
-from PyQt5 import QtWidgets, QtGui, QtCore
-
-curved_flag = True
-# cam_name = cam_name
-hanhwa_dist = []
-hanhwa_x = []
-hanhwa_r = []
-hanhwa_g = []
-hanhwa_b = []
-# epoch = epoch
-# rgbsavedir = os.path.join(f"rgb/{cam_name}")
-# extsavedir = os.path.join(f"extinction/{cam_name}")
-
-def select_max_rgb(r, g, b):
-
- select_color = ""
- c_list = [r, g, b]
-
- c_index = c_list.index(max(c_list))
-
- if c_index == 0:
- select_color = "red"
- elif c_index == 1:
- select_color = "green"
- else :
- select_color = "blue"
- return select_color
-
-def cal_curve(hanhwa: pd.DataFrame):
- # hanhwa = pd.read_csv(f"{rgbsavedir}/{epoch}.csv")
- print(hanhwa)
- hanhwa = hanhwa.sort_values(by=['distance'])
- hanhwa_dist = hanhwa[['distance']].squeeze().to_numpy()
- hanhwa_x = np.linspace(hanhwa_dist[0], hanhwa_dist[-1], 100, endpoint=True)
- hanhwa_x.sort()
- hanhwa_r = hanhwa[['r']].squeeze().to_numpy()
- hanhwa_g = hanhwa[['g']].squeeze().to_numpy()
- hanhwa_b = hanhwa[['b']].squeeze().to_numpy()
-
- r1_init = hanhwa_r[0] * 0.7
- g1_init = hanhwa_g[0] * 0.7
- b1_init = hanhwa_b[0] * 0.7
-
- r2_init = hanhwa_r[-1] * 1.3
- g2_init = hanhwa_g[-1] * 1.3
- b2_init = hanhwa_b[-1] * 1.3
-
- select_color = select_max_rgb(r2_init, g2_init, b2_init)
-
- r_ext_init = [r1_init, r2_init, 1]
- g_ext_init = [g1_init, g2_init, 1]
- b_ext_init = [b1_init, b2_init, 1]
-
- try:
-
- hanhwa_opt_r, hanhwa_cov_r = curve_fit(func, hanhwa_dist, hanhwa_r, p0=r_ext_init, maxfev=5000)
- hanhwa_opt_g, hanhwa_cov_g = curve_fit(func, hanhwa_dist, hanhwa_g, p0=g_ext_init, maxfev=5000)
- hanhwa_opt_b, hanhwa_cov_b = curve_fit(func, hanhwa_dist, hanhwa_b, p0=b_ext_init, maxfev=5000)
-
- except Exception as e:
- print("error msg: ", e)
- return
- list1 = []
- list2 = []
- list3 = []
-
- list1.append(hanhwa_opt_r[0])
- list1.append(hanhwa_opt_g[0])
- list1.append(hanhwa_opt_b[0])
-
- list2.append(hanhwa_opt_r[1])
- list2.append(hanhwa_opt_g[1])
- list2.append(hanhwa_opt_b[1])
-
- list3.append(hanhwa_opt_r[2])
- list3.append(hanhwa_opt_g[2])
- list3.append(hanhwa_opt_b[2])
-
- hanhwa_err_r = np.sqrt(np.diag(hanhwa_cov_r))
- hanhwa_err_g = np.sqrt(np.diag(hanhwa_cov_g))
- hanhwa_err_b = np.sqrt(np.diag(hanhwa_cov_b))
-
- print_result(hanhwa_opt_r, hanhwa_opt_g, hanhwa_opt_b, hanhwa_err_r, hanhwa_err_g, hanhwa_err_b)
-
- print(f"Red channel: {extcoeff_to_vis(hanhwa_opt_r[2], hanhwa_err_r[2], 3)} km")
- print(f"Green channel: {extcoeff_to_vis(hanhwa_opt_g[2], hanhwa_err_g[2], 3)} km")
- print(f"Blue channel: {extcoeff_to_vis(hanhwa_opt_b[2], hanhwa_err_b[2], 3)} km")
-
- return list1, list2, list3, select_color
- # update_extinc_signal.emit(list1, list2, list3, select_color)
-
- try:
- os.mkdir(extsavedir)
- except Exception as e:
- pass
-
-# @staticmethod
-def func(x, c1, c2, a):
- return c2 + (c1 - c2) * np.exp(-a * x)
-
-def print_result(opt_r, opt_g, opt_b, err_r, err_g, err_b):
- print(f"Red channel: (",
- f"C1: {opt_r[0]:.2f} ± {err_r[0]:.2f}, ",
- f"C2: {opt_r[1]:.2f} ± {err_r[1]:.2f}, ",
- f"alpha: {opt_r[2]:.2f} ± {err_r[2]:.2f})")
- print(f"Green channel: (",
- f"C1: {opt_g[0]:.2f} ± {err_g[0]:.2f}, ",
- f"C2: {opt_g[1]:.2f} ± {err_g[1]:.2f}, ",
- f"alpha: {opt_g[2]:.2f} ± {err_g[2]:.2f})")
- print(f"Blue channel: (",
- f"C1: {opt_b[0]:.2f} ± {err_b[0]:.2f}, ",
- f"C2: {opt_b[1]:.2f} ± {err_b[1]:.2f}, ",
- f"alpha: {opt_b[2]:.2f} ± {err_b[2]:.2f})")
-
-def extcoeff_to_vis(optimal, error, coeff=3.291):
- return coeff / (optimal + np.array((1, 0, -1)) * error)
diff --git a/src/calculation/gary_visibility.py b/src/calculation/gary_visibility.py
deleted file mode 100644
index 113eebf..0000000
--- a/src/calculation/gary_visibility.py
+++ /dev/null
@@ -1,106 +0,0 @@
-import itertools
-import os
-
-import numpy as np
-import pandas as pd
-
-import scipy
-from scipy.optimize import curve_fit
-import matplotlib
-import matplotlib.pyplot as plt
-
-
-def minprint(self):
- """지정한 구역들에서 소산계수 산출용 픽셀을 출력하는 함수"""
- result = ()
- cnt = 1
- min_x = []
- min_y = []
-
- for upper_left, lower_right in zip(left_range, right_range):
- result = minrgb(upper_left, lower_right)
- print(f"target{cnt}의 소산계수 검출용 픽셀위치 = ", result)
- min_x.append(result[0])
- min_y.append(result[1])
- cnt += 1
-
- get_rgb(epoch)
-
- curved_thread = CurvedThread(camera_name, epoch)
- curved_thread.update_extinc_signal.connect(extinc_print)
- curved_thread.run()
-
- list_test()
-
- graph_dir = os.path.join(f"extinction/{camera_name}")
-def minrgb(self, upper_left, lower_right):
- """드래그한 영역의 RGB 최솟값을 추출한다"""
-
- up_y = min(upper_left[1], lower_right[1])
- down_y = max(upper_left[1], lower_right[1])
-
- left_x = min(upper_left[0], lower_right[0])
- right_x = max(upper_left[0], lower_right[0])
-
- test = cp_image[up_y:down_y, left_x:right_x, :]
-
- # 드래그한 영역의 RGB 값을 각각 추출한다.
- # r = test[:, :]
- # g = test[:, :, 1]
- # b = test[:, :, 2]
-
- # RGB값을 각 위치별로 모두 더한다.
- # RGB 최댓값이 255로 정해져있어 값을 초과하면 0부터 시작된다. numpy의 clip 함수를 이용해 array의 최댓값을 수정한다.
- # r = np.clip(r, 0, 765)
- # sum_rgb = r + g + b
-
- # RGB 값을 합한 뒤 가장 최솟값의 index를 추출한다.
- t_idx = np.where(test == np.min(test))
-
- show_min_y = t_idx[0][0] + up_y
- show_min_x = t_idx[1][0] + left_x
-
- return (show_min_x, show_min_y)
-
-def get_rgb(self, epoch: str):
- r_list = []
- g_list = []
- b_list = []
-
- for x, y in zip(min_x, min_y):
-
- r_list.append(cp_image[y, x, 0])
- g_list.append(cp_image[y, x, 1])
- b_list.append(cp_image[y, x, 2])
-
- print("red : ", cp_image[y, x, 0])
- print("green : ", cp_image[y, x, 1])
- print("blue: ", cp_image[y, x, 2])
-
-
- save_rgb(r_list, g_list, b_list, epoch)
-
-def save_rgb(self, r_list, g_list, b_list, epoch):
- """Save the rgb information for each target."""
- try:
- save_path = os.path.join(f"rgb/{camera_name}")
- os.mkdir(save_path)
-
- except Exception as e:
- pass
-
- if r_list:
- r_list = list(map(int, r_list))
- g_list = list(map(int, g_list))
- b_list = list(map(int, b_list))
- print(b_list)
-
- col = ["target_name", "r", "g", "b", "distance"]
- result = pd.DataFrame(columns=col)
- result["target_name"] = target_name
- result["r"] = r_list
- result["g"] = g_list
- result["b"] = b_list
- result["distance"] = distance
- print(result.head(10))
- result.to_csv(f"{save_path}/{epoch}.csv", mode="w", index=False)
\ No newline at end of file
diff --git a/src/clock.py b/src/clock.py
new file mode 100644
index 0000000..428d7ce
--- /dev/null
+++ b/src/clock.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python3
+#
+# Copyright 2021-2022 Sijung Co., Ltd.
+#
+# Authors:
+# cotjdals5450@gmail.com (Seong Min Chae)
+# 5jx2oh@gmail.com (Jongjin Oh)
+
+import time
+
+
+def clockclock(queue):
+ """Real-time clock
+ Current time to be expressed on JS-06
+
+ :param queue: MultiProcessing Queue
+ """
+ while True:
+ now = str(time.time())
+ queue.put(now)
+ time.sleep(1)
diff --git a/src/controller.py b/src/controller.py
index 2372a69..4268be7 100644
--- a/src/controller.py
+++ b/src/controller.py
@@ -1,8 +1,8 @@
#!/usr/bin/env python3
#
# Copyright 2020-2021 Sijung Co., Ltd.
-#
-# Authors:
+#
+# Authors:
# ruddyscent@gmail.com (Kyungwon Chun)
# 5jx2oh@gmail.com (Jongjin Oh)
@@ -13,35 +13,27 @@
import cv2
import numpy as np
-# import onnxruntime as ort
from PyQt5.QtCore import (QDateTime, QDir, QObject, QRect, QThread,
QThreadPool, QTime, QTimer, pyqtSignal, pyqtSlot)
from PyQt5.QtGui import QImage
-from PyQt5.QtMultimedia import QVideoFrame
-
-# from .model import (Js08AttrModel, Js08CameraTableModel, Js08IoRunner,
-# Js08Settings, Js08SimpleTarget, Js08Wedge)
-class MainCtrl(QObject):
+class JS08MainCtrl(QObject):
abnormal_shutdown = pyqtSignal()
- front_camera_changed = pyqtSignal(str) # uri
- rear_camera_changed = pyqtSignal(str) # uri
+ front_camera_changed = pyqtSignal(str) # uri
+ rear_camera_changed = pyqtSignal(str) # uri
front_target_decomposed = pyqtSignal()
rear_target_decomposed = pyqtSignal()
- target_assorted = pyqtSignal(list, list) # positives, negatives
- wedge_vis_ready = pyqtSignal(int, dict) # epoch, wedge visibility
+ target_assorted = pyqtSignal(list, list) # positives, negatives
+ wedge_vis_ready = pyqtSignal(int, dict) # epoch, wedge visibility
- # def __init__(self, model: Js08AttrModel):
def __init__(self):
super().__init__()
self.writer_pool = QThreadPool.globalInstance()
self.writer_pool.setMaxThreadCount(1)
- self._model = model
-
self.num_working_cam = 0
self.front_simple_targets = []
@@ -50,34 +42,11 @@ def __init__(self):
self.front_target_prepared = False
self.rear_target_prepared = False
- self.init_db()
-
self.observation_timer = QTimer(self)
- # self.front_camera_changed.connect(self.decompose_front_targets)
- # self.rear_camera_changed.connect(self.decompose_rear_targets)
self.worker_running = False
self.start_observation_timer()
- def init_db(self):
- db_host = Js08Settings.get('db_host')
- db_port = Js08Settings.get('db_port')
- db_name = Js08Settings.get('db_name')
- self._model.connect_to_db(db_host, db_port, db_name)
-
- if getattr(sys, 'frozen', False):
- directory = sys._MEIPASS
- else:
- directory = os.path.dirname(__file__)
- attr_path = os.path.join(directory, 'resources', 'attr.json')
- with open(attr_path, 'r') as f:
- attr_json = json.load(f)
- camera_path = os.path.join(directory, 'resources', 'camera.json')
- with open(camera_path, 'r') as f:
- camera_json = json.load(f)
-
- self._model.setup_db(attr_json, camera_json)
-
@pyqtSlot(str)
def decompose_front_targets(self, _: str) -> None:
"""Make list of SimpleTarget by decoposing compound targets.
@@ -85,7 +54,6 @@ def decompose_front_targets(self, _: str) -> None:
Parameters:
"""
self.front_target_prepared = False
- # self.decompose_targets('front')
self.front_target_prepared = True
@pyqtSlot(str)
@@ -112,9 +80,9 @@ def decompose_targets(self, direction: str) -> None:
elif direction == 'rear':
targets = attr['rear_camera']['targets']
id = str(attr['rear_camera']['camera_id'])
-
- base_path = Js08Settings.get('image_base_path')
-
+
+ base_path = Js08Settings.get('image_base_path')
+
# Prepare model.
# TODO(Kyungwon): Put the model file into Qt Resource Collection.
if getattr(sys, 'frozen', False):
@@ -127,7 +95,7 @@ def decompose_targets(self, direction: str) -> None:
input_shape = sess.get_inputs()[0].shape
input_height = input_shape[1]
input_width = input_shape[2]
-
+
for tg in targets:
wedge = tg['wedge']
azimuth = tg['azimuth']
@@ -172,7 +140,7 @@ def read_mask(self, path: str) -> np.ndarray:
def start_observation_timer(self) -> None:
print('DEBUG(start_observation_timer):', QTime.currentTime().toString())
- self.observation_timer.setInterval(1000) # every one second
+ self.observation_timer.setInterval(10000) # every 10 seconds
self.observation_timer.timeout.connect(self.start_worker)
self.observation_timer.start()
@@ -193,11 +161,11 @@ def start_worker(self) -> None:
rear_uri = self.get_rear_camera_uri()
self.worker = Js08InferenceWorker(
self.epoch,
- front_uri,
- rear_uri,
- self.front_simple_targets,
+ front_uri,
+ rear_uri,
+ self.front_simple_targets,
self.rear_simple_targets
- )
+ )
self.worker_thread = QThread()
self.worker.moveToThread(self.worker_thread)
self.worker_thread.started.connect(self.worker.run)
@@ -216,7 +184,7 @@ def postproduction(self):
epoch: seconds since epoch
"""
epoch = self.epoch
-
+
pos, neg = self.assort_discernment()
self.target_assorted.emit(pos, neg)
wedge_vis = self.wedge_visibility()
@@ -262,13 +230,13 @@ def wedge_visibility(self) -> dict:
wedge_vis = {w: None for w in Js08Wedge}
for t in self.front_simple_targets:
if t.discernment:
- if wedge_vis[t.wedge] == None:
+ if wedge_vis[t.wedge] is None:
wedge_vis[t.wedge] = t.distance
elif wedge_vis[t.wedge] < t.distance:
wedge_vis[t.wedge] = t.distance
for t in self.rear_simple_targets:
if t.discernment:
- if wedge_vis[t.wedge] == None:
+ if wedge_vis[t.wedge] is None:
wedge_vis[t.wedge] = t.distance
elif wedge_vis[t.wedge] < t.distance:
wedge_vis[t.wedge] = t.distance
@@ -286,7 +254,7 @@ def save_image(self, dir: str, filename: str, image: QImage) -> None:
path = QDir.cleanPath(os.path.join(dir, filename))
runner = Js08IoRunner(path, image)
self.writer_pool.start(runner)
-
+
def grab_image(self, direction: str) -> QImage:
"""
Parameters:
@@ -320,7 +288,7 @@ def get_target(self, direction: str) -> list:
def get_camera_table_model(self) -> dict:
cameras = self.get_cameras()
- table_model = Js08CameraTableModel(cameras)
+ table_model = Js08CameraTableModel(cameras)
return table_model
def check_exit_status(self) -> bool:
@@ -335,7 +303,7 @@ def update_cameras(self, cameras: list, update_target: bool = False) -> None:
for cam_id in cam_id_in_db:
if cam_id not in cam_id_in_arg:
self._model.delete_camera(cam_id)
-
+
# if `cameras` does not have 'targets' field, add an empty list for it.
for cam in cameras:
if 'targets' not in cam:
@@ -349,7 +317,7 @@ def update_cameras(self, cameras: list, update_target: bool = False) -> None:
if c_arg['_id'] == c_db['_id']:
c_arg['targets'] = c_db['targets']
continue
-
+
# if '_id' is empty, delete the field
for cam in cameras:
if not cam['_id']:
@@ -369,7 +337,7 @@ def get_attr(self) -> dict:
# if self._attr.count_documents({}):
# attr_doc = list(self._attr.find().sort("_id", -1).limit(1))[0]
return attr_doc
-
+
def insert_attr(self, model: dict) -> None:
self._model.insert_attr(model)
@@ -379,7 +347,7 @@ def restore_defaults(self) -> None:
@pyqtSlot(bool)
def set_normal_shutdown(self) -> None:
- Js08Settings.set('normal_shutdown', True)
+ Js08Settings.set('normal_shutdown', True)
def get_cameras(self) -> list:
return self._model.read_cameras()
@@ -387,14 +355,15 @@ def get_cameras(self) -> list:
class Js08InferenceWorker(QObject):
finished = pyqtSignal()
-
- def __init__(self, epoch: int, front_uri: str, rear_uri: str, front_decomposed_targets: list, rear_decomposed_targets: list) -> None:
+
+ def __init__(self, epoch: int, front_uri: str, rear_uri: str, front_decomposed_targets: list,
+ rear_decomposed_targets: list) -> None:
"""
Parameters:
ctrl:
"""
super().__init__()
-
+
# TODO(Kyungwon): Put the model file into Qt Resource Collection.
if getattr(sys, 'frozen', False):
directory = sys._MEIPASS
@@ -470,7 +439,7 @@ def run(self):
self.save_image(dir, filename, front_image)
filename = f'vista-rear-{now.toString("yyyy-MM-dd-hh-mm")}.png'
self.save_image(dir, filename, rear_image)
-
+
# Discriminate the targets of front camera
self.classify_batch(self.front_targets, front_image)
@@ -479,7 +448,7 @@ def run(self):
self.finished.emit()
- def classify_batch(self, targets: List[Js08SimpleTarget], vista: QImage):
+ def classify_batch(self, targets: list, vista: QImage):
"""Discriminate image batch
Parameters:
@@ -498,9 +467,9 @@ def classify_batch(self, targets: List[Js08SimpleTarget], vista: QImage):
for i, target in enumerate(targets):
if i % self.batch_size == 0:
data = np.zeros(
- (self.batch_size, self.input_height, self.input_width, 3),
+ (self.batch_size, self.input_height, self.input_width, 3),
dtype=np.float32
- )
+ )
roi_image = target.clip_roi(vista)
arr = target.img_to_arr(roi_image, self.input_width, self.input_height)
@@ -522,4 +491,4 @@ def classify_batch(self, targets: List[Js08SimpleTarget], vista: QImage):
if save_target_clip:
postfix = 'pos' if target.discernment else 'neg'
filename = f'{target.label}_{postfix}.png'
- self.save_image(dir, filename, masked_img_list[i])
\ No newline at end of file
+ self.save_image(dir, filename, masked_img_list[i])
diff --git a/src/curve_save.py b/src/curve_save.py
deleted file mode 100644
index 62bf6dd..0000000
--- a/src/curve_save.py
+++ /dev/null
@@ -1,124 +0,0 @@
-import itertools
-import os
-
-import numpy as np
-import pandas as pd
-
-import scipy
-from scipy.optimize import curve_fit
-from PyQt5 import QtWidgets, QtGui, QtCore
-
-curved_flag = True
-# cam_name = cam_name
-hanhwa_dist = []
-hanhwa_x = []
-hanhwa_r = []
-hanhwa_g = []
-hanhwa_b = []
-# epoch = epoch
-# rgbsavedir = os.path.join(f"rgb/{cam_name}")
-# extsavedir = os.path.join(f"extinction/{cam_name}")
-
-def select_max_rgb(r, g, b):
-
- select_color = ""
- c_list = [r, g, b]
-
- c_index = c_list.index(max(c_list))
-
- if c_index == 0:
- select_color = "red"
- elif c_index == 1:
- select_color = "green"
- else :
- select_color = "blue"
- return select_color
-
-def cal_curve(hanhwa: pd.DataFrame):
- # hanhwa = pd.read_csv(f"{rgbsavedir}/{epoch}.csv")
- print(hanhwa)
- hanhwa = hanhwa.sort_values(by=['distance'])
- hanhwa_dist = hanhwa[['distance']].squeeze().to_numpy()
- hanhwa_x = np.linspace(hanhwa_dist[0], hanhwa_dist[-1], 100, endpoint=True)
- hanhwa_x.sort()
- hanhwa_r = hanhwa[['r']].squeeze().to_numpy()
- hanhwa_g = hanhwa[['g']].squeeze().to_numpy()
- hanhwa_b = hanhwa[['b']].squeeze().to_numpy()
-
- r1_init = hanhwa_r[0] * 0.7
- g1_init = hanhwa_g[0] * 0.7
- b1_init = hanhwa_b[0] * 0.7
-
- r2_init = hanhwa_r[-1] * 1.3
- g2_init = hanhwa_g[-1] * 1.3
- b2_init = hanhwa_b[-1] * 1.3
-
- select_color = select_max_rgb(r2_init, g2_init, b2_init)
-
- r_ext_init = [r1_init, r2_init, 1]
- g_ext_init = [g1_init, g2_init, 1]
- b_ext_init = [b1_init, b2_init, 1]
-
- try:
-
- hanhwa_opt_r, hanhwa_cov_r = curve_fit(func, hanhwa_dist, hanhwa_r, p0=r_ext_init, maxfev=5000)
- hanhwa_opt_g, hanhwa_cov_g = curve_fit(func, hanhwa_dist, hanhwa_g, p0=g_ext_init, maxfev=5000)
- hanhwa_opt_b, hanhwa_cov_b = curve_fit(func, hanhwa_dist, hanhwa_b, p0=b_ext_init, maxfev=5000)
-
- except Exception as e:
- print("error msg: ", e)
- return
- list1 = []
- list2 = []
- list3 = []
-
- list1.append(hanhwa_opt_r[0])
- list1.append(hanhwa_opt_g[0])
- list1.append(hanhwa_opt_b[0])
-
- list2.append(hanhwa_opt_r[1])
- list2.append(hanhwa_opt_g[1])
- list2.append(hanhwa_opt_b[1])
-
- list3.append(hanhwa_opt_r[2])
- list3.append(hanhwa_opt_g[2])
- list3.append(hanhwa_opt_b[2])
-
- hanhwa_err_r = np.sqrt(np.diag(hanhwa_cov_r))
- hanhwa_err_g = np.sqrt(np.diag(hanhwa_cov_g))
- hanhwa_err_b = np.sqrt(np.diag(hanhwa_cov_b))
-
- print_result(hanhwa_opt_r, hanhwa_opt_g, hanhwa_opt_b, hanhwa_err_r, hanhwa_err_g, hanhwa_err_b)
-
- print(f"Red channel: {extcoeff_to_vis(hanhwa_opt_r[2], hanhwa_err_r[2], 3)} km")
- print(f"Green channel: {extcoeff_to_vis(hanhwa_opt_g[2], hanhwa_err_g[2], 3)} km")
- print(f"Blue channel: {extcoeff_to_vis(hanhwa_opt_b[2], hanhwa_err_b[2], 3)} km")
-
- return list1, list2, list3, select_color
- # update_extinc_signal.emit(list1, list2, list3, select_color)
-
- try:
- os.mkdir(extsavedir)
- except Exception as e:
- pass
-
-# @staticmethod
-def func(x, c1, c2, a):
- return c2 + (c1 - c2) * np.exp(-a * x)
-
-def print_result(opt_r, opt_g, opt_b, err_r, err_g, err_b):
- print(f"Red channel: (",
- f"C1: {opt_r[0]:.2f} ± {err_r[0]:.2f}, ",
- f"C2: {opt_r[1]:.2f} ± {err_r[1]:.2f}, ",
- f"alpha: {opt_r[2]:.2f} ± {err_r[2]:.2f})")
- print(f"Green channel: (",
- f"C1: {opt_g[0]:.2f} ± {err_g[0]:.2f}, ",
- f"C2: {opt_g[1]:.2f} ± {err_g[1]:.2f}, ",
- f"alpha: {opt_g[2]:.2f} ± {err_g[2]:.2f})")
- print(f"Blue channel: (",
- f"C1: {opt_b[0]:.2f} ± {err_b[0]:.2f}, ",
- f"C2: {opt_b[1]:.2f} ± {err_b[1]:.2f}, ",
- f"alpha: {opt_b[2]:.2f} ± {err_b[2]:.2f})")
-
-def extcoeff_to_vis(optimal, error, coeff=3.291):
- return coeff / (optimal + np.array((1, 0, -1)) * error)
diff --git a/src/curve_thread.py b/src/curve_thread.py
new file mode 100644
index 0000000..fa52782
--- /dev/null
+++ b/src/curve_thread.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python3
+#
+# Copyright 2021-2022 Sijung Co., Ltd.
+#
+# Authors:
+# cotjdals5450@gmail.com (Seong Min Chae)
+# 5jx2oh@gmail.com (Jongjin Oh)
+
+from multiprocessing import Queue
+
+from PyQt5.QtCore import QThread, pyqtSignal
+
+
+class CurveThread(QThread):
+ poped = pyqtSignal(dict)
+
+ def __init__(self, _q: Queue):
+ super().__init__()
+ self._run_flag = False
+ self.q = _q
+
+ def run(self):
+ self._run_flag = True
+ while self._run_flag:
+ if not self.q.empty():
+ visibility = self.q.get()
+ self.poped.emit(visibility)
+ # shut down capture system
+
+ def stop(self):
+ """Sets run flag to False and waits for thread to finish"""
+ self._run_flag = False
+ self.quit()
+ self.wait()
diff --git a/src/js08.py b/src/js08.py
new file mode 100644
index 0000000..9eb232b
--- /dev/null
+++ b/src/js08.py
@@ -0,0 +1,1136 @@
+#!/usr/bin/env python3
+#
+# Copyright 2021-2022 Sijung Co., Ltd.
+#
+# Authors:
+# cotjdals5450@gmail.com (Seong Min Chae)
+# 5jx2oh@gmail.com (Jongjin Oh)
+
+import sys
+import os
+import time
+import random
+import collections
+
+import vlc
+import numpy as np
+import pandas as pd
+import multiprocessing as mp
+from multiprocessing import Process, Queue
+
+from PyQt5.QtGui import (QPixmap, QIcon, QPainter,
+ QColor, QPen, QFont)
+from PyQt5.QtWidgets import (QMainWindow, QWidget, QFrame,
+ QVBoxLayout, QLabel, QInputDialog,
+ QMessageBox)
+from PyQt5.QtCore import (Qt, pyqtSlot, pyqtSignal,
+ QRect, QTimer, QObject,
+ QThread, QPointF, QDateTime,
+ QPoint)
+from PyQt5.QtChart import (QChartView, QLegend, QLineSeries,
+ QPolarChart, QValueAxis, QChart,
+ QDateTimeAxis)
+from PyQt5 import uic
+
+from login_view import LoginWindow
+from video_thread_mp import producer
+from js08_settings import JS08SettingWidget
+from model import JS08Settings
+from curve_thread import CurveThread
+from clock import clockclock
+
+os.environ['VLC_VERBOSE'] = '-1'
+
+
+def resource_path(relative_path: str):
+ """
+ Get absolute path to resource, works for dev and for PyInstaller
+
+ :param relative_path: Files to reference
+ :return: os.path.join
+ """
+ try:
+ base_path = sys._MEIPASS
+ except Exception:
+ base_path = os.path.abspath('.')
+
+ return os.path.join(base_path, relative_path)
+
+
+class Consumer(QThread):
+ poped = pyqtSignal(str)
+
+ def __init__(self, q):
+ super().__init__()
+ self.q = q
+ self.running = True
+
+ def run(self):
+ while self.running:
+ if not self.q.empty():
+ data = q.get()
+ self.poped.emit(data)
+
+ def pause(self):
+ self.running = False
+
+ def resume(self):
+ self.running = True
+
+
+class VisibilityView(QChartView):
+
+ def __init__(self, parent: QWidget, maxlen: int):
+ super().__init__(parent)
+ self.setMinimumSize(200, 200)
+ self.setMaximumSize(600, 400)
+
+ self.maxlen = maxlen
+ self.epoch = []
+ self.vis = []
+ self.flag = False
+
+ now = QDateTime.currentSecsSinceEpoch()
+ str_now = str(now)
+ sequence = '0'
+ indicies = (10, 10)
+ # print(sequence.join([str_now[:indicies[0] - 1], str_now[indicies[1]:]]))
+ now = int(sequence.join([str_now[:indicies[0] - 1], str_now[indicies[1]:]]))
+
+ current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(now))
+ year = current_time[:4]
+ md = current_time[5:7] + current_time[8:10]
+ # zeros = [(t * 1000, -1) for t in range(now - maxlen * 60, now, 60)]
+ # self.data = collections.deque(zeros, maxlen=maxlen)
+
+ self.setRenderHint(QPainter.Antialiasing)
+
+ chart = QChart(title='Visibility')
+ chart.legend().setVisible(False)
+
+ self.setChart(chart)
+ self.series = QLineSeries()
+ chart.addSeries(self.series)
+
+ axis_x = QDateTimeAxis()
+ axis_x.setFormat('hh:mm')
+ axis_x.setTitleText('Time')
+
+ save_path = os.path.join(f'{JS08Settings.get("data_csv_path")}/PNM_9031RV_front/{year}')
+ file = f'{save_path}/{md}.csv'
+ if os.path.isfile(f'{file}') is False:
+
+ zeros = [(t * 1000, -1) for t in range(now - maxlen * 60, now, 60)]
+ self.data = collections.deque(zeros, maxlen=maxlen)
+
+ left = QDateTime.fromMSecsSinceEpoch(self.data[0][0])
+ right = QDateTime.fromMSecsSinceEpoch(self.data[-1][0])
+ # left = QDateTime.fromMSecsSinceEpoch(now - 3600 * 24)
+ # right = QDateTime.fromMSecsSinceEpoch(now * 1000)
+ axis_x.setRange(left, right)
+ chart.setAxisX(axis_x, self.series)
+ else:
+
+ result = pd.read_csv(f'{save_path}/{md}.csv')
+ epoch = result['epoch'].tolist()
+ vis_list = result['visibility'].tolist()
+
+ # data = [(t * 1000, -1) for t in range(now - maxlen * 60, now, 60)]
+ data = []
+
+ for i in range(len(epoch)):
+ # zeros = [(t * 1000, vis_list[i]) for t in range(now - maxlen * 60, now, 60)]
+ data.append((epoch[i] * 1000, vis_list[i]))
+ # if epoch[i] * 1000 in self.data[i]:
+ # print('!!!!!!!!!!')
+ # self.data.append((epoch[i] * 1000, vis_list[i]))
+ self.data = collections.deque(data, maxlen=maxlen)
+ # print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(epoch[i])))
+
+ left = QDateTime.fromMSecsSinceEpoch(self.data[0][0])
+ right = QDateTime.fromMSecsSinceEpoch(self.data[-1][0])
+ axis_x.setRange(left, right)
+ chart.setAxisX(axis_x, self.series)
+
+ axis_y = QValueAxis()
+ axis_y.setRange(0, 20)
+ # axis_y.setLabelsColor(QColor(255, 255, 255, 255))
+ axis_y.setLabelFormat('%d')
+ axis_y.setTitleText('Distance (km)')
+ chart.setAxisY(axis_y, self.series)
+
+ data_point = [QPointF(t, v) for t, v in self.data]
+ self.series.append(data_point)
+
+ @pyqtSlot(int, list)
+ def refresh_stats(self, epoch: int, vis_list: list):
+
+ # print(len(epoch), len(vis))
+
+ # now = QDateTime.currentSecsSinceEpoch()
+
+ if len(vis_list) == 0:
+ vis_list = [0]
+ prev_vis = self.prevailing_visibility(vis_list)
+ self.data.append((epoch * 1000, prev_vis))
+
+ left = QDateTime.fromMSecsSinceEpoch(self.data[0][0])
+ right = QDateTime.fromMSecsSinceEpoch(self.data[-1][0])
+ # left = QDateTime.fromMSecsSinceEpoch(now - 3600 * 24 * 1000)
+ # right = QDateTime.fromMSecsSinceEpoch(now * 1000)
+ self.chart().axisX().setRange(left, right)
+
+ data_point = [QPointF(t, v) for t, v in self.data]
+ self.series.replace(data_point)
+
+ # for i in range(len(epoch)):
+ # # self.data.append((epoch[i], vis_list[i]))
+ # self.series.append(epoch[i], vis_list[i])
+
+ # self.series.replace([QPointF(1649725277.0, 5)])
+
+ # print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(self.data[-1][0] / 1000)))
+
+ # self.axis_x.setRange(left, right)
+ # self.chart.setAxisX(self.axis_x, self.series)
+
+ # print(self.flag)
+ # if self.flag is False:
+ # for i in range(len(epoch)):
+ # self.series.append(epoch[i], vis[i])
+ # self.flag = True
+ # else:
+ # self.series.append(epoch[-1], vis[-1])
+
+ # self.epoch = epoch
+ # self.vis = vis
+
+ # self.chart.removeSeries(self.series)
+
+ # now = QDateTime.currentSecsSinceEpoch()
+ # zeros = [(t * 1000, -1) for t in range(now - self.maxlen * 60, now, 60)]
+ # self.data = collections.deque(zeros, maxlen=self.maxlen)
+
+ # self.setRenderHint(QPainter.Antialiasing)
+
+ # self.chart = QChart()
+ # self.chart.legend().setVisible(False)
+ # self.series.clear()
+ # self.series = QLineSeries()
+
+ # if len(self.epoch) == 0:
+ # for i in range(len(self.epoch)):
+ # print(i)
+ # self.series.append(self.epoch[i], self.vis[i])
+ # else:
+ # self.series.append(self.epoch[-1], self.vis[-1])
+ # print(self.epoch[-1], self.vis[-1])
+
+ # print(epoch, vis)
+ # print(len(epoch), len(vis))
+
+ # self.setChart(self.chart)
+ # self.chart.addSeries(self.series)
+
+ def prevailing_visibility(self, vis: list) -> float:
+ if None in vis:
+ return 0
+
+ sorted_vis = sorted(vis, reverse=True)
+ prevailing = sorted_vis[(len(sorted_vis) - 1) // 2]
+
+ return prevailing
+
+ def mouseDoubleClickEvent(self, event):
+ # view = GraphRangeView()
+ # view.exec_()
+ print('?')
+
+
+class DiscernmentView(QChartView):
+
+ def __init__(self, parent: QWidget):
+ super().__init__(parent)
+ self.setRenderHint(QPainter.Antialiasing)
+ self.setMinimumSize(200, 200)
+ self.setMaximumSize(600, 400)
+
+ chart = QPolarChart(title='Discernment Visibility')
+ chart.legend().setAlignment(Qt.AlignRight)
+ chart.legend().setMarkerShape(QLegend.MarkerShapeCircle)
+ # chart.legend().setColor(QColor(255, 255, 255, 255))
+ # chart.setTitleBrush(QColor(255, 255, 255, 255))
+ # chart.setBackgroundBrush(QColor(0, 0, 0, 255))
+ self.setChart(chart)
+
+ # self.positives = QScatterSeries(name='Visibility')
+ # self.negatives = QScatterSeries(name='Negative')
+ # self.positives.setColor(QColor('green'))
+ # self.negatives.setColor(QColor('red'))
+ # self.positives.setMarkerSize(5)
+ # self.negatives.setMarkerSize(10)
+ # chart.addSeries(self.positives)
+ # chart.addSeries(self.negatives)
+
+ self.series = QLineSeries()
+ self.series.setName('Visibility')
+ self.series.setColor(QColor('green'))
+ # self.series.append([QPointF(0, 0), QPoint(45, 10), QPoint(90, 5), QPointF(135, 5),
+ # QPointF(180, 10), QPointF(225, 10), QPointF(270, 15), QPointF(315, 15),
+ # QPointF(360, 0)])
+ chart.addSeries(self.series)
+
+ axis_x = QValueAxis()
+ axis_x.setTickCount(9)
+ # axis_x.setLabelsColor(QColor(255, 255, 255, 255))
+ axis_x.setRange(0, 360)
+ axis_x.setLabelFormat('%d \xc2\xb0')
+ axis_x.setTitleText('Azimuth (deg)')
+ axis_x.setTitleVisible(False)
+ # chart.setAxisX(axis_x, self.positives)
+ # chart.setAxisX(axis_x, self.negatives)
+ chart.setAxisX(axis_x, self.series)
+
+ axis_y = QValueAxis()
+ # axis_y.setLabelsColor(QColor(255, 255, 255, 255))
+ axis_y.setRange(0, 20)
+ axis_y.setLabelFormat('%d km')
+ axis_y.setTitleText('Distance (km)')
+ axis_y.setTitleVisible(False)
+ # chart.setAxisY(axis_y, self.positives)
+ # chart.setAxisY(axis_y, self.negatives)
+ chart.setAxisY(axis_y, self.series)
+
+ # self.refresh_stats()
+
+ def refresh_stats(self, visibility: dict):
+ # az0 = 22.5 # 0 ~ 45°
+ # az1 = 67.5 # 45 ~ 90°
+ # az2 = 112.5 # 90 ~ 135°
+ # az3 = 157.5 # 135 ~ 180°
+ # az4 = 202.5 # 180 ~ 225°
+ # az5 = 247.5 # 225 ~ 270°
+ # az6 = 292.5 # 270 ~ 315°
+ # az7 = 337.5 # 315 ~ 360°
+ #
+ # positives = []
+ # negatives = [(0, 4), (0, 9), (0, 14),
+ # (45, 5), (45, 10), (45, 15),
+ # (90, 5), (90, 10), (90, 15),
+ # (135, 5), (135, 10), (135, 15),
+ # (180, 5), (180, 10), (180, 15),
+ # (225, 5), (225, 10), (225, 15),
+ # (270, 5), (270, 10), (270, 15),
+ # (315, 5), (315, 10), (315, 15)]
+ # negatives = [(az0, 4), (az1, 7), (az2, 8), (az3, 6), (az4, 8), (az5, 7), (az6, 8), (az7, 9)]
+ #
+ # pos_point = [QPointF(a, d) for a, d in positives]
+ # self.positives.replace(pos_point)
+ # neg_point = [QPointF(a, d) for a, d in negatives]
+ # self.negatives.replace(neg_point)
+
+ a = random.randint(0, 20)
+ b = random.randint(0, 20)
+ c = random.randint(0, 20)
+ d = random.randint(0, 20)
+ e = random.randint(0, 20)
+ f = random.randint(0, 20)
+ g = random.randint(0, 20)
+ h = random.randint(0, 20)
+
+ self.series.replace([
+ QPointF(0, float(visibility.get('front_N'))), QPointF(45, float(visibility.get('front_NE'))),
+ QPointF(90, float(visibility.get('front_E'))), QPointF(135, float(visibility.get('rear_SE'))),
+ QPointF(180, float(visibility.get('rear_S'))), QPointF(225, float(visibility.get('rear_SW'))),
+ QPointF(270, float(visibility.get('rear_W'))), QPointF(315, float(visibility.get('front_NW'))),
+ QPointF(360, float(visibility.get('front_N')))
+ ])
+
+ def random_refresh(self):
+ # az0 = 22 # 0 ~ 45°
+ # az1 = 67 # 45 ~ 90°
+ # az2 = 112 # 90 ~ 135°
+ # az3 = 157 # 135 ~ 180°
+ # az4 = 202 # 180 ~ 225°
+ # az5 = 247 # 225 ~ 270°
+ # az6 = 292 # 270 ~ 315°
+ # az7 = 337 # 315 ~ 360°
+
+ a = random.randint(0, 20)
+ b = random.randint(0, 20)
+ c = random.randint(0, 20)
+ d = random.randint(0, 20)
+ e = random.randint(0, 20)
+ f = random.randint(0, 20)
+ g = random.randint(0, 20)
+ h = random.randint(0, 20)
+ # print(a, b, c, d, e, f, g, h)
+
+ self.series.replace([QPointF(0, a), QPointF(45, b), QPointF(90, c), QPointF(135, d),
+ QPointF(180, e), QPointF(225, f), QPointF(270, g), QPointF(315, h),
+ QPointF(360, a)])
+ # self.series.replace([QPointF(0, 5), QPoint(45, 6), QPoint(90, 7), QPointF(135, 8),
+ # QPointF(180, 9), QPointF(225, 10), QPointF(270, 11), QPointF(315, 12),
+ # QPointF(360, 13)])
+
+ def mouseDoubleClickEvent(self, event):
+ print('ddable click76')
+
+
+# class PolarPlot(QChartView):
+# def __init__(self, parent: QWidget):
+# super().__init__(parent)
+# self.setRenderHint(QPainter.Antialiasing)
+# self.setMinimumSize(200, 200)
+# self.setMaximumSize(600, 400)
+#
+# # self.main_widget = QWidget()
+# # self.setCentralWidget(self.main_widget)
+# #
+# chart = QChart()
+# chart.legend().setVisible(False)
+# # vbox = QVBoxLayout(self.main_widget)
+# # vbox.addWidget()
+#
+# data = pd.DataFrame({'distance': [5, 10, 15, 20, 15, 10, 5, 10]})
+# compass = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW']
+# # index = []
+#
+# dist = data['distance']
+# dist_list = dist.values.tolist()
+# min_value = min(dist_list)
+#
+# # for i in range(len(dist_list)):
+# # if dist_list[i] == min_value:
+# # index.append(i)
+#
+# self.fig, self.ax = plt.subplots(1, 1, subplot_kw={'projection': 'polar'})
+# self.ax.set_theta_zero_location('N')
+# self.ax.set_theta_direction(-1)
+#
+# # for i in range(len(dist_list)):
+# # if i in index:
+# # plt.bar(0.25 * np.pi * (1 + 2 * i) / 2, int(dist_list[i]), width=0.25 * np.pi, color=['red'])
+# # else:
+# # plt.bar(0.25 * np.pi * (1 + 2 * i) / 2, int(dist_list[i]), width=0.25 * np.pi, color=['green'])
+#
+# self.canvas = FigureCanvas(self.fig)
+# self.canvas.resize(600, 400)
+# # self.setChart(self.canvas)
+#
+# self.ax.set_xlabel('Visibility', fontsize=10)
+# self.ax.set_rgrids(np.arange(0, 20, 5))
+# # self.ax.set_xticklabels(compass)
+# self.ax.set_rorigin(-10)
+#
+# self.refresh_stats(dist_list)
+#
+# @pyqtSlot(list)
+# def refresh_stats(self, distance: list):
+# self.ax.clear()
+#
+# self.ax.set_theta_zero_location('N')
+# self.ax.set_theta_direction(-1)
+# self.ax.set_xlabel('Visibility', fontsize=10)
+#
+# # self.ax.set_rgrids(np.arange(0, 20, 5))
+# self.ax.set_rgrids([0, 5, 10, 15, 20])
+# self.ax.set_xticklabels(['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'])
+# self.ax.set_rorigin(-10)
+#
+# # index = []
+# min_value = min(distance)
+#
+# for i in range(len(distance)):
+# if distance[i] == min_value:
+# # index.append(i)
+# # if i in index:
+# plt.bar(0.25 * np.pi * (1 + 2 * i) / 2, int(distance[i]), width=0.25 * np.pi, color=['red'])
+# else:
+# plt.bar(0.25 * np.pi * (1 + 2 * i) / 2, int(distance[i]), width=0.25 * np.pi, color=['green'])
+#
+# self.canvas.draw()
+#
+# def mouseDoubleClickEvent(self, event):
+# print('hi22')
+
+
+class ThumbnailView(QMainWindow):
+
+ def __init__(self, image_file_name: str, date: int):
+ super().__init__()
+
+ ui_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
+ 'resources/thumbnail_view.ui')
+ uic.loadUi(resource_path(ui_path), self)
+
+ if os.path.isfile(
+ f'{JS08Settings.get("image_save_path")}/vista/PNM_9031RV_front/{date}/{image_file_name}.png') and \
+ os.path.isfile(f'{JS08Settings.get("image_save_path")}/vista/PNM_9031RV_rear/{date}/{image_file_name}.png'):
+
+ front_image = f'{JS08Settings.get("image_save_path")}/vista/PNM_9031RV_front/{date}/{image_file_name}.png'
+ rear_image = f'{JS08Settings.get("image_save_path")}/vista/PNM_9031RV_rear/{date}/{image_file_name}.png'
+
+ self.front_image.setPixmap(
+ QPixmap(front_image).scaled(self.width(), self.height(), Qt.KeepAspectRatio))
+ self.rear_image.setPixmap(
+ QPixmap(rear_image).scaled(self.width(), self.height(), Qt.KeepAspectRatio))
+
+ # self.front_image.setPixmap(QPixmap(front_image))
+ # self.rear_image.setPixmap(QPixmap(rear_image))
+ else:
+ print('no file')
+
+
+class Js08MainWindow(QMainWindow):
+
+ def __init__(self, q, _q):
+ super().__init__()
+
+ # login_window = LoginWindow()
+ # login_window.exec_()
+
+ ui_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
+ 'resources/main_window.ui')
+ uic.loadUi(resource_path(ui_path), self)
+ # self.showFullScreen()
+
+ self._plot = VisibilityView(self, 1440)
+ # self._polar = PolarPlot(self)
+ self._polar = DiscernmentView(self)
+
+ self.view = None
+ self.km_mile_convert = False
+ self.visibility = 0
+ self.pm_text = 0
+ self.year_date = None
+ self.epoch = []
+ self.q_list = []
+ self.q_list_scale = 1440
+ self.data_date = []
+ self.data_time = []
+ self.data_vis = []
+
+ self.blank_label_front = QLabel()
+ self.blank_label_rear = QLabel()
+ self.blank_label_front.setStyleSheet('background-color: #FFFFFF')
+ self.blank_label_rear.setStyleSheet('background-color: #FFFFFF')
+ # self.blank_label_front.raise_()
+ # self.blank_label_rear.raise_()
+
+ self.front_video_widget = VideoWidget(self)
+ self.front_video_widget.on_camera_change(JS08Settings.get('front_main'))
+
+ self.rear_video_widget = VideoWidget(self)
+ self.rear_video_widget.on_camera_change(JS08Settings.get('rear_main'))
+
+ self.video_horizontalLayout.addWidget(self.front_video_widget.video_frame)
+ self.video_horizontalLayout.addWidget(self.rear_video_widget.video_frame)
+
+ self.graph_horizontalLayout.addWidget(self._plot)
+ self.polar_horizontalLayout.addWidget(self._polar)
+
+ self.setting_button.enterEvent = self.btn_on
+ self.setting_button.leaveEvent = self.btn_off
+
+ self.consumer = Consumer(q)
+ self.consumer.poped.connect(self.clock)
+ self.consumer.start()
+
+ self.video_thread = CurveThread(_q)
+ self.video_thread.poped.connect(self.print_data)
+ self.video_thread.start()
+
+ self.click_style = 'border: 1px solid red;'
+
+ self.alert.clicked.connect(self.alert_test)
+
+ self.c_vis_label.mousePressEvent = self.unit_convert
+ self.p_vis_label.mousePressEvent = self.test
+
+ self.label_1hour_front.mouseDoubleClickEvent = self.thumbnail_click1_front
+ self.label_1hour_rear.mouseDoubleClickEvent = self.thumbnail_click1_rear
+ self.label_2hour_front.mouseDoubleClickEvent = self.thumbnail_click2_front
+ self.label_2hour_rear.mouseDoubleClickEvent = self.thumbnail_click2_rear
+ self.label_3hour_front.mouseDoubleClickEvent = self.thumbnail_click3_front
+ self.label_3hour_rear.mouseDoubleClickEvent = self.thumbnail_click3_rear
+
+ self.setting_button.clicked.connect(self.setting_btn_click)
+ self.azimuth_button.clicked.connect(self.azimuth_btn_click)
+ # self.button.clicked.connect(self.button_click)
+
+ self.show()
+
+ def front_camera_pause(self, event):
+ self.front_video_widget.media_player.pause()
+
+ def rear_camera_pause(self, event):
+ self.rear_video_widget.media_player.pause()
+
+ def alert_test(self):
+ self.alert.setIcon(QIcon('resources/red.png'))
+ # a = [5, 10, 15, 20, 15, 10, 5, 10]
+ # random.shuffle(a)
+ # self._polar.refresh_stats(a)
+
+ def reset_StyleSheet(self):
+ self.label_1hour_front.setStyleSheet('')
+ self.label_1hour_rear.setStyleSheet('')
+ self.label_2hour_front.setStyleSheet('')
+ self.label_2hour_rear.setStyleSheet('')
+ self.label_3hour_front.setStyleSheet('')
+ self.label_3hour_rear.setStyleSheet('')
+
+ def thumbnail_view(self, file_name: str):
+ if self.isFullScreen():
+ self.view = ThumbnailView(file_name, int(file_name[2:8]))
+ self.view.setGeometry(QRect(self.video_horizontalLayout.geometry().x(),
+ self.video_horizontalLayout.geometry().y() + 21,
+ self.video_horizontalLayout.geometry().width(),
+ self.video_horizontalLayout.geometry().height()))
+ self.view.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)
+ self.view.setWindowModality(Qt.ApplicationModal)
+ self.view.show()
+ self.view.raise_()
+
+ else:
+ self.view = QMainWindow()
+
+ def thumbnail_click1_front(self, e):
+
+ name = self.label_1hour_time.text()[:2] + self.label_1hour_time.text()[3:]
+ epoch = time.strftime('%Y%m%d', time.localtime(time.time()))
+ self.thumbnail_view(epoch + name + '00')
+
+ self.reset_StyleSheet()
+ self.label_1hour_front.setStyleSheet(self.click_style)
+ self.monitoring_label.setText(f' {self.label_1hour_time.text()} image')
+
+ QTimer.singleShot(5000, self.thumbnail_show)
+
+ def thumbnail_click1_rear(self, e):
+ name = self.label_1hour_time.text()[:2] + self.label_1hour_time.text()[3:]
+ epoch = time.strftime('%Y%m%d', time.localtime(time.time()))
+ self.thumbnail_view(epoch + name + '00')
+
+ self.reset_StyleSheet()
+ self.label_1hour_rear.setStyleSheet(self.click_style)
+ self.monitoring_label.setText(f' {self.label_1hour_time.text()} image')
+
+ QTimer.singleShot(5000, self.thumbnail_show)
+
+ def thumbnail_click2_front(self, e):
+ name = self.label_2hour_time.text()[:2] + self.label_2hour_time.text()[3:]
+ epoch = time.strftime('%Y%m%d', time.localtime(time.time()))
+ self.thumbnail_view(epoch + name + '00')
+
+ self.reset_StyleSheet()
+ self.label_2hour_front.setStyleSheet(self.click_style)
+ self.monitoring_label.setText(f' {self.label_2hour_time.text()} image')
+
+ QTimer.singleShot(5000, self.thumbnail_show)
+
+ def thumbnail_click2_rear(self, e):
+ name = self.label_2hour_time.text()[:2] + self.label_2hour_time.text()[3:]
+ epoch = time.strftime('%Y%m%d', time.localtime(time.time()))
+ self.thumbnail_view(epoch + name + '00')
+
+ self.reset_StyleSheet()
+ self.label_2hour_rear.setStyleSheet(self.click_style)
+ self.monitoring_label.setText(f' {self.label_2hour_time.text()} image')
+
+ QTimer.singleShot(5000, self.thumbnail_show)
+
+ def thumbnail_click3_front(self, e):
+ name = self.label_3hour_time.text()[:2] + self.label_3hour_time.text()[3:]
+ epoch = time.strftime('%Y%m%d', time.localtime(time.time()))
+ self.thumbnail_view(epoch + name + '00')
+
+ self.reset_StyleSheet()
+ self.label_3hour_front.setStyleSheet(self.click_style)
+ self.monitoring_label.setText(f' {self.label_3hour_time.text()} image')
+
+ QTimer.singleShot(5000, self.thumbnail_show)
+
+ def thumbnail_click3_rear(self, e):
+ name = self.label_3hour_time.text()[:2] + self.label_3hour_time.text()[3:]
+ epoch = time.strftime('%Y%m%d', time.localtime(time.time()))
+ self.thumbnail_view(epoch + name + '00')
+
+ self.reset_StyleSheet()
+ self.label_3hour_rear.setStyleSheet(self.click_style)
+ self.monitoring_label.setText(f' {self.label_3hour_time.text()} image')
+
+ QTimer.singleShot(5000, self.thumbnail_show)
+
+ def thumbnail_show(self):
+ self.monitoring_label.setText(' Monitoring')
+ self.reset_StyleSheet()
+ self.view.close()
+
+ @pyqtSlot()
+ def setting_btn_click(self):
+ self.front_video_widget.media_player.stop()
+ self.rear_video_widget.media_player.stop()
+ self.consumer.pause()
+
+ dlg = JS08SettingWidget()
+ dlg.show()
+ dlg.setWindowModality(Qt.ApplicationModal)
+ dlg.exec_()
+
+ self.front_video_widget.media_player.play()
+ self.rear_video_widget.media_player.play()
+ self.consumer.resume()
+ self.consumer.start()
+
+ def azimuth_btn_click(self):
+ # self.front_video_widget.flag_status()
+ # self.rear_video_widget.flag_status()
+ # self.front_video_widget.update()
+ # self.rear_video_widget.update()
+ print(self.front_video_widget.media_player.video_get_width(0))
+ print(self.front_video_widget.media_player.video_get_size())
+
+ def button_click(self):
+ pass
+
+ def btn_on(self, event):
+ self.setting_button.setIcon(QIcon('resources/settings_on.png'))
+
+ def btn_off(self, event):
+ self.setting_button.setIcon(QIcon('resources/settings.png'))
+
+ def unit_convert(self, event):
+ if self.km_mile_convert:
+ self.km_mile_convert = False
+ elif self.km_mile_convert is False:
+ self.km_mile_convert = True
+
+ def test(self, event):
+ print(self.front_video_widget.media_player.video_get_width(0))
+
+ def get_data(self, year, month_day):
+ """
+ Prevailing visibility of front camera data
+
+ :param year: Name of the year folder to access
+ :param month_day: Name of the month and day folder to access
+ :return: date, epoch, visibility in list type
+
+ """
+
+ save_path = os.path.join(f'{JS08Settings.get("data_csv_path")}/PNM_9031RV_front/{year}')
+
+ if os.path.isfile(f'{save_path}/{month_day}.csv'):
+ result = pd.read_csv(f'{save_path}/{month_day}.csv')
+ data_datetime = result['date'].tolist()
+ data_epoch = result['epoch'].tolist()
+ data_visibility = result['visibility'].tolist()
+
+ return data_datetime, data_epoch, data_visibility
+
+ else:
+ return [], [], []
+
+ @pyqtSlot(dict)
+ def print_data(self, visibility: dict):
+
+ visibility_front = round(float(visibility.get('visibility_front')), 3)
+ visibility_rear = round(float(visibility.get('visibility_rear')), 3)
+
+ epoch = QDateTime.currentSecsSinceEpoch()
+ current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(epoch))
+ year = current_time[:4]
+ md = current_time[5:7] + current_time[8:10]
+
+ get_date, get_epoch, self.q_list = self.get_data(year, md)
+
+ if len(self.q_list) == 0 or self.q_list_scale != len(self.q_list):
+ self.q_list = []
+ get_date = []
+ get_epoch = []
+ for i in range(self.q_list_scale):
+ self.q_list.append(visibility_front)
+ result_vis = np.mean(self.q_list)
+ else:
+ self.q_list.pop(0)
+ self.q_list.append(visibility_front)
+ result_vis = np.mean(self.q_list)
+
+ if len(self.data_date) >= self.q_list_scale or len(self.data_vis) >= self.q_list_scale:
+ self.data_date.pop(0)
+ self.data_time.pop(0)
+ self.data_vis.pop(0)
+
+ self.data_date.append(current_time)
+ self.data_time.append(epoch)
+ self.data_vis.append(visibility_front)
+
+ save_path_front = os.path.join(f'{JS08Settings.get("data_csv_path")}/PNM_9031RV_front/{year}')
+ save_path_rear = os.path.join(f'{JS08Settings.get("data_csv_path")}/PNM_9031RV_rear/{year}')
+
+ file_front = f'{save_path_front}/{md}.csv'
+ file_rear = f'{save_path_rear}/{md}.csv'
+
+ result_front = pd.DataFrame(columns=['date', 'epoch', 'visibility', 'W', 'NW', 'N', 'NE', 'E'])
+ result_rear = pd.DataFrame(columns=['date', 'epoch', 'visibility', 'E', 'SE', 'S', 'SW', 'W'])
+
+ if os.path.isfile(f'{file_front}') is False or os.path.isfile(f'{file_rear}') is False:
+ os.makedirs(f'{save_path_front}', exist_ok=True)
+ os.makedirs(f'{save_path_rear}', exist_ok=True)
+ result_front.to_csv(f'{file_front}', mode='w', index=False)
+ result_rear.to_csv(f'{file_rear}', mode='w', index=False)
+
+ result_front['date'] = [self.data_date[-1]]
+ result_front['epoch'] = [self.data_time[-1]]
+ result_front['visibility'] = [self.data_vis[-1]]
+ result_front['W'] = round(float(visibility.get('front_W')), 3)
+ result_front['NW'] = round(float(visibility.get('front_NW')), 3)
+ result_front['N'] = round(float(visibility.get('front_N')), 3)
+ result_front['NE'] = round(float(visibility.get('front_NE')), 3)
+ result_front['E'] = round(float(visibility.get('front_E')), 3)
+ result_front.to_csv(f'{file_front}', mode='a', index=False, header=False)
+
+ result_rear['date'] = [self.data_date[-1]]
+ result_rear['epoch'] = [self.data_time[-1]]
+ result_rear['visibility'] = visibility_rear
+ result_rear['E'] = round(float(visibility.get('rear_E')), 3)
+ result_rear['SE'] = round(float(visibility.get('rear_SE')), 3)
+ result_rear['S'] = round(float(visibility.get('rear_S')), 3)
+ result_rear['SW'] = round(float(visibility.get('rear_SW')), 3)
+ result_rear['W'] = round(float(visibility.get('rear_W')), 3)
+ result_rear.to_csv(f'{file_rear}', mode='a', index=False, header=False)
+
+ self.visibility = round(float(result_vis), 3)
+
+ self._plot.refresh_stats(epoch, self.q_list)
+ self._polar.refresh_stats(visibility)
+ # self._polar.random_refresh()
+ # print(f'visibility: {visibility}')
+
+ @pyqtSlot(str)
+ def clock(self, data):
+ self.blank_label_front.setGeometry(self.front_video_widget.geometry())
+ self.blank_label_rear.setGeometry(self.rear_video_widget.geometry())
+
+ current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(float(data)))
+ self.year_date = current_time[2:4] + current_time[5:7] + current_time[8:10]
+ self.real_time_label.setText(current_time)
+ # self.p_vis_label.setText(f'{self.pm_text} ㎍/㎥')
+
+ if self.visibility != 0:
+ ext = 3.912 / self.visibility
+ hd = 89
+ self.pm_text = round((ext * 1000 / 4 / 2.5) / (1 + 5.67 * ((hd / 100) ** 5.8)), 2)
+
+ if self.km_mile_convert:
+ self.c_vis_label.setText(f'{format(round(self.visibility / 1.609, 2), ",")} mile')
+
+ elif self.km_mile_convert is False:
+ self.c_vis_label.setText(f'{format(int(self.visibility * 1000), ",")} m')
+
+ if current_time[-1:] == '0':
+ self.thumbnail_refresh()
+ # self._plot.refresh_stats(QDateTime.currentSecsSinceEpoch(), self.q_list)
+
+ if int(self.visibility * 1000) <= JS08Settings.get('visibility_alert_limit'):
+ self.alert.setIcon(QIcon('resources/red.png'))
+ else:
+ self.alert.setIcon(QIcon('resources/green.png'))
+
+ def thumbnail_refresh(self):
+
+ one_hour_ago = time.strftime('%Y%m%d%H%M00', time.localtime(time.time() - 3600))
+ two_hour_ago = time.strftime('%Y%m%d%H%M00', time.localtime(time.time() - 3600 * 2))
+ three_hour_ago = time.strftime('%Y%m%d%H%M00', time.localtime(time.time() - 3600 * 3))
+ # four_hour_ago = time.strftime('%Y%m%d%H%M00', time.localtime(time.time() - 3600 * 4))
+ # five_hour_ago = time.strftime('%Y%m%d%H%M00', time.localtime(time.time() - 3600 * 5))
+ # six_hour_ago = time.strftime('%Y%m%d%H%M00', time.localtime(time.time() - 3600 * 6))
+
+ # one_min_ago = time.strftime('%Y%m%d%H%M00', time.localtime(time.time() - 60))
+ # two_min_ago = time.strftime('%Y%m%d%H%M00', time.localtime(time.time() - 60 * 2))
+ # three_min_ago = time.strftime('%Y%m%d%H%M00', time.localtime(time.time() - 60 * 3))
+ # four_min_ago = time.strftime('%Y%m%d%H%M00', time.localtime(time.time() - 60 * 4))
+ # five_min_ago = time.strftime('%Y%m%d%H%M00', time.localtime(time.time() - 60 * 5))
+ # six_min_ago = time.strftime('%Y%m%d%H%M00', time.localtime(time.time() - 60 * 6))
+
+ self.label_1hour_time.setText(time.strftime('%H:%M', time.localtime(time.time() - 3600)))
+ self.label_2hour_time.setText(time.strftime('%H:%M', time.localtime(time.time() - 3600 * 2)))
+ self.label_3hour_time.setText(time.strftime('%H:%M', time.localtime(time.time() - 3600 * 3)))
+ # self.label_4hour_time.setText(time.strftime('%H:%M', time.localtime(time.time(w) - 3600 * 4)))
+ # self.label_5hour_time.setText(time.strftime('%H:%M', time.localtime(time.time() - 3600 * 5)))
+ # self.label_6hour_time.setText(time.strftime('%H:%M', time.localtime(time.time() - 3600 * 6)))
+
+ # self.label_1hour_time.setText(time.strftime('%H:%M', time.localtime(time.time() - 60)))
+ # self.label_2hour_time.setText(time.strftime('%H:%M', time.localtime(time.time() - 60 * 2)))
+ # self.label_3hour_time.setText(time.strftime('%H:%M', time.localtime(time.time() - 60 * 3)))
+ # self.label_4hour_time.setText(time.strftime('%H:%M', time.localtime(time.time() - 60 * 4)))
+ # self.label_5hour_time.setText(time.strftime('%H:%M', time.localtime(time.time() - 60 * 5)))
+ # self.label_6hour_time.setText(time.strftime('%H:%M', time.localtime(time.time() - 60 * 6)))
+
+ # self.label_1hour_front.setPixmap(
+ # QPixmap(
+ # f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_front/{self.year_date}/{one_min_ago}.jpg')
+ # .scaled(self.label_1hour_front.width(), self.label_1hour_front.height() - 5, Qt.IgnoreAspectRatio))
+ # self.label_1hour_rear.setPixmap(
+ # QPixmap(
+ # f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_rear/{self.year_date}/{one_min_ago}.jpg')
+ # .scaled(self.label_1hour_rear.width(), self.label_1hour_rear.height() - 5, Qt.IgnoreAspectRatio))
+ # self.label_2hour_front.setPixmap(
+ # QPixmap(
+ # f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_front/{self.year_date}/{two_min_ago}.jpg')
+ # .scaled(self.label_2hour_front.width(), self.label_2hour_front.height() - 5, Qt.IgnoreAspectRatio))
+ # self.label_2hour_rear.setPixmap(
+ # QPixmap(
+ # f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_rear/{self.year_date}/{two_min_ago}.jpg')
+ # .scaled(self.label_2hour_rear.width(), self.label_2hour_rear.height() - 5, Qt.IgnoreAspectRatio))
+ # self.label_3hour_front.setPixmap(
+ # QPixmap(
+ # f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_front/{self.year_date}/{three_min_ago}.jpg')
+ # .scaled(self.label_3hour_front.width(), self.label_3hour_front.height() - 5, Qt.IgnoreAspectRatio))
+ # self.label_3hour_rear.setPixmap(
+ # QPixmap(
+ # f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_rear/{self.year_date}/{three_min_ago}.jpg')
+ # .scaled(self.label_3hour_rear.width(), self.label_3hour_rear.height() - 5, Qt.IgnoreAspectRatio))
+
+ if os.path.isfile(
+ f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_front/{self.year_date}/{one_hour_ago}.jpg'):
+ self.label_1hour_front.setPixmap(
+ QPixmap(
+ f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_front/{self.year_date}/{one_hour_ago}.jpg')
+ .scaled(self.label_1hour_front.width(), self.label_1hour_front.height() - 5, Qt.IgnoreAspectRatio))
+ self.label_1hour_rear.setPixmap(
+ QPixmap(
+ f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_rear/{self.year_date}/{one_hour_ago}.jpg')
+ .scaled(self.label_1hour_rear.width(), self.label_1hour_rear.height() - 5, Qt.IgnoreAspectRatio))
+
+ if os.path.isfile(
+ f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_front/{self.year_date}/{two_hour_ago}.jpg'):
+ self.label_2hour_front.setPixmap(
+ QPixmap(
+ f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_front/{self.year_date}/{two_hour_ago}.jpg')
+ .scaled(self.label_2hour_front.width(), self.label_2hour_front.height() - 5, Qt.IgnoreAspectRatio))
+ self.label_2hour_rear.setPixmap(
+ QPixmap(
+ f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_rear/{self.year_date}/{two_hour_ago}.jpg')
+ .scaled(self.label_2hour_rear.width(), self.label_2hour_rear.height() - 5, Qt.IgnoreAspectRatio))
+
+ if os.path.isfile(
+ f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_front/{self.year_date}/{three_hour_ago}.jpg'):
+ self.label_3hour_front.setPixmap(
+ QPixmap(
+ f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_front/{self.year_date}/{three_hour_ago}.jpg')
+ .scaled(self.label_3hour_front.width(), self.label_3hour_front.height() - 5, Qt.IgnoreAspectRatio))
+ self.label_3hour_rear.setPixmap(
+ QPixmap(
+ f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_rear/{self.year_date}/{three_hour_ago}.jpg')
+ .scaled(self.label_3hour_rear.width(), self.label_3hour_rear.height() - 5, Qt.IgnoreAspectRatio))
+
+ # self.label_1hour.setPixmap(
+ # QPixmap(f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_front/{self.year_date}/{one_hour_ago}.jpg'))
+ # self.label_2hour.setPixmap(
+ # QPixmap(f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_front/{self.year_date}/{two_hour_ago}.jpg'))
+ # self.label_3hour.setPixmap(
+ # QPixmap(f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_front/{self.year_date}/{three_hour_ago}.jpg'))
+ # self.label_4hour.setPixmap(
+ # QPixmap(f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_front/{self.year_date}/{four_hour_ago}.jpg'))
+ # self.label_5hour.setPixmap(
+ # QPixmap(f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_front/{self.year_date}/{five_hour_ago}.jpg'))
+ # self.label_6hour.setPixmap(
+ # QPixmap(f'{JS08Settings.get("image_save_path")}/resize/PNM_9031RV_front/{self.year_date}/{six_hour_ago}.jpg'))
+
+ def keyPressEvent(self, e):
+ """Override function QMainwindow KeyPressEvent that works when key is pressed"""
+ if e.key() == Qt.Key_F:
+ self.showFullScreen()
+ self.thumbnail_refresh()
+ if e.key() == Qt.Key_D:
+ self.showNormal()
+ self.thumbnail_refresh()
+
+ def drawLines(self, qp):
+ pen = QPen(Qt.white, 1, Qt.DotLine)
+
+ qp.setPen(pen)
+ qp.drawLine(240, 0, 240, 411)
+ qp.drawLine(480, 0, 480, 411)
+ qp.drawLine(720, 0, 720, 411)
+
+ def closeEvent(self, event):
+ self.consumer.terminate()
+ self.video_thread.terminate()
+ print(f'Close time: {time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}')
+
+
+class VideoWidget(QWidget):
+ """Video stream player using QVideoWidget"""
+
+ def __init__(self, parent: QObject = None):
+ super().__init__(parent)
+
+ self.begin = QPoint()
+ self.end = QPoint()
+ self.flag = False
+
+ args = [
+ '--rtsp-frame-buffer-size=400000',
+ '--quiet',
+ # '--no-embedded-video',
+ # '--no-video-deco',
+ # '--no-qt-video-autoresize',
+ # '--no-autoscale',
+ # '--no-plugins-cache',
+ # '--mouse-hide-timeout=0',
+ # '--sout-x264-keyint=25',
+ # '--sout-x264-ref=1'
+ ]
+
+ self.instance = vlc.Instance(args)
+ self.instance.log_unset()
+
+ self.media_player = self.instance.media_player_new()
+ self.media_player.video_set_aspect_ratio('21:9')
+
+ self.video_frame = QFrame()
+ self.blank_label = QLabel()
+ # self.blank_label.setStyleSheet('background-color: #83BCD4')
+
+ if sys.platform == 'win32':
+ self.media_player.set_hwnd(self.video_frame.winId())
+
+ # layout = QVBoxLayout(self)
+ # layout.addWidget(self.video_frame)
+
+ # self.video_frame.paintEvent = self.paint
+
+ def flag_status(self):
+ if self.flag:
+ self.flag = False
+ elif self.flag is False:
+ self.flag = True
+
+ def paint(self, event):
+
+ qp = QPainter()
+ qp.begin(self)
+ self.drawLines(qp)
+ qp.end()
+
+ def drawLines(self, qp):
+
+ pen = QPen(Qt.white, 1, Qt.DotLine)
+
+ qp.setPen(pen)
+ qp.setFont(QFont('Arial', 6))
+
+ if self.flag:
+ # if self.end.x() >= 600:
+ # self.end.setX(600)
+ #
+ # elif self.end.x() <= 360:
+ # self.end.setX(360)
+
+ self.end.setX(360)
+
+ qp.drawLine(self.width() * 0.125, 0,
+ self.width() * 0.125, self.height())
+ qp.drawLine(self.width() * 0.375, 0,
+ self.width() * 0.375, self.height())
+ qp.drawLine(self.width() * 0.625, 0,
+ self.width() * 0.625, self.height())
+ qp.drawLine(self.width() * 0.875, 0,
+ self.width() * 0.875, self.height())
+
+ if self.geometry().x() == 0:
+ qp.drawText(self.width() * 0.0625, 7, 'W')
+ qp.drawText(self.width() * 0.25, 7, 'NW')
+ qp.drawText(self.width() * 0.5, 7, 'N')
+ qp.drawText(self.width() * 0.75, 7, 'NE')
+ qp.drawText(self.width() * 0.9375, 7, 'E')
+
+ qp.drawText(self.width() * 0.0625, self.height() - 2, 'W')
+ qp.drawText(self.width() * 0.25, self.height() - 2, 'NW')
+ qp.drawText(self.width() * 0.5, self.height() - 2, 'N')
+ qp.drawText(self.width() * 0.75, self.height() - 2, 'NE')
+ qp.drawText(self.width() * 0.9375, self.height() - 2, 'E')
+
+ elif self.geometry().x() == 960:
+ qp.drawText(self.width() * 0.0625, 7, 'E')
+ qp.drawText(self.width() * 0.25, 7, 'SE')
+ qp.drawText(self.width() * 0.5, 7, 'S')
+ qp.drawText(self.width() * 0.75, 7, 'SW')
+ qp.drawText(self.width() * 0.9375, 7, 'W')
+
+ qp.drawText(self.width() * 0.0625, self.height() - 2, 'E')
+ qp.drawText(self.width() * 0.25, self.height() - 2, 'SE')
+ qp.drawText(self.width() * 0.5, self.height() - 2, 'S')
+ qp.drawText(self.width() * 0.75, self.height() - 2, 'SW')
+ qp.drawText(self.width() * 0.9375, self.height() - 2, 'W')
+
+ @pyqtSlot(str)
+ def on_camera_change(self, uri: str):
+ if uri[:4] == 'rtsp':
+ self.media_player.set_media(self.instance.media_new(uri))
+ self.media_player.play()
+
+ else:
+ pass
+
+ def mouseDoubleClickEvent(self, event):
+ print('하윙')
+
+
+class MainCtrl(QObject):
+ front_camera_changed = pyqtSignal(str)
+ rear_camera_changed = pyqtSignal(str)
+
+ def __init__(self):
+ super().__init__()
+
+ self.front_target_prepared = False
+ self.rear_target_prepared = False
+
+ self.front_camera_changed.connect(self.decompose_front_targets)
+ self.rear_camera_changed.connect(self.decompose_rear_targets)
+
+ @pyqtSlot(str)
+ def decompose_front_targets(self, _: str):
+ self.front_target_prepared = False
+ self.decompose_targets('front')
+ self.front_target_prepared = True
+
+
+if __name__ == '__main__':
+ try:
+ os.chdir(sys._MEIPASS)
+ except:
+ os.chdir(os.getcwd())
+
+ from PyQt5.QtWidgets import QApplication
+
+ print(f'Start time: {time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}')
+
+ mp.freeze_support()
+ q = Queue()
+ _q = Queue()
+
+ _producer = producer
+
+ p = Process(name='clock', target=clockclock, args=(q,), daemon=True)
+ _p = Process(name='producer', target=_producer, args=(_q,), daemon=True)
+
+ p.start()
+ _p.start()
+
+ os.makedirs(f'{JS08Settings.get("data_csv_path")}', exist_ok=True)
+ os.makedirs(f'{JS08Settings.get("target_csv_path")}', exist_ok=True)
+ os.makedirs(f'{JS08Settings.get("image_save_path")}', exist_ok=True)
+
+ app = QApplication(sys.argv)
+ screen_size = app.desktop().screenGeometry()
+ width, height = screen_size.width(), screen_size.height()
+ if width > 1920 or height > 1080:
+ QMessageBox.warning(None, 'Warning', 'JS08 is based on FHD screen.')
+ window = Js08MainWindow(q, _q)
+ sys.exit(app.exec())
diff --git a/src/js08_settings.py b/src/js08_settings.py
new file mode 100644
index 0000000..421cba4
--- /dev/null
+++ b/src/js08_settings.py
@@ -0,0 +1,668 @@
+#!/usr/bin/env python3
+#
+# Copyright 2021-2022 Sijung Co., Ltd.
+#
+# Authors:
+# cotjdals5450@gmail.com (Seong Min Chae)
+# 5jx2oh@gmail.com (Jongjin Oh)
+
+import os
+import cv2
+import time
+import numpy as np
+import pandas as pd
+from scipy.optimize import curve_fit
+
+from PyQt5 import uic
+from PyQt5.QtCore import (QPoint, QRect, Qt,
+ QTimer)
+from PyQt5.QtGui import (QPixmap, QPainter, QBrush,
+ QColor, QPen, QImage,
+ QIcon, QFont)
+from PyQt5.QtWidgets import (QApplication, QInputDialog, QDialog,
+ QMessageBox, QFileDialog, QHeaderView,
+ QTableWidget, QTableWidgetItem, QLabel)
+from PyQt5.QtChart import QChart, QChartView, QLineSeries, QValueAxis
+
+from model import JS08Settings
+import target_info
+from auto_file_delete import FileAutoDelete
+
+
+def resource_path(relative_path: str):
+ """
+ Get absolute path to resource, works for dev and for PyInstaller
+
+ :param relative_path: Files to reference
+ :return: os.path.join
+ """
+ try:
+ base_path = sys._MEIPASS
+ except Exception:
+ base_path = os.path.abspath('.')
+
+ return os.path.join(base_path, relative_path)
+
+
+class JS08SettingWidget(QDialog):
+
+ def __init__(self):
+
+ super().__init__()
+ ui_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
+ 'resources/setting_window.ui')
+ uic.loadUi(resource_path(ui_path), self)
+ self.showFullScreen()
+ self.setWindowFlag(Qt.FramelessWindowHint)
+
+ self.begin = QPoint()
+ self.end = QPoint()
+
+ self.upper_left = ()
+ self.lower_right = ()
+
+ self.target_name = []
+ self.left_range = []
+ self.right_range = []
+ self.distance = []
+ self.azimuth = []
+
+ self.isDrawing = False
+ self.draw_flag = False
+
+ self.video_width = 0
+ self.video_height = 0
+
+ self.cp_image = None
+ self.end_drawing = None
+
+ self.chart_view = None
+ self.select_target = None
+ self.select_target_flag = False
+ self.tableWidget.doubleClicked.connect(self.tableWidget_doubleClicked)
+
+ self.r_list = []
+ self.g_list = []
+ self.b_list = []
+
+ self.current_camera = 'PNM_9030V'
+ self.cam_flag = False
+
+ self.image_load()
+
+ self.flag = 0
+ # self.get_target(self.current_camera)
+
+ # Add QChart Widget in value_verticalLayout
+ if len(self.left_range) > 0:
+ self.tableWidget.setEditTriggers(QTableWidget.NoEditTriggers)
+ self.show_target_table()
+
+ if len(self.distance) > 4:
+ # self.chart_view = self.chart_draw()
+ # self.value_verticalLayout.addWidget(self.chart_view)
+ # self.chart_update()
+ pass
+
+ self.red_checkBox.clicked.connect(self.chart_update)
+ self.green_checkBox.clicked.connect(self.chart_update)
+ self.blue_checkBox.clicked.connect(self.chart_update)
+
+ self.flip_button.clicked.connect(self.camera_flip)
+ self.flip_button.enterEvent = self.btn_on
+ self.flip_button.leaveEvent = self.btn_off
+
+ self.data_csv_path_button.clicked.connect(self.data_csv_path)
+ self.target_csv_path_button.clicked.connect(self.target_csv_path)
+ self.image_save_path_button.clicked.connect(self.image_save_path)
+ self.afd_button.clicked.connect(self.afd_btn_click)
+
+ self.data_csv_path_textBrowser.setPlainText(JS08Settings.get('data_csv_path'))
+ self.target_csv_path_textBrowser.setPlainText(JS08Settings.get('target_csv_path'))
+ self.image_save_path_textBrowser.setPlainText(JS08Settings.get('image_save_path'))
+
+ self.vis_limit_spinBox.setValue(JS08Settings.get('visibility_alert_limit'))
+ self.id_lineEdit.setText(JS08Settings.get('login_id'))
+ self.pw_lineEdit.setText(JS08Settings.get('login_pw'))
+
+ self.image_size_comboBox.setCurrentIndex(JS08Settings.get('image_size'))
+
+ self.image_label.paintEvent = self.lbl_paintEvent
+ self.image_label.mousePressEvent = self.lbl_mousePressEvent
+ self.image_label.mouseMoveEvent = self.lbl_mouseMoveEvent
+ self.image_label.mouseReleaseEvent = self.lbl_mouseReleaseEvent
+
+ self.buttonBox.accepted.connect(self.accept_click)
+ self.buttonBox.rejected.connect(self.reject_click)
+
+ def show_target_table(self):
+ min_x = []
+ min_y = []
+ self.r_list = []
+ self.g_list = []
+ self.b_list = []
+
+ copy_image = self.cp_image.copy()
+ row_count = len(self.distance)
+ self.tableWidget.setRowCount(row_count)
+ self.tableWidget.setColumnCount(3)
+ self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
+ self.tableWidget.setHorizontalHeaderLabels(['Number', 'Distance', 'Azimuth'])
+
+ for upper_left, lower_right in zip(self.left_range, self.right_range):
+ result = target_info.minrgb(upper_left, lower_right, copy_image)
+ min_x.append(result[0])
+ min_y.append(result[1])
+
+ self.r_list.append(copy_image[result[1], result[0], 0])
+ self.g_list.append(copy_image[result[1], result[0], 1])
+ self.b_list.append(copy_image[result[1], result[0], 2])
+
+ for i in range(0, row_count):
+ # crop_image = copy_image[min_y[i] - 50: min_y[i] + 50, min_x[i] - 50: min_x[i] + 50, :].copy()
+ # item = self.getImageLabel(crop_image)
+ # self.tableWidget.setCellWidget(i, 0, item)
+
+ item2 = QTableWidgetItem(f'target {i + 1}')
+ item2.setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter)
+ item2.setForeground(QBrush(QColor(255, 255, 255)))
+ self.tableWidget.setItem(i, 0, item2)
+
+ item3 = QTableWidgetItem(f'{self.distance[i]} km')
+ item3.setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter)
+ item3.setForeground(QBrush(QColor(255, 255, 255)))
+ self.tableWidget.setItem(i, 1, item3)
+
+ item4 = QTableWidgetItem(f'{self.azimuth[i]}')
+ item4.setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter)
+ item4.setForeground(QBrush(QColor(255, 255, 255)))
+ self.tableWidget.setItem(i, 2, item4)
+
+ def tableWidget_doubleClicked(self, event):
+ self.select_target = self.tableWidget.currentIndex().row()
+ self.update()
+
+ def getImageLabel(self, image):
+ imageLabel = QLabel()
+ imageLabel.setScaledContents(True)
+ height, width, channel = image.shape
+ bytesPerLine = channel * width
+
+ qImage = QImage(image.data.tobytes(), 100, 100, bytesPerLine, QImage.Format_RGB888)
+ imageLabel.setPixmap(QPixmap.fromImage(qImage))
+
+ return imageLabel
+
+ def func(self, x, c1, c2, a):
+ return c2 + (c1 - c2) * np.exp(-a * x)
+
+ def chart_update(self):
+
+ if self.chart_view is None:
+ self.chart_view = self.chart_draw()
+
+ if self.value_verticalLayout.count() == 0:
+ self.chart_view = self.chart_draw()
+ self.value_verticalLayout.addWidget(self.chart_view)
+ else:
+ new_chart_view = self.chart_draw()
+ self.value_verticalLayout.removeWidget(self.chart_view)
+ self.value_verticalLayout.addWidget(new_chart_view)
+ self.value_verticalLayout.update()
+ self.chart_view = new_chart_view
+
+ def chart_draw(self):
+ """세팅창 그래프 칸에 소산계수 차트를 그리는 함수"""
+
+ try:
+ self.x = np.linspace(self.distance[0], self.distance[-1], 100, endpoint=True)
+ self.x.sort()
+
+ hanhwa_opt_r, hanhwa_cov_r = curve_fit(self.func, self.distance, self.r_list, maxfev=5000)
+ hanhwa_opt_g, hanhwa_cov_g = curve_fit(self.func, self.distance, self.g_list, maxfev=5000)
+ hanhwa_opt_b, hanhwa_cov_b = curve_fit(self.func, self.distance, self.b_list, maxfev=5000)
+
+ # chart object
+ chart = QChart()
+ font = QFont()
+ font.setPixelSize(20)
+ font.setBold(3)
+ # palette = QPalette()
+ # palette.setColor(QPalette.Window, QColor('red'))
+ chart.setTitleFont(font)
+ # chart.setPalette(palette)
+ chart.setTitle('Extinction coefficient Graph')
+ chart.setAnimationOptions(QChart.SeriesAnimations)
+ chart.setBackgroundBrush(QBrush(QColor(255, 255, 255)))
+
+ axis_x = QValueAxis()
+ axis_x.setTickCount(7)
+ axis_x.setLabelFormat('%i')
+ axis_x.setTitleText('Distance(km)')
+ axis_x.setRange(0, 6)
+ chart.addAxis(axis_x, Qt.AlignBottom)
+
+ axis_y = QValueAxis()
+ axis_y.setTickCount(7)
+ axis_y.setLabelFormat('%i')
+ axis_y.setTitleText('Intensity')
+ axis_y.setRange(0, 255)
+ chart.addAxis(axis_y, Qt.AlignLeft)
+
+ # Red Graph
+ if self.red_checkBox.isChecked():
+ series1 = QLineSeries()
+ series1.setName('Red')
+ pen = QPen()
+ pen.setWidth(2)
+ series1.setPen(pen)
+ series1.setColor(QColor('Red'))
+
+ for dis in self.x:
+ series1.append(*(dis, self.func(dis, *hanhwa_opt_r)))
+ chart.addSeries(series1) # data feeding
+ series1.attachAxis(axis_x)
+ series1.attachAxis(axis_y)
+
+ # Green Graph
+ if self.green_checkBox.isChecked():
+ series2 = QLineSeries()
+ series2.setName('Green')
+ pen = QPen()
+ pen.setWidth(2)
+ series2.setPen(pen)
+ series2.setColor(QColor('Green'))
+ for dis in self.x:
+ series2.append(*(dis, self.func(dis, *hanhwa_opt_g)))
+ chart.addSeries(series2) # data feeding
+
+ series2.attachAxis(axis_x)
+ series2.attachAxis(axis_y)
+
+ # Blue Graph
+ if self.blue_checkBox.isChecked():
+ series3 = QLineSeries()
+ series3.setName('Blue')
+ pen = QPen()
+ pen.setWidth(2)
+ series3.setPen(pen)
+ series3.setColor(QColor('Blue'))
+ for dis in self.x:
+ series3.append(*(dis, self.func(dis, *hanhwa_opt_b)))
+ chart.addSeries(series3) # data feeding
+
+ series3.attachAxis(axis_x)
+ series3.attachAxis(axis_y)
+
+ chart.legend().setAlignment(Qt.AlignRight)
+
+ # displaying chart
+ chart.setBackgroundBrush(QBrush(QColor(22, 32, 42)))
+ chart_view = QChartView(chart)
+ chart_view.setRenderHint(QPainter.Antialiasing)
+ chart_view.setMaximumSize(800, 500)
+
+ return chart_view
+
+ except TypeError as e:
+ QMessageBox.about(self, 'Error', f'{e}')
+ pass
+
+ def camera_flip(self):
+ if self.cam_flag:
+ self.cam_flag = False
+ else:
+ self.cam_flag = True
+ self.image_load()
+
+ def btn_on(self, e):
+ self.flip_button.setIcon(QIcon('resources/flip_on.png'))
+
+ def btn_off(self, e):
+ self.flip_button.setIcon(QIcon('resources/flip_off.png'))
+
+ def image_load(self):
+ self.left_range = None
+ self.right_range = None
+
+ if self.cam_flag: # cam_flag is True = PNM_9031RV_rear
+ src = JS08Settings.get('rear_camera_rtsp')
+ self.current_camera = JS08Settings.get('rear_camera_name')
+ self.target_setting_label.setText(f' Rear Target Setting ({self.current_camera})')
+ self.get_target(self.current_camera)
+
+ else: # cam_flag is False = PNM_9031RV_front
+ src = JS08Settings.get('front_camera_rtsp')
+ self.current_camera = JS08Settings.get('front_camera_name')
+ self.target_setting_label.setText(f' Front Target Setting ({self.current_camera})')
+ self.get_target(self.current_camera)
+
+ try:
+ # print(f'Current camera - {self.current_camera.replace("_", " ")}')
+
+ # os.makedirs(f'{JS08Settings.get("target_csv_path")}/{self.current_camera}', exist_ok=True)
+ cap = cv2.VideoCapture(src)
+ ret, cv_img = cap.read()
+ cp_image = cv_img.copy()
+ cap.release()
+
+ except Exception as e:
+ QMessageBox.about(self, 'Error', f'{e}')
+
+ self.image_label.setPixmap(self.convert_cv_qt(cp_image))
+ self.show_target_table()
+ self.chart_update()
+
+ def convert_cv_qt(self, cv_img):
+ """Convert CV image to QImage."""
+ cv_img = cv_img.copy()
+ cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
+
+ self.cp_image = cv_img.copy()
+
+ self.video_height, self.video_width, ch = cv_img.shape
+
+ bytes_per_line = ch * self.video_width
+ convert_to_Qt_format = QImage(cv_img.data, self.video_width, self.video_height,
+ bytes_per_line, QImage.Format_RGB888)
+ p = convert_to_Qt_format.scaled(self.image_label.width(),
+ self.image_label.height(),
+ Qt.KeepAspectRatio, Qt.SmoothTransformation)
+
+ return QPixmap.fromImage(p)
+
+ def str_to_tuple(self, before_list):
+ """저장된 타겟들의 위치정보인 튜플 리스트가 문자열로 바뀌어 다시 튜플형태로 변환하는 함수"""
+ tuple_list = [i.split(',') for i in before_list]
+ tuple_list = [(int(i[0][1:]), int(i[1][:-1])) for i in tuple_list]
+ return tuple_list
+
+ # 타겟 조정 및 썸네일 관련 함수 시작
+ def thumbnail_pos(self, end_pos):
+ x = int((end_pos.x() / self.image_label.width()) * self.video_width)
+ y = int((end_pos.y() / self.image_label.height()) * self.video_height)
+ return x, y
+
+ def thumbnail(self, image):
+ height, width, channel = image.shape
+ bytesPerLine = channel * width
+ qImg = QImage(image.data.tobytes(), width, height, bytesPerLine, QImage.Format_RGB888)
+ return qImg
+
+ def lbl_paintEvent(self, event):
+ painter = QPainter(self.image_label)
+
+ back_ground_image = self.thumbnail(self.cp_image)
+ bk_image = QPixmap.fromImage(back_ground_image)
+ painter.drawPixmap(QRect(0, 0, self.image_label.width(),
+ self.image_label.height()), bk_image)
+
+ painter.setPen(QPen(Qt.white, 1, Qt.DotLine))
+
+ painter.drawLine((self.image_label.width() * 0.125), 0,
+ (self.image_label.width() * 0.125), self.image_label.height())
+ painter.drawLine((self.image_label.width() * 0.375), 0,
+ (self.image_label.width() * 0.375), self.image_label.height())
+ painter.drawLine((self.image_label.width() * 0.625), 0,
+ (self.image_label.width() * 0.625), self.image_label.height())
+ painter.drawLine((self.image_label.width() * 0.875), 0,
+ (self.image_label.width() * 0.875), self.image_label.height())
+
+ if self.cam_flag:
+ if time.strftime('%Y%m%d', time.localtime(time.time())):
+ painter.setPen(QPen(Qt.black, 1, Qt.DotLine))
+ painter.drawText(self.image_label.width() * 0.0625, 20, 'E')
+ painter.drawText(self.image_label.width() * 0.25, 20, 'SE')
+ painter.drawText(self.image_label.width() * 0.5, 20, 'S')
+ painter.drawText(self.image_label.width() * 0.75, 20, 'SW')
+ painter.drawText(self.image_label.width() * 0.9375, 20, 'W')
+ painter.setPen(QPen(Qt.white, 1, Qt.DotLine))
+ elif self.cam_flag is False:
+ painter.drawText(self.image_label.width() * 0.0625, 20, 'W')
+ painter.drawText(self.image_label.width() * 0.25, 20, 'NW')
+ painter.drawText(self.image_label.width() * 0.5, 20, 'N')
+ painter.drawText(self.image_label.width() * 0.75, 20, 'NE')
+ painter.drawText(self.image_label.width() * 0.9375, 20, 'E')
+
+ if self.left_range and self.right_range:
+ for name, corner1, corner2, in zip(self.target_name, self.left_range, self.right_range):
+ br = QBrush(QColor(100, 10, 10, 40))
+ painter.setBrush(br)
+ painter.setPen(QPen(Qt.red, 2, Qt.SolidLine))
+ corner1_1 = int(corner1[0] / self.video_width * self.image_label.width())
+ corner1_2 = int(corner1[1] / self.video_height * self.image_label.height())
+ corner2_1 = int((corner2[0] - corner1[0]) / self.video_width * self.image_label.width())
+ corner2_2 = int((corner2[1] - corner1[1]) / self.video_height * self.image_label.height())
+ painter.drawRect(QRect(corner1_1, corner1_2, corner2_1, corner2_2))
+ painter.drawText(corner1_1 + corner2_1, corner1_2 - 5, f'{name[7:]}')
+
+ # print(f'self.select_target: {self.select_target}')
+
+ if self.isDrawing:
+ br = QBrush(QColor(100, 10, 10, 40))
+ painter.setBrush(br)
+ painter.setPen(QPen(Qt.red, 2, Qt.SolidLine))
+ painter.drawRect(QRect(self.begin, self.end))
+ # th_x, th_y = self.thumbnail_pos(self.end)
+ # th_qImage = self.thumbnail(self.cp_image[th_y - 50:th_y + 50, th_x - 50:th_x + 50, :])
+ # thumbnail_image = QPixmap.fromImage(th_qImage)
+ # painter.drawPixmap(QRect(self.end.x(), self.end.y(), 200, 200), thumbnail_image)
+
+ if self.end_drawing:
+ painter.eraseRect(QRect(self.begin, self.end))
+ painter.eraseRect(QRect(self.end.x(), self.end.y(), 200, 200))
+ self.end_drawing = False
+ self.isDrawing = False
+ painter.end()
+
+ def lbl_mousePressEvent(self, event):
+ """마우스 클릭시 발생하는 이벤트, QLabel method overriding"""
+
+ # 좌 클릭시 실행
+ if event.buttons() == Qt.LeftButton:
+ self.isDrawing = True
+ self.begin = event.pos()
+ self.end = event.pos()
+ self.upper_left = (int((self.begin.x() / self.image_label.width()) * self.video_width),
+ int((self.begin.y() / self.image_label.height()) * self.video_height))
+ self.image_label.update()
+
+ self.draw_flag = True
+
+ # 우 클릭시 실행
+ elif event.buttons() == Qt.RightButton:
+ self.isDrawing = False
+
+ text, ok = QInputDialog.getText(self, 'Delete target',
+ 'Input target number to delete')
+ if ok:
+ if text == '':
+ del self.target_name[-1]
+ del self.left_range[-1]
+ del self.right_range[-1]
+ del self.distance[-1]
+ del self.azimuth[-1]
+
+ else:
+ if len(self.left_range) > 0:
+ text = int(text)
+ del self.target_name[text - 1]
+ del self.left_range[text - 1]
+ del self.right_range[text - 1]
+ del self.distance[text - 1]
+ del self.azimuth[text - 1]
+
+ self.update()
+ self.image_label.update()
+ self.draw_flag = False
+
+ def lbl_mouseMoveEvent(self, event):
+ """마우스가 움직일 때 발생하는 이벤트, QLabel method overriding"""
+ if event.buttons() == Qt.LeftButton:
+ self.end = event.pos()
+ self.image_label.update()
+ self.isDrawing = True
+
+ def lbl_mouseReleaseEvent(self, event):
+ """마우스 클릭이 떼질 때 발생하는 이벤트, QLabel method overriding"""
+ if self.draw_flag:
+ if self.cam_flag:
+ if 0 < self.upper_left[0] <= self.video_width * 0.125:
+ self.azimuth.append('E')
+ elif self.video_width * 0.125 < self.upper_left[0] <= self.video_width * 0.375:
+ self.azimuth.append('SE')
+ elif self.video_width * 0.375 < self.upper_left[0] <= self.video_width * 0.625:
+ self.azimuth.append('S')
+ elif self.video_width * 0.625 < self.upper_left[0] <= self.video_width * 0.875:
+ self.azimuth.append('SW')
+ elif self.video_width * 0.875 < self.upper_left[0] <= self.video_width:
+ self.azimuth.append('W')
+
+ elif self.cam_flag is False:
+ if 0 < self.upper_left[0] <= self.video_width * 0.125:
+ self.azimuth.append('W')
+ elif self.video_width * 0.125 < self.upper_left[0] <= self.video_width * 0.375:
+ self.azimuth.append('NW')
+ elif self.video_width * 0.375 < self.upper_left[0] <= self.video_width * 0.625:
+ self.azimuth.append('N')
+ elif self.video_width * 0.625 < self.upper_left[0] <= self.video_width * 0.875:
+ self.azimuth.append('NE')
+ elif self.video_width * 0.875 < self.upper_left[0] <= self.video_width:
+ self.azimuth.append('E')
+
+ self.end = event.pos()
+ self.image_label.update()
+ self.lower_right = (int((self.end.x() / self.image_label.width()) * self.video_width),
+ int((self.end.y() / self.image_label.height()) * self.video_height))
+
+ text, ok = QInputDialog.getText(self, '거리 입력', '거리(km)')
+
+ if ok:
+ self.left_range.append(self.upper_left)
+ self.right_range.append(self.lower_right)
+ self.distance.append(text)
+ self.target_name.append('target_' + str(len(self.left_range)))
+
+ # self.save_target(self.current_camera)
+ self.isDrawing = False
+ self.end_drawing = True
+ else:
+ self.isDrawing = False
+ del self.azimuth[-1]
+
+ self.image_label.update()
+
+ self.show_target_table()
+
+ def data_csv_path(self):
+ fName = QFileDialog.getExistingDirectory(
+ self, 'Select path to save data csv file', JS08Settings.get('data_csv_path'))
+ if fName:
+ self.data_csv_path_textBrowser.setPlainText(fName)
+ else:
+ pass
+
+ def target_csv_path(self):
+ fName = QFileDialog.getExistingDirectory(
+ self, 'Select path to save target csv file', JS08Settings.get('target_csv_path'))
+ if fName:
+ self.target_csv_path_textBrowser.setPlainText(fName)
+ else:
+ pass
+
+ def image_save_path(self):
+ fName = QFileDialog.getExistingDirectory(
+ self, 'Select path to save image file', JS08Settings.get('image_save_path'))
+ if fName:
+ self.image_save_path_textBrowser.setPlainText(fName)
+ else:
+ pass
+
+ def afd_btn_click(self):
+ dlg = FileAutoDelete()
+ dlg.show()
+ dlg.exec_()
+
+ def save_vis(self):
+
+ save_path_front = f'{JS08Settings.get("data_csv_path")}/{JS08Settings.get("front_camera_name")}/' \
+ f'{JS08Settings.get("front_camera_name")}.csv'
+
+ print(save_path_front)
+
+ col = ['datetime', 'camera_direction',
+ 'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW',
+ 'prevailing_visibility']
+ result = pd.DataFrame(col)
+ print(result)
+
+ # result['datetime'] =
+ # result['camera_direction'] =
+ # result['N'] =
+ # result['NE'] =
+ # result['E'] =
+ # result['SE'] =
+ # result['S'] =
+ # result['SW'] =
+ # result['W'] =
+ # result['NW'] =
+ # result['prevailing_visibility'] =
+
+ result.to_csv(f'{JS08Settings.get("data_csv_path")}/{self.current_camera}/{self.current_camera}.csv',
+ index=False)
+
+ def save_target(self, camera: str):
+
+ file = f'{JS08Settings.get("target_csv_path")}/{camera}/{camera}.csv'
+ if self.left_range and os.path.isfile(file):
+ col = ['target_name', 'left_range', 'right_range', 'distance', 'azimuth']
+ result = pd.DataFrame(columns=col)
+ result['target_name'] = self.target_name
+ result['left_range'] = self.left_range
+ result['right_range'] = self.right_range
+ result['distance'] = self.distance
+ result['azimuth'] = self.azimuth
+ result.to_csv(file, mode='w', index=False)
+ print(f'[{camera}.csv SAVED]')
+
+ def get_target(self, camera: str):
+
+ save_path = os.path.join(f'{JS08Settings.get("target_csv_path")}/{camera}')
+ file = f'{save_path}/{camera}.csv'
+
+ if os.path.isfile(f'{save_path}/{camera}.csv') is False:
+ os.makedirs(f'{save_path}', exist_ok=True)
+ makeFile = pd.DataFrame(columns=['target_name', 'left_range', 'right_range', 'distance', 'azimuth'])
+ makeFile.to_csv(file, mode='w', index=False)
+
+ target_df = pd.read_csv(f'{save_path}/{camera}.csv')
+ self.target_name = target_df['target_name'].tolist()
+ self.left_range = self.str_to_tuple(target_df['left_range'].tolist())
+ self.right_range = self.str_to_tuple(target_df['right_range'].tolist())
+ self.distance = target_df['distance'].tolist()
+ self.azimuth = target_df['azimuth'].tolist()
+
+ def accept_click(self):
+
+ JS08Settings.set('data_csv_path', self.data_csv_path_textBrowser.toPlainText())
+ JS08Settings.set('target_csv_path', self.target_csv_path_textBrowser.toPlainText())
+ JS08Settings.set('image_save_path', self.image_save_path_textBrowser.toPlainText())
+ JS08Settings.set('image_size', self.image_size_comboBox.currentIndex())
+ JS08Settings.set('visibility_alert_limit', self.vis_limit_spinBox.value())
+ JS08Settings.set('login_id', self.id_lineEdit.text())
+ JS08Settings.set('login_pw', self.pw_lineEdit.text())
+
+ self.save_target(self.current_camera)
+ self.close()
+
+ def reject_click(self):
+ self.close()
+
+
+if __name__ == '__main__':
+ import sys
+
+ app = QApplication(sys.argv)
+ ui = JS08SettingWidget()
+ ui.show()
+ sys.exit(app.exec_())
diff --git a/src/login_view.py b/src/login_view.py
new file mode 100644
index 0000000..1de4647
--- /dev/null
+++ b/src/login_view.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python3
+#
+# Copyright 2021-2022 Sijung Co., Ltd.
+#
+# Authors:
+# cotjdals5450@gmail.com (Seong Min Chae)
+# 5jx2oh@gmail.com (Jongjin Oh)
+
+import os
+import sys
+import time
+
+from PyQt5.QtWidgets import QDialog
+from PyQt5.QtCore import Qt
+from PyQt5 import uic
+
+from model import JS08Settings
+
+
+class LoginWindow(QDialog):
+
+ def __init__(self):
+ super().__init__()
+
+ ui_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
+ 'resources/login_window.ui')
+ uic.loadUi(ui_path, self)
+ self.setWindowFlag(Qt.WindowCloseButtonHint, False)
+ self.setWindowFlag(Qt.WindowContextHelpButtonHint, False)
+ self.show()
+
+ self.login_button.clicked.connect(self.login_click)
+ self.login_button.setShortcut('Return')
+
+ self.id = JS08Settings.get('login_id')
+ self.pw = JS08Settings.get('login_pw')
+
+ self.flag = 0
+
+ def login_click(self):
+ if self.id_lineEdit.text() == self.id and self.pw_lineEdit.text() == self.pw:
+ self.close()
+ else:
+ self.alert_label.setText('ID or P/W is not correct')
+ self.flag = self.flag + 1
+ if self.flag >= 5:
+ self.alert_label.setText('P/W = 1 + 2 + 3 + 4')
+
+ def keyPressEvent(self, event):
+ if event.key() == Qt.Key_Escape:
+ pass
+
+
+if __name__ == '__main__':
+ from PyQt5.QtWidgets import QApplication
+
+ app = QApplication(sys.argv)
+ window = LoginWindow()
+ sys.exit(app.exec_())
diff --git a/src/logo.ico b/src/logo.ico
new file mode 100644
index 0000000..da0d3d5
Binary files /dev/null and b/src/logo.ico differ
diff --git a/src/model.py b/src/model.py
index 4889d3c..ae61472 100644
--- a/src/model.py
+++ b/src/model.py
@@ -7,13 +7,20 @@
# 5jx2oh@gmail.com (Jongjin Oh)
import os
-from PyQt5.QtCore import QSettings, QStandardPaths
+from PyQt5.QtCore import (QSettings, QRect)
+from PyQt5.QtGui import (QImage)
-class JS06Settings:
- settings = QSettings('sijung', 'js06')
+class JS08Settings:
+ settings = QSettings('sijung', 'js08')
defaults = {
+ 'front_camera_name': 'PNM_9031RV_front',
+ 'front_camera_rtsp': 'rtsp://admin:sijung5520@192.168.100.131/profile2/media.smp',
+ 'front_main': 'rtsp://admin:sijung5520@192.168.100.131/profile5/media.smp',
+ 'rear_camera_name': 'PNM_9031RV_rear',
+ 'rear_camera_rtsp': 'rtsp://admin:sijung5520@192.168.100.132/profile2/media.smp',
+ 'rear_main': 'rtsp://admin:sijung5520@192.168.100.132/profile5/media.smp',
'data_csv_path': os.path.join('D:\\JS06', 'data'),
'target_csv_path': os.path.join('D:\\JS06', 'target'),
'image_save_path': os.path.join('D:\\JS06', 'image'),
@@ -39,3 +46,18 @@ def get(cls, key):
def restore_defaults(cls):
for key, value in cls.defaults.items():
cls.set(key, value)
+
+
+class JS06SimpleTarget:
+
+ def __init__(self,
+ label: str, wedge: str, azimuth: float,
+ distance: float, roi: QRect, mask: QImage,
+ input_width: int, input_height: int):
+ super().__init__()
+ self.label = label
+ self.wedge = wedge
+ self.azimuth = azimuth
+ self.distance = distance
+ self.roi = roi
+
diff --git a/src/nd01.py b/src/nd01.py
deleted file mode 100644
index 5bd57c5..0000000
--- a/src/nd01.py
+++ /dev/null
@@ -1,512 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2021-2022 Sijung Co., Ltd.
-#
-# Authors:
-# cotjdals5450@gmail.com (Seong Min Chae)
-# 5jx2oh@gmail.com (Jongjin Oh)
-
-
-import sys
-import os
-import time
-
-import vlc
-import numpy as np
-import pyqtgraph as pg
-import multiprocessing as mp
-from multiprocessing import Process, Queue
-
-from PyQt5.QtGui import (QPixmap, QIcon, QPainter, QColor)
-from PyQt5.QtWidgets import (QMainWindow, QWidget, QGraphicsScene,
- QFrame, QVBoxLayout)
-from PyQt5.QtCore import (Qt, pyqtSlot, pyqtSignal, QRect,
- QTimer, QObject, QThread)
-from PyQt5.QtChart import (QChartView, QLegend, QLineSeries,
- QPolarChart, QScatterSeries, QValueAxis)
-from PyQt5 import uic
-
-from video_thread_mp import producer, VideoThread
-from nd01_settings import ND01SettingWidget
-from model import JS06Settings
-from save_db import main
-
-
-def clock(queue):
- """Real-time clock
- Current time to be expressed on JS-06
-
- :param queue: MultiProcessing Queue
- """
- while True:
- now = str(time.time())
- queue.put(now)
- time.sleep(1)
-
-
-class Consumer(QThread):
- poped = pyqtSignal(str)
-
- def __init__(self, q):
- super().__init__()
- self.q = q
- self.running = True
-
- def run(self):
- while self.running:
- if not self.q.empty():
- data = q.get()
- self.poped.emit(data)
-
- def pause(self):
- self.running = False
-
- def resume(self):
- self.running = True
-
-
-class TimeAxisItem(pg.AxisItem):
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.setLabel(text='Time (sec)', units=None)
- self.enableAutoSIPrefix(False)
-
- def tickStrings(self, values, scale, spacing):
- """
- override 하여, tick 옆에 써지는 문자를 원하는대로 수정함.
- values --> x축 값들
- 숫자로 이루어진 Iterable data(하나씩 차례로 반환 가능한 object -> ex) List[int]) list, str, tuple 등등
- """
- return [time.strftime("%H:%M:%S", time.localtime(local_time)) for local_time in values]
-
-
-class PlotWidget(QWidget):
-
- def __init__(self, parent=None):
- QWidget.__init__(self, parent)
-
- self.pw = pg.PlotWidget(
- labels={'left': 'Visibility (km)'},
- axisItems={'bottom': TimeAxisItem(orientation='bottom')}
- )
-
- self.pw.showGrid(x=True, y=True)
- self.pdi = self.pw.plot(pen='w') # PlotDataItem obj 반환.
-
- self.p1 = self.pw.plotItem
-
- self.p2 = pg.ViewBox()
- self.p1.showAxis('right')
- self.p1.scene().addItem(self.p2)
- self.p1.getAxis('right').linkToView(self.p2)
- self.p2.setXLink(self.p1)
- self.p1.getAxis('right').setLabel('Axis 2', color='#ffff00')
-
- self.p2.setGeometry(self.p1.vb.sceneBoundingRect())
- # self.p2.addItem(pg.PlotCurveItem([10, 20, 40, 80, 400, 2000], pen='y'))
- # self.pdi.sigClicked.connect(self.onclick)
-
- self.plotData = {'x': [], 'y': []}
- self.pre_plotData = {'x': [], 'y': []}
-
- def update_plot(self, new_time_data: int):
- self.plotData['x'].append(new_time_data)
- self.plotData['y'].append(np.random.randint(10000, 15000))
-
- # 항상 x축 시간을 설정한 범위 ( -3 시간 전 ~ 10 분 후 )만 보여줌.
- # self.pw.setXRange(new_time_data - 3600 * 3, new_time_data + 600, padding=0)
- # self.pw.setYRange(-1, 21, padding=0)
-
- data = []
- for i in self.plotData['y']:
- i = i / 1000
- data.append(i)
- self.pdi.setData(self.plotData['x'], data)
-
- # self.pdi.setData([1643873584, 1643873585, 1643873586, 1643873587, 1643873588],
- # [12, 11, 10, 14, 13])
-
- def onclick(self, plot, points):
- for point in points:
- print(point.pos())
-
-
-class PolarWidget(QWidget):
-
- def __init__(self, parent=None):
- QWidget.__init__(self, parent)
-
- self.pw = pg.plot(
- labels={'left': 'Visibility (km)'},
- axisItems={'bottom': TimeAxisItem(orientation='bottom')}
- )
-
- self.pw.showGrid(x=True, y=True)
- self.pdi = self.pw.plot(pen='w')
-
- self.pw.addLine(x=0, pen=0.2)
- self.pw.addLine(y=0, pen=0.2)
- for r in range(2, 20, 2):
- circle = pg.QtGui.QGraphicsEllipseItem(-r, -r, r * 2, r * 2)
- circle.setPen(pg.mkPen(0.2))
- self.pw.addItem(circle)
-
- theta = np.linspace(0, 2 * np.pi, 8)
- radius = np.random.normal(loc=10, size=8)
-
- x = radius * np.cos(theta)
- y = radius * np.sin(theta)
- self.pw.plot(x, y)
-
-
-class ThumbnailView(QMainWindow):
-
- def __init__(self, image_file_name: str, date: int):
- super().__init__()
-
- ui_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
- "ui/thumbnail_view.ui")
- uic.loadUi(ui_path, self)
-
- self.front_image.setPixmap(QPixmap(f'D:/ND-01/vista/{date}/{image_file_name}.png')
- .scaled(self.front_image.width(), self.front_image.height()))
- self.rear_image.setPixmap(QPixmap(f'D:/ND-01/vista/{date}/{image_file_name}.png')
- .scaled(self.rear_image.width(), self.rear_image.height()))
-
-
-class ND01MainWindow(QMainWindow):
-
- def __init__(self, q):
- super().__init__()
-
- ui_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
- "resources/main_window.ui")
- uic.loadUi(ui_path, self)
- self.showFullScreen()
- self._plot = PlotWidget()
- self._polar = PolarWidget()
- self.view = None
- self.km_mile_convert = False
- self.date = None
-
- self.front_video_widget = VideoWidget(self)
- self.front_video_widget.on_camera_change("rtsp://admin:sijung5520@192.168.100.101/profile2/media.smp")
-
- self.rear_video_widget = VideoWidget(self)
- self.rear_video_widget.on_camera_change("rtsp://admin:sijung5520@192.168.100.100/profile2/media.smp")
-
- self.video_horizontalLayout.addWidget(self.front_video_widget)
- self.video_horizontalLayout.addWidget(self.rear_video_widget)
-
- self.scene = QGraphicsScene()
- self.vis_plot.setScene(self.scene)
- self.plotWidget = self._plot.pw
- self.plotWidget.resize(600, 400)
- self.scene.addWidget(self.plotWidget)
-
- self.scene_polar = QGraphicsScene()
- self.polar_plot.setScene(self.scene_polar)
- self.polarWidget = self._polar.pw
- self.polarWidget.resize(600, 400)
- self.scene_polar.addWidget(self.polarWidget)
-
- self.setting_button.enterEvent = self.btn_on
- self.setting_button.leaveEvent = self.btn_off
-
- self.consumer = Consumer(q)
- self.consumer.poped.connect(self.clock)
- self.consumer.start()
-
- self.click_style = 'border: 1px solid red;'
-
- self.alert.clicked.connect(self.alert_test)
-
- self.c_vis_label.mousePressEvent = self.unit_convert
- self.p_vis_label.mousePressEvent = self.unit_convert
-
- self.label_1hour.mouseDoubleClickEvent = self.thumbnail_click1
- self.label_2hour.mouseDoubleClickEvent = self.thumbnail_click2
- self.label_3hour.mouseDoubleClickEvent = self.thumbnail_click3
- self.label_4hour.mouseDoubleClickEvent = self.thumbnail_click4
- self.label_5hour.mouseDoubleClickEvent = self.thumbnail_click5
- self.label_6hour.mouseDoubleClickEvent = self.thumbnail_click6
-
- self.setting_button.clicked.connect(self.setting_btn_click)
-
- self.show()
-
- def alert_test(self):
- self.alert.setIcon(QIcon('resources/asset/red.png'))
-
- def reset_StyleSheet(self):
- self.label_1hour.setStyleSheet('')
- self.label_2hour.setStyleSheet('')
- self.label_3hour.setStyleSheet('')
- self.label_4hour.setStyleSheet('')
- self.label_5hour.setStyleSheet('')
- self.label_6hour.setStyleSheet('')
-
- def thumbnail_view(self, file_name: str):
- self.view = ThumbnailView(file_name, self.date)
- self.view.setGeometry(QRect(self.video_horizontalLayout.geometry().x(),
- self.video_horizontalLayout.geometry().y() + 21,
- self.video_horizontalLayout.geometry().width(),
- self.video_horizontalLayout.geometry().height()))
- self.view.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)
- self.view.setWindowModality(Qt.ApplicationModal)
- self.view.show()
-
- def thumbnail_click1(self, e):
- name = self.label_1hour_time.text()[:2] + self.label_1hour_time.text()[3:]
- epoch = time.strftime("%Y%m%d", time.localtime(time.time()))
- self.thumbnail_view(epoch + name + "00")
-
- self.reset_StyleSheet()
- self.label_1hour.setStyleSheet(self.click_style)
- self.monitoring_label.setText(f' {self.label_1hour_time.text()} image')
-
- QTimer.singleShot(5000, self.thumbnail_show)
-
- def thumbnail_click2(self, e):
- name = self.label_2hour_time.text()[:2] + self.label_2hour_time.text()[3:]
- epoch = time.strftime("%Y%m%d", time.localtime(time.time()))
- self.thumbnail_view(epoch + name + "00")
-
- self.reset_StyleSheet()
- self.label_2hour.setStyleSheet(self.click_style)
- self.monitoring_label.setText(f' {self.label_2hour_time.text()} image')
-
- QTimer.singleShot(5000, self.thumbnail_show)
-
- def thumbnail_click3(self, e):
- name = self.label_3hour_time.text()[:2] + self.label_3hour_time.text()[3:]
- epoch = time.strftime("%Y%m%d", time.localtime(time.time()))
- self.thumbnail_view(epoch + name + "00")
-
- self.reset_StyleSheet()
- self.label_3hour.setStyleSheet(self.click_style)
- self.monitoring_label.setText(f' {self.label_3hour_time.text()} image')
-
- QTimer.singleShot(5000, self.thumbnail_show)
-
- def thumbnail_click4(self, e):
- name = self.label_4hour_time.text()[:2] + self.label_4hour_time.text()[3:]
- epoch = time.strftime("%Y%m%d", time.localtime(time.time()))
- self.thumbnail_view(epoch + name + "00")
-
- self.reset_StyleSheet()
- self.label_4hour.setStyleSheet(self.click_style)
- self.monitoring_label.setText(f' {self.label_4hour_time.text()} image')
-
- QTimer.singleShot(5000, self.thumbnail_show)
-
- def thumbnail_click5(self, e):
- name = self.label_5hour_time.text()[:2] + self.label_5hour_time.text()[3:]
- epoch = time.strftime("%Y%m%d", time.localtime(time.time()))
- self.thumbnail_view(epoch + name + "00")
-
- self.reset_StyleSheet()
- self.label_5hour.setStyleSheet(self.click_style)
- self.monitoring_label.setText(f' {self.label_5hour_time.text()} image')
-
- QTimer.singleShot(5000, self.thumbnail_show)
-
- def thumbnail_click6(self, e):
- name = self.label_6hour_time.text()[:2] + self.label_6hour_time.text()[3:]
- epoch = time.strftime("%Y%m%d", time.localtime(time.time()))
- self.thumbnail_view(epoch + name + "00")
-
- self.reset_StyleSheet()
- self.label_6hour.setStyleSheet(self.click_style)
- self.monitoring_label.setText(f' {self.label_6hour_time.text()} image')
-
- QTimer.singleShot(5000, self.thumbnail_show)
-
- def thumbnail_show(self):
- self.monitoring_label.setText(' Monitoring')
- self.reset_StyleSheet()
- self.view.close()
-
- @pyqtSlot()
- def setting_btn_click(self):
- self.front_video_widget.media_player.stop()
- self.rear_video_widget.media_player.stop()
- self.consumer.pause()
-
- dlg = ND01SettingWidget()
- dlg.show()
- dlg.setWindowModality(Qt.ApplicationModal)
- dlg.exec_()
-
- self.front_video_widget.media_player.play()
- self.rear_video_widget.media_player.play()
- self.consumer.resume()
- self.consumer.start()
-
- def btn_on(self, event):
- self.setting_button.setIcon(QIcon('resources/asset/settings_on.png'))
-
- def btn_off(self, event):
- self.setting_button.setIcon(QIcon('resources/asset/settings.png'))
-
- def unit_convert(self, event):
- if self.km_mile_convert:
- self.km_mile_convert = False
- elif self.km_mile_convert is False:
- self.km_mile_convert = True
-
- @pyqtSlot(str)
- def clock(self, data):
- current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(float(data)))
- self.date = current_time[2:4] + current_time[5:7]
- self.real_time_label.setText(current_time)
- self._plot.update_plot(int(float(data)))
-
- result = 0
- for i in self._plot.plotData['y']:
- result += i
- p_vis_km = f'{format(round(int(result / len(self._plot.plotData["y"])), 2), ",")}'
- p_vis_nm = f'{format(round(int(result / len(self._plot.plotData["y"])) / 1609, 2), ",")}'
-
- if self.km_mile_convert:
- self.c_vis_label.setText(f'{format(round(self._plot.plotData["y"][-1] / 1609, 2), ",")} mile')
- self.p_vis_label.setText(f'{p_vis_nm} mile')
-
- elif self.km_mile_convert is False:
- self.c_vis_label.setText(f'{format(self._plot.plotData["y"][-1], ",")} m')
- self.p_vis_label.setText(f'{p_vis_km} m')
-
- data_time = self._plot.plotData['x']
- if int(float(data)) - 3600 * 3 in self._plot.plotData['x']:
- index = data_time.index(int(float(data)) - 3600 * 3)
- self._plot.plotData['x'].pop(index)
- self._plot.plotData['y'].pop(index)
-
- self.thumbnail_refresh()
- if current_time[-2:] == "00":
- self.thumbnail_refresh()
-
- if int(p_vis_km.replace(',', '')) <= JS06Settings.get('visibility_alert_limit'):
- self.alert.setIcon(QIcon('resources/asset/red.png'))
-
- def thumbnail_refresh(self):
- one_hour_ago = time.strftime('%Y%m%d%H%M00', time.localtime(time.time() - 3600))
- two_hour_ago = time.strftime('%Y%m%d%H%M00', time.localtime(time.time() - 3600 * 2))
- three_hour_ago = time.strftime('%Y%m%d%H%M00', time.localtime(time.time() - 3600 * 3))
- four_hour_ago = time.strftime('%Y%m%d%H%M00', time.localtime(time.time() - 3600 * 4))
- five_hour_ago = time.strftime('%Y%m%d%H%M00', time.localtime(time.time() - 3600 * 5))
- six_hour_ago = time.strftime('%Y%m%d%H%M00', time.localtime(time.time() - 3600 * 6))
-
- self.label_1hour_time.setText(time.strftime('%H:%M', time.localtime(time.time() - 3600)))
- self.label_2hour_time.setText(time.strftime('%H:%M', time.localtime(time.time() - 3600 * 2)))
- self.label_3hour_time.setText(time.strftime('%H:%M', time.localtime(time.time() - 3600 * 3)))
- self.label_4hour_time.setText(time.strftime('%H:%M', time.localtime(time.time() - 3600 * 4)))
- self.label_5hour_time.setText(time.strftime('%H:%M', time.localtime(time.time() - 3600 * 5)))
- self.label_6hour_time.setText(time.strftime('%H:%M', time.localtime(time.time() - 3600 * 6)))
-
- self.label_1hour.setPixmap(
- QPixmap(f'{JS06Settings.get("image_save_path")}/resize/{self.date}/{one_hour_ago}.jpg'))
- self.label_2hour.setPixmap(
- QPixmap(f'{JS06Settings.get("image_save_path")}/resize/{self.date}/{two_hour_ago}.jpg'))
- self.label_3hour.setPixmap(
- QPixmap(f'{JS06Settings.get("image_save_path")}/resize/{self.date}/{three_hour_ago}.jpg'))
- self.label_4hour.setPixmap(
- QPixmap(f'{JS06Settings.get("image_save_path")}/resize/{self.date}/{four_hour_ago}.jpg'))
- self.label_5hour.setPixmap(
- QPixmap(f'{JS06Settings.get("image_save_path")}/resize/{self.date}/{five_hour_ago}.jpg'))
- self.label_6hour.setPixmap(
- QPixmap(f'{JS06Settings.get("image_save_path")}/resize/{self.date}/{six_hour_ago}.jpg'))
-
- def keyPressEvent(self, e):
- """Override function QMainwindow KeyPressEvent that works when key is pressed"""
- if e.key() == Qt.Key_F:
- self.showFullScreen()
- if e.key() == Qt.Key_D:
- self.showNormal()
-
-
-class VideoWidget(QWidget):
- """Video stream player using QVideoWidget"""
- video_frame = None
-
- def __init__(self, parent: QObject = None):
- super().__init__(parent)
-
- args = [
- "--rtsp-frame-buffer-size",
- "1000000"
- ]
-
- self.instance = vlc.Instance(args)
- self.instance.log_unset()
- self.media_player = self.instance.media_player_new()
-
- self.image_player = self.instance.media_list_player_new()
- self.image_media = self.instance.media_list_new('')
-
- self.video_frame = QFrame()
-
- if sys.platform == 'win32':
- self.media_player.set_hwnd(self.video_frame.winId())
-
- layout = QVBoxLayout(self)
- layout.addWidget(self.video_frame)
-
- @pyqtSlot(str)
- def on_camera_change(self, uri: str):
- # uri = "rtsp://admin:sijung5520@192.168.100.100/profile2/media.smp"
- if uri[:4] == "rtsp":
- self.media_player.set_media(self.instance.media_new(uri))
- self.media_player.play()
- else:
- pass
-
-
-class MainCtrl(QObject):
- front_camera_changed = pyqtSignal(str)
- rear_camera_changed = pyqtSignal(str)
-
- def __init__(self):
- super().__init__()
-
- self.front_target_prepared = False
- self.rear_target_prepared = False
-
- self.front_camera_changed.connect(self.decompose_front_targets)
- self.rear_camera_changed.connect(self.decompose_rear_targets)
-
- @pyqtSlot(str)
- def decompose_front_targets(self, _: str):
- self.front_target_prepared = False
- self.decompose_targets('front')
- self.front_target_prepared = True
-
-
-if __name__ == '__main__':
-
- from PyQt5.QtWidgets import QApplication
-
- mp.freeze_support()
- q = Queue()
- _q = Queue()
-
- _producer = producer
-
- p = Process(name='clock', target=clock, args=(q, ), daemon=True)
- _p = Process(name="producer", target=_producer, args=(_q, ), daemon=True)
-
- p.start()
- _p.start()
-
- os.makedirs('D:/ND-01/vista', exist_ok=True)
- os.makedirs('D:/ND-01/resize', exist_ok=True)
-
- app = QApplication(sys.argv)
- window = ND01MainWindow(q)
- sys.exit(app.exec_())
-
- # MainWindow = QMainWindow()
- # ui = ND01MainWindow()
- # ui.show()
- # sys.exit(app.exec_())
diff --git a/src/nd01_settings.py b/src/nd01_settings.py
deleted file mode 100644
index 9d8e2b7..0000000
--- a/src/nd01_settings.py
+++ /dev/null
@@ -1,350 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2021-2022 Sijung Co., Ltd.
-#
-# Authors:
-# cotjdals5450@gmail.com (Seong Min Chae)
-# 5jx2oh@gmail.com (Jongjin Oh)
-
-
-import os
-
-import cv2
-import pandas as pd
-from PyQt5 import uic
-from PyQt5.QtCore import (QPoint, QRect, Qt)
-from PyQt5.QtGui import (QPixmap, QPainter, QBrush,
- QColor, QPen, QImage,
- QIcon)
-from PyQt5.QtWidgets import (QApplication, QLabel, QInputDialog,
- QDialog, QAbstractItemView, QVBoxLayout,
- QGridLayout, QPushButton, QMessageBox,
- QFileDialog)
-from model import JS06Settings
-
-
-class ND01SettingWidget(QDialog):
-
- def __init__(self, *args, **kwargs):
-
- super().__init__(*args, **kwargs)
- ui_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
- "resources/settings.ui")
- uic.loadUi(ui_path, self)
- # self.setWindowFlag(Qt.FramelessWindowHint)
-
- self.begin = QPoint()
- self.end = QPoint()
- self.upper_left = ()
- self.lower_right = ()
- self.left_range = []
- self.right_range = []
- self.distance = []
- self.target_name = []
- self.min_xy = ()
-
- self.isDrawing = False
- self.draw_flag = False
- self.cam_flag = False
-
- self.video_width = 0
- self.video_height = 0
-
- self.cp_image = None
- self.end_drawing = None
-
- self.current_camera = ""
-
- self.image_load()
-
- # 그림 그리는 삐뮤디 생성
- # self.blank_lbl = QLabel(self.image_label)
- # # self.blank_lbl.setGeometry(0, 0, 1200, 500)
- # self.blank_lbl.paintEvent = self.lbl_paintEvent
- #
- # self.blank_lbl.mousePressEvent = self.lbl_mousePressEvent
- # self.blank_lbl.mouseMoveEvent = self.lbl_mouseMoveEvent
- # self.blank_lbl.mouseReleaseEvent = self.lbl_mouseReleaseEvent
-
- self.flip_button.clicked.connect(self.camera_flip)
- self.flip_button.enterEvent = self.btn_on
- self.flip_button.leaveEvent = self.btn_off
-
- self.data_csv_path_button.clicked.connect(self.data_csv_path)
- self.target_csv_path_button.clicked.connect(self.target_csv_path)
- self.image_save_path_button.clicked.connect(self.image_save_path)
-
- self.data_csv_path_textBrowser.setPlainText(JS06Settings.get('data_csv_path'))
- self.target_csv_path_textBrowser.setPlainText(JS06Settings.get('target_csv_path'))
- self.image_save_path_textBrowser.setPlainText(JS06Settings.get('image_save_path'))
-
- self.vis_limit_spinBox.setValue(JS06Settings.get('visibility_alert_limit'))
- self.id_lineEdit.setText(JS06Settings.get('login_id'))
- self.pw_lineEdit.setText(JS06Settings.get('login_pw'))
-
- self.image_size_comboBox.setCurrentIndex(JS06Settings.get('image_size'))
- # self.image_size_comboBox.currentTextChanged.connect(self.image_size_changed)
-
- self.image_label.paintEvent = self.lbl_paintEvent
- self.image_label.mousePressEvent = self.lbl_mousePressEvent
- self.image_label.mouseMoveEvent = self.lbl_mouseMoveEvent
- self.image_label.mouseReleaseEvent = self.lbl_mouseReleaseEvent
-
- self.get_target()
-
- self.buttonBox.accepted.connect(self.accept_click)
- self.buttonBox.rejected.connect(self.reject)
-
- def camera_flip(self):
- if self.cam_flag:
- self.cam_flag = False
- else:
- self.cam_flag = True
- self.image_load()
-
- def btn_on(self, e):
- self.flip_button.setIcon(QIcon('resources/asset/flip_on.png'))
-
- def btn_off(self, e):
- self.flip_button.setIcon(QIcon('resources/asset/flip_off.png'))
-
- def image_load(self):
- # self.image_label.update()
-
- if self.cam_flag:
- src = "rtsp://admin:sijung5520@192.168.100.100/profile2/media.smp"
- self.target_setting_label.setText(' Rear Target Setting')
- self.current_camera = 'PNM_9030V'
- self.get_target()
-
- else:
- src = "rtsp://admin:sijung5520@192.168.100.101/profile2/media.smp"
- self.target_setting_label.setText(' Front Target Setting')
- self.current_camera = 'PNM_9022V'
- self.get_target()
-
- try:
- print(f'현재 카메라 {self.current_camera}')
-
- os.makedirs(f'{JS06Settings.get("target_csv_path")}/{self.current_camera}', exist_ok=True)
- cap = cv2.VideoCapture(src)
- ret, cv_img = cap.read()
- cp_image = cv_img.copy()
- cap.release()
- except Exception as e:
- QMessageBox.about(self, 'Error', f'{e}')
-
- self.image_label.setPixmap(self.convert_cv_qt(cp_image))
-
- def convert_cv_qt(self, cv_img):
- """Convert CV image to QImage."""
- cv_img = cv_img.copy()
- cv_img = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)
-
- self.cp_image = cv_img.copy()
-
- self.video_height, self.video_width, ch = cv_img.shape
-
- bytes_per_line = ch * self.video_width
- convert_to_Qt_format = QImage(cv_img.data, self.video_width, self.video_height,
- bytes_per_line, QImage.Format_RGB888)
- p = convert_to_Qt_format.scaled(self.image_label.width(),
- self.image_label.height(),
- Qt.KeepAspectRatio, Qt.SmoothTransformation)
-
- return QPixmap.fromImage(p)
-
- def lbl_paintEvent(self, event):
- painter = QPainter(self.image_label)
-
- back_ground_image = self.thumbnail(self.cp_image)
- bk_image = QPixmap.fromImage(back_ground_image)
- painter.drawPixmap(QRect(0, 0, self.image_label.width(),
- self.image_label.height()), bk_image)
-
- for corner1, corner2, in zip(self.left_range, self.right_range):
- br = QBrush(QColor(100, 10, 10, 40))
- painter.setBrush(br)
- painter.setPen(QPen(Qt.red, 2, Qt.SolidLine))
- corner1_1 = int(corner1[0] / self.video_width * self.image_label.width())
- corner1_2 = int(corner1[1] / self.video_height * self.image_label.height())
- corner2_1 = int((corner2[0] - corner1[0]) / self.video_width * self.image_label.width())
- corner2_2 = int((corner2[1] - corner1[1]) / self.video_height * self.image_label.height())
- painter.drawRect(QRect(corner1_1, corner1_2, corner2_1, corner2_2))
-
- if self.isDrawing:
- br = QBrush(QColor(100, 10, 10, 40))
- painter.setBrush(br)
- painter.setPen(QPen(Qt.red, 2, Qt.SolidLine))
- painter.drawRect(QRect(self.begin, self.end))
- th_x, th_y = self.thumbnail_pos(self.end)
- th_qImage = self.thumbnail(self.cp_image[th_y - 50:th_y + 50, th_x - 50:th_x + 50, :])
- thumbnail_image = QPixmap.fromImage(th_qImage)
- painter.drawPixmap(QRect(self.end.x(), self.end.y(), 200, 200), thumbnail_image)
-
- if self.end_drawing:
- painter.eraseRect(QRect(self.begin, self.end))
- painter.eraseRect(QRect(self.end.x(), self.end.y(), 200, 200))
- self.end_drawing = False
- self.isDrawing = False
- painter.end()
-
- def str_to_tuple(self, before_list):
- """저장된 타겟들의 위치정보인 튜플 리스트가 문자열로 바뀌어 다시 튜플형태로 변환하는 함수"""
- tuple_list = [i.split(',') for i in before_list]
- tuple_list = [(int(i[0][1:]), int(i[1][:-1])) for i in tuple_list]
- return tuple_list
-
- # 타겟 조정 및 썸네일 관련 함수 시작
- def thumbnail_pos(self, end_pos):
- x = int((end_pos.x() / self.image_label.width()) * self.video_width)
- y = int((end_pos.y() / self.image_label.height()) * self.video_height)
- return x, y
-
- def thumbnail(self, image):
- height, width, channel = image.shape
- bytesPerLine = channel * width
- qImg = QImage(image.data.tobytes(), width, height, bytesPerLine, QImage.Format_RGB888)
- return qImg
-
- def lbl_mousePressEvent(self, event):
- """마우스 클릭시 발생하는 이벤트, QLabel method overriding"""
-
- # 좌 클릭시 실행
- if event.buttons() == Qt.LeftButton:
- self.isDrawing = True
- self.begin = event.pos()
- self.end = event.pos()
- self.upper_left = (int((self.begin.x() / self.image_label.width()) * self.video_width),
- int((self.begin.y() / self.image_label.height()) * self.video_height))
- self.image_label.update()
-
- self.draw_flag = True
-
- # 우 클릭시 실행
- elif event.buttons() == Qt.RightButton:
- self.isDrawing = False
- if len(self.left_range) > 0:
- del self.distance[-1]
- del self.target_name[-1]
- del self.left_range[-1]
- del self.right_range[-1]
- self.save_target(self.current_camera)
- self.draw_flag = False
- self.image_label.update()
-
- def lbl_mouseMoveEvent(self, event):
- """마우스가 움직일 때 발생하는 이벤트, QLabel method overriding"""
- if event.buttons() == Qt.LeftButton:
- self.end = event.pos()
- self.image_label.update()
- self.isDrawing = True
-
- def lbl_mouseReleaseEvent(self, event):
- """마우스 클릭이 떼질 때 발생하는 이벤트, QLabel method overriding"""
- if self.draw_flag:
- self.end = event.pos()
- self.image_label.update()
- self.lower_right = (int((self.end.x() / self.image_label.width()) * self.video_width),
- int((self.end.y() / self.image_label.height()) * self.video_height))
- text, ok = QInputDialog.getText(self, '거리 입력', '거리(km)')
- if ok:
- self.left_range.append(self.upper_left)
- self.right_range.append(self.lower_right)
- self.distance.append(text)
- # self.min_xy = self.minrgb(self.upper_left, self.lower_right)
- self.target_name.append("target_" + str(len(self.left_range)))
- self.save_target(self.current_camera)
- self.isDrawing = False
- self.end_drawing = True
-
- print(f'{text} km')
- else:
- self.isDrawing = False
- self.image_label.update()
-
- def data_csv_path(self):
- fName = QFileDialog.getExistingDirectory(
- self, 'Select path to save data csv file', JS06Settings.get('data_csv_path'))
- if fName:
- self.data_csv_path_textBrowser.setPlainText(fName)
- else:
- pass
-
- def target_csv_path(self):
- fName = QFileDialog.getExistingDirectory(
- self, 'Select path to save target csv file', JS06Settings.get('target_csv_path'))
- if fName:
- self.target_csv_path_textBrowser.setPlainText(fName)
- else:
- pass
-
- def image_save_path(self):
- fName = QFileDialog.getExistingDirectory(
- self, 'Select path to save image file', JS06Settings.get('image_save_path'))
- if fName:
- self.image_save_path_textBrowser.setPlainText(fName)
- else:
- pass
-
- def save_vis(self):
-
- col = ['datetime', 'camera_direction',
- 'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW',
- 'prevailing_visibility']
- result = pd.DataFrame(col)
- print(result)
- # result['datetime'] =
- # result['camera_direction'] =
- # result['N'] =
- # result['NE'] =
- # result['E'] =
- # result['SE'] =
- # result['S'] =
- # result['SW'] =
- # result['W'] =
- # result['NW'] =
- # result['prevailing_visibility'] =
- # result.to_csv(f'{JS06Settings.get("data_csv_path")}/{self.current_camera}/{self.current_camera}.csv',
- # index=False)
-
- def save_target(self, camera: str):
-
- print(f'타겟을 저장합니다 - {camera}')
- if self.left_range:
- col = ['target_name', 'left_range', 'right_range', 'distance']
- result = pd.DataFrame(columns=col)
- result['target_name'] = self.target_name
- result['left_range'] = self.left_range
- result['right_range'] = self.right_range
- result['distance'] = self.distance
- result.to_csv(f'{JS06Settings.get("target_csv_path")}/{camera}/{camera}.csv',
- mode='w', index=False)
- print(f'{JS06Settings.get("target_csv_path")}/{camera}/{camera}.csv - SAVED!!!!')
-
- def get_target(self):
- print("타겟을 불러옵니다.")
-
- save_path = os.path.join(f'{JS06Settings.get("target_csv_path")}/{self.current_camera}')
- if os.path.isfile(f'{save_path}/{self.current_camera}.csv'):
- target_df = pd.read_csv(f'{save_path}/{self.current_camera}.csv')
- self.target_name = target_df["target_name"].tolist()
- self.left_range = self.str_to_tuple(target_df["left_range"].tolist())
- self.right_range = self.str_to_tuple(target_df["right_range"].tolist())
- self.distance = target_df["distance"].tolist()
- else:
- QMessageBox.about(self, 'Error', 'no file...')
-
- def accept_click(self):
- print('accept? yes accept~')
-
- # JS06Settings.set('data_csv_path', self.)
-
-
-if __name__ == '__main__':
- import sys
-
- app = QApplication(sys.argv)
- ui = ND01SettingWidget()
- ui.show()
- sys.exit(app.exec_())
diff --git a/src/resources/auto_file_delete.ui b/src/resources/auto_file_delete.ui
new file mode 100644
index 0000000..268f40c
--- /dev/null
+++ b/src/resources/auto_file_delete.ui
@@ -0,0 +1,111 @@
+
+
+ Form
+
+
+ Qt::WindowModal
+
+
+
+ 0
+ 0
+ 298
+ 282
+
+
+
+
+ KoPubWorld돋움체 Medium
+ 10
+ 50
+ false
+ false
+
+
+
+ ArrowCursor
+
+
+ File delete
+
+
+ This is this.
+
+
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ Noto Sans
+
+
+
+ Select a date and erase the data before that date
+
+
+ background-color: rgb(255, 255, 255);
+color: rgb(0, 0, 0);
+
+
+
+
+
+ Qt::Sunday
+
+
+ true
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ Noto Sans
+ 10
+ 50
+ false
+ false
+
+
+
+ PointingHandCursor
+
+
+ Exit this window
+
+
+
+
+
+ Close
+
+
+ Ctrl+W
+
+
+
+
+
+
+
+
+
+
diff --git a/src/resources/azimuth_off.png b/src/resources/azimuth_off.png
new file mode 100644
index 0000000..3088db3
Binary files /dev/null and b/src/resources/azimuth_off.png differ
diff --git a/src/resources/azimuth_on.png b/src/resources/azimuth_on.png
new file mode 100644
index 0000000..05f3f91
Binary files /dev/null and b/src/resources/azimuth_on.png differ
diff --git a/src/resources/asset/clock.png b/src/resources/clock.png
similarity index 100%
rename from src/resources/asset/clock.png
rename to src/resources/clock.png
diff --git a/src/resources/f_logo.png b/src/resources/f_logo.png
new file mode 100644
index 0000000..369a90e
Binary files /dev/null and b/src/resources/f_logo.png differ
diff --git a/src/resources/asset/flip_off.png b/src/resources/flip_off.png
similarity index 100%
rename from src/resources/asset/flip_off.png
rename to src/resources/flip_off.png
diff --git a/src/resources/asset/flip_on.png b/src/resources/flip_on.png
similarity index 100%
rename from src/resources/asset/flip_on.png
rename to src/resources/flip_on.png
diff --git a/src/resources/asset/graph.png b/src/resources/graph.png
similarity index 100%
rename from src/resources/asset/graph.png
rename to src/resources/graph.png
diff --git a/src/resources/graph_range_window.ui b/src/resources/graph_range_window.ui
new file mode 100644
index 0000000..060988d
--- /dev/null
+++ b/src/resources/graph_range_window.ui
@@ -0,0 +1,80 @@
+
+
+ Dialog
+
+
+
+ 0
+ 0
+ 260
+ 139
+
+
+
+ Dialog
+
+
+
+
+ 50
+ 100
+ 156
+ 23
+
+
+
+
+ Noto Sans
+
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+ 20
+ 20
+ 121
+ 16
+
+
+
+
+ 0
+ 0
+
+
+
+
+ Noto Sans
+ 8
+
+
+
+ Graph Time Range
+
+
+
+
+
+ 20
+ 40
+ 221
+ 31
+
+
+
+
+ Noto Sans
+
+
+
+ ex) 24 = Visibility values for 24 hours
+
+
+
+
+
+
diff --git a/src/resources/asset/green.png b/src/resources/green.png
similarity index 100%
rename from src/resources/asset/green.png
rename to src/resources/green.png
diff --git a/src/resources/login_window.ui b/src/resources/login_window.ui
new file mode 100644
index 0000000..ed1a42c
--- /dev/null
+++ b/src/resources/login_window.ui
@@ -0,0 +1,138 @@
+
+
+ Dialog
+
+
+
+ 0
+ 0
+ 290
+ 300
+
+
+
+ Login
+
+
+ background-color:rgb(22,32,42);
+
+
+ -
+
+
+
+ Noto Sans
+
+
+
+ background-color:rgb(27,49,70);
+
+
+
-
+
+
+
+ Noto Sans
+
+
+
+ background-color: #ffffff;
+
+
+ ID
+
+
+
+ -
+
+
+
+
+
+
+
+
+ asset/f_logo.png
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+ Noto Sans
+ 10
+
+
+
+ color:#ff0000;
+
+
+ QFrame::Plain
+
+
+
+
+
+ Qt::AutoText
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ Noto Sans
+
+
+
+ background-color: #ffffff;
+
+
+ QLineEdit::PasswordEchoOnEdit
+
+
+ Password
+
+
+
+
+
+
+ -
+
+
+
+ Noto Sans
+ 75
+ true
+
+
+
+ background-color:rgb(27,49,70);color:#ffffff;
+
+
+ Login
+
+
+
+
+
+
+
+
diff --git a/src/resources/asset/logo.png b/src/resources/logo.png
similarity index 100%
rename from src/resources/asset/logo.png
rename to src/resources/logo.png
diff --git a/src/resources/main_window.ui b/src/resources/main_window.ui
index ca94d06..c062bd7 100644
--- a/src/resources/main_window.ui
+++ b/src/resources/main_window.ui
@@ -77,6 +77,9 @@
-
+
+ 0
+
0
@@ -208,7 +211,7 @@ background-color: #1b3146;
-
-
+
true
@@ -224,19 +227,21 @@ background-color: #1b3146;
55
+
+
+ Noto Sans
+
+
OpenHandCursor
border:0px;
-background-color: #1b3146;
+background-color: #1b3146;
+color: rgb(255, 255, 255);
-
-
-
-
- asset/settings.pngasset/settings.png
+ Azimuth
@@ -255,43 +260,23 @@ background-color: #1b3146;
-
-
- -
-
-
- 0
-
-
-
-
-
- -
-
-
- 6
-
-
-
-
-
- 0
-
-
-
-
-
- 0
- 0
-
+
+
+
+ 0
+ 0
+
-
+
- 16777215
- 131
+ 16
+ 55
- background-color: rgb(255, 255, 255);
+ border:0px;
+background-color: #1b3146;
@@ -299,172 +284,144 @@ background-color: #1b3146;
-
-
+
+
+ true
+
-
+
0
0
-
-
- Noto Sans
- 75
- true
-
-
-
- background-color:rgb(27,49,70);
-color:#ffffff;
-
-
-
-
-
- Qt::AlignCenter
-
-
-
-
-
- -
-
-
- 0
-
-
-
-
0
- 0
+ 55
-
-
- 16777215
- 131
-
+
+ OpenHandCursor
- background-color: rgb(255, 255, 255);
+ border:0px;
+background-color: #1b3146;
-
-
- -
-
-
-
- 0
- 0
-
+
+
+ settings.pngsettings.png
-
-
- Noto Sans
- 75
- true
-
+
+
+ 40
+ 40
+
-
- background-color:rgb(27,49,70);
-color:#ffffff;
+
+ true
-
-
+
+ true
-
- Qt::AlignCenter
+
+ true
-
-
+
0
-
-
-
-
-
- 0
- 0
-
-
-
-
- 16777215
- 131
-
-
-
- background-color: rgb(255, 255, 255);
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- Noto Sans
- 75
- true
-
-
-
- background-color:rgb(27,49,70);
-color:#ffffff;
-
-
-
-
-
- Qt::AlignCenter
-
-
-
+
+ 0
+
+
+ 0
+
+
+
+ -
+
+
+ 6
+
-
-
+
0
-
-
-
-
- 0
- 0
-
-
-
-
- 16777215
- 131
-
-
-
- background-color: rgb(255, 255, 255);
-
-
-
+
+
+ 0
-
+
-
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 131
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 131
+
+
+
+
+
+
+
+
+
+
+
+
+
-
@@ -477,6 +434,7 @@ color:#ffffff;
Noto Sans
+ 11
75
true
@@ -496,31 +454,74 @@ color:#ffffff;
-
-
+
0
-
-
-
-
- 0
- 0
-
-
-
-
- 16777215
- 131
-
-
-
- background-color: rgb(255, 255, 255);
-
-
-
+
+
+ 0
-
+
-
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 131
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 131
+
+
+
+
+
+
+
+
+
+
+
+
+
-
@@ -533,6 +534,7 @@ color:#ffffff;
Noto Sans
+ 11
75
true
@@ -552,31 +554,74 @@ color:#ffffff;
-
-
+
0
-
-
-
-
- 0
- 0
-
-
-
-
- 16777215
- 131
-
-
-
- background-color: rgb(255, 255, 255);
-
-
-
+
+
+ 0
-
+
-
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 131
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 131
+
+
+
+
+
+
+
+
+
+
+
+
+
-
@@ -589,6 +634,7 @@ color:#ffffff;
Noto Sans
+ 11
75
true
@@ -617,111 +663,182 @@ color:#ffffff;
-
-
+
QLayout::SetMinimumSize
-
-
-
- QLayout::SetMinimumSize
-
-
- 12
+
+
+ 6
-
-
+
0
-
-
-
-
- 0
- 0
-
-
-
-
- Noto Sans
- 23
-
+
+
+ 0
-
- background-color:rgb(27,49,70);
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ Noto Sans
+ 23
+
+
+
+ background-color:rgb(27,49,70);
color: #ffffff;
-
-
- Time series
-
-
+
+
+ Time series
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 42
+
+
+
+ border:0px;
+background-color: #1b3146;
+
+
+
+
+
+
+ graph.pnggraph.png
+
+
+
+ 32
+ 32
+
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+
+
-
-
-
-
- 0
- 0
-
-
-
-
- 0
- 42
-
-
-
- border:0px;
-background-color: #1b3146;
-
-
-
-
-
-
- resources/icon/graph.pngresources/icon/graph.png
-
-
-
- 32
- 32
-
-
-
- true
-
-
- true
-
-
- true
-
-
+
-
-
+
+
+ 0
+
+
+ QLayout::SetMinimumSize
+
+
+ 6
+
-
-
-
-
- 0
- 0
-
+
+
+ 0
-
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ Noto Sans
+ 23
+
+
+
+ background-color:rgb(27,49,70);
+color: #ffffff;
+
+
+ Discernment
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 42
+
+
+
+ border:0px;
+background-color: #1b3146;
+
+
+
+
+
+
+ polar.pngpolar.png
+
+
+
+ 35
+ 35
+
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+
+
-
-
-
-
- 0
- 0
-
-
-
+
@@ -786,7 +903,7 @@ background-color: #1b3146;
- resources/icon/clock.pngresources/icon/clock.png
+ clock.pngclock.png
@@ -877,7 +994,7 @@ background-color: #1b3146;
- resources/icon/vis.pngresources/icon/vis.png
+ vis.pngvis.png
@@ -904,7 +1021,7 @@ background-color: #1b3146;
- color:rgb(28,136,227);
+ color:#ffffff;
- km
@@ -934,8 +1051,7 @@ background-color: #1b3146;
- background-color:rgb(27,49,70);
-color: #ffffff;
+ color: rgb(69, 165, 255);
Prediction Visibility
@@ -943,7 +1059,7 @@ color: #ffffff;
-
-
+
0
@@ -957,15 +1073,14 @@ color: #ffffff;
- border:0px;
-background-color: #1b3146;
+ color: rgb(69, 165, 255);
- resources/icon/vis.pngresources/icon/vis.png
+ pre_vis_1.pngpre_vis_1.png
@@ -992,7 +1107,7 @@ background-color: #1b3146;
- color:#ffffff
+ color: rgb(69, 165, 255);
- km
diff --git a/src/resources/polar.png b/src/resources/polar.png
new file mode 100644
index 0000000..ef675fe
Binary files /dev/null and b/src/resources/polar.png differ
diff --git a/src/resources/pre_vis.png b/src/resources/pre_vis.png
new file mode 100644
index 0000000..502e033
Binary files /dev/null and b/src/resources/pre_vis.png differ
diff --git a/src/resources/pre_vis_1.png b/src/resources/pre_vis_1.png
new file mode 100644
index 0000000..c25686d
Binary files /dev/null and b/src/resources/pre_vis_1.png differ
diff --git a/src/resources/asset/red.png b/src/resources/red.png
similarity index 100%
rename from src/resources/asset/red.png
rename to src/resources/red.png
diff --git a/src/resources/settings.ui b/src/resources/setting_window.ui
similarity index 78%
rename from src/resources/settings.ui
rename to src/resources/setting_window.ui
index cd2102e..700fe31 100644
--- a/src/resources/settings.ui
+++ b/src/resources/setting_window.ui
@@ -6,8 +6,8 @@
0
0
- 1159
- 888
+ 971
+ 558
@@ -95,6 +95,9 @@ color: #ffffff;
15
+
+ PointingHandCursor
+
border:0px;
background-color: #1b3146;
@@ -105,7 +108,7 @@ color: #ffffff;
- asset/flip_off.pngasset/flip_off.png
+ flip_off.pngflip_off.png
@@ -177,19 +180,13 @@ color: #ffffff;
-
-
-
+
+
- 0
- 250
+ 700
+ 500
-
- background-color:rgb(25,39,52);
-
-
-
-
@@ -222,22 +219,6 @@ color: #ffffff;
- -
-
-
-
- 0
- 250
-
-
-
- background-color:rgb(25,39,52);
-
-
-
-
-
-
-
@@ -273,7 +254,7 @@ color: #ffffff;
-
-
+
0
0
@@ -285,7 +266,7 @@ color: #ffffff;
-
+ background-color:rgb(27,49,70);
color: #ffffff;
@@ -345,7 +326,7 @@ color: #ffffff;
-
-
+
0
0
@@ -357,7 +338,7 @@ color: #ffffff;
-
+ background-color:rgb(27,49,70);
color: #ffffff;
@@ -417,7 +398,7 @@ color: #ffffff;
-
-
+
0
0
@@ -429,7 +410,7 @@ color: #ffffff;
-
+ background-color:rgb(27,49,70);
color: #ffffff;
@@ -482,14 +463,107 @@ color: #ffffff;
-
-
+
0
+
+ QLayout::SetMaximumSize
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ Noto Sans
+ 10
+
+
+
+ background-color:rgb(27,49,70);
+color: #ffffff;
+
+
+ Graph setting:
+
+
+
+ -
+
+
+
+ Noto Sans
+ 50
+ false
+
+
+
+ color: rgb(255, 255, 255);
+
+
+ Red
+
+
+ true
+
+
+
+ -
+
+
+
+ Noto Sans
+ 50
+ false
+
+
+
+ color: rgb(255, 255, 255);
+
+
+ Green
+
+
+ true
+
+
+
+ -
+
+
+
+ Noto Sans
+ 50
+ false
+
+
+
+ color: rgb(255, 255, 255);
+
+
+ Blue
+
+
+ true
+
+
+
+
+
+ -
+
+
+ 6
+
-
-
+
0
0
@@ -501,7 +575,7 @@ color: #ffffff;
-
+ background-color:rgb(27,49,70);
color: #ffffff;
@@ -534,12 +608,12 @@ color: #ffffff;
-
- 0
+ 6
-
-
+
0
0
@@ -551,7 +625,7 @@ color: #ffffff;
-
+ background-color:rgb(27,49,70);
color: #ffffff;
@@ -592,12 +666,12 @@ color: #ffffff;
-
- 0
+ 6
-
-
+
0
0
@@ -609,7 +683,7 @@ color: #ffffff;
-
+ background-color:rgb(27,49,70);
color: #ffffff;
@@ -635,12 +709,12 @@ color: #ffffff;
-
- 0
+ 6
-
-
+
0
0
@@ -652,7 +726,7 @@ color: #ffffff;
-
+ background-color:rgb(27,49,70);
color: #ffffff;
@@ -676,55 +750,57 @@ color: #ffffff;
-
-
-
-
- Noto Sans
- 10
-
-
-
- background-color:rgb(27,49,70);
-color: #ffffff;
-
-
- Other QSetting 1
-
-
-
- -
-
-
-
- Noto Sans
- 10
-
+
+
+ 6
-
- background-color:rgb(27,49,70);
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ Noto Sans
+ 10
+
+
+
+ background-color:rgb(27,49,70);
color: #ffffff;
-
-
- Other QSetting 2
-
-
-
- -
-
-
-
- Noto Sans
- 10
-
-
-
- background-color:rgb(27,49,70);
+
+
+ File delete:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+ background-color:rgb(27,49,70);
color: #ffffff;
-
-
- Other QSetting 3
-
-
+
+
+ ↩
+
+
+
+
-
@@ -750,6 +826,9 @@ color: #ffffff;
QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok
+
+ false
+
diff --git a/src/resources/asset/settings.png b/src/resources/settings.png
similarity index 100%
rename from src/resources/asset/settings.png
rename to src/resources/settings.png
diff --git a/src/resources/asset/settings_on.png b/src/resources/settings_on.png
similarity index 100%
rename from src/resources/asset/settings_on.png
rename to src/resources/settings_on.png
diff --git a/src/resources/thumb.ui b/src/resources/thumb.ui
new file mode 100644
index 0000000..b43fb07
--- /dev/null
+++ b/src/resources/thumb.ui
@@ -0,0 +1,341 @@
+
+
+ MainWindow
+
+
+ true
+
+
+
+ 0
+ 0
+ 784
+ 366
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 400
+ 100
+
+
+
+
+ Noto Sans
+ 9
+ 50
+ false
+ false
+
+
+
+ false
+
+
+ JS-08
+
+
+ background-color:rgb(22,32,42);
+border-color: rgb(255, 255, 255);
+
+
+ Qt::ToolButtonIconOnly
+
+
+ QTabWidget::Rounded
+
+
+ true
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+ false
+
+
+
+
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ 2
+
+
+ QLayout::SetMinimumSize
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ Noto Sans
+ 15
+
+
+
+ background-color:rgb(27,49,70);
+color: rgb(255, 255, 255);
+
+
+ Front
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ Noto Sans
+ 15
+
+
+
+ background-color:rgb(27,49,70);
+color: rgb(255, 255, 255);
+
+
+ Rear
+
+
+ Qt::AlignCenter
+
+
+
+
+
+ -
+
+
+ 6
+
+
+ QLayout::SetMaximumSize
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 30
+
+
+
+
+
+
+ <html><head/><body><p><br/></p></body></html>
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 30
+
+
+
+
+
+
+ <html><head/><body><p><br/></p></body></html>
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
+
+
+
+
+
+ &Quit
+
+
+ Exit
+
+
+ Exit JS-06
+
+
+ Ctrl+W
+
+
+
+
+ sd
+
+
+
+
+ true
+
+
+ true
+
+
+ km
+
+
+
+
+ true
+
+
+ true
+
+
+ mi
+
+
+
+
+ true
+
+
+ false
+
+
+ Inference
+
+
+ I
+
+
+
+
+ false
+
+
+ Edit &Target
+
+
+
+
+ true
+
+
+ Edit &Camera Info
+
+
+
+
+ About
+
+
+
+
+ Con&figuration
+
+
+
+
+
+
+
+
+ actionExit
+ triggered()
+ MainWindow
+ close()
+
+
+ -1
+ -1
+
+
+ 187
+ 228
+
+
+
+
+
diff --git a/src/resources/thumbnail_view.ui b/src/resources/thumbnail_view.ui
index f8c1849..fa8ac0b 100644
--- a/src/resources/thumbnail_view.ui
+++ b/src/resources/thumbnail_view.ui
@@ -85,27 +85,27 @@ border-color: rgb(255, 255, 255);
-
- 0
+ 2
- 5
+ 0
- 5
+ 2
- 5
+ 0
- 5
+ 0
-
- 6
+ 2
- QLayout::SetMinimumSize
+ QLayout::SetDefaultConstraint
-
@@ -118,7 +118,9 @@ border-color: rgb(255, 255, 255);
Noto Sans
- 15
+ 17
+ 50
+ false
@@ -144,7 +146,9 @@ color: rgb(255, 255, 255);
Noto Sans
- 15
+ 17
+ 50
+ false
@@ -164,32 +168,27 @@ color: rgb(255, 255, 255);
-
- 6
+ 2
-
-
+
0
0
-
-
- 952
- 362
-
-
- 30
+ Noto Sans
+ 20
color: rgb(255, 255, 255);
- <html><head/><body><p><br/></p></body></html>
+ No file
Qt::AlignCenter
@@ -199,27 +198,22 @@ color: rgb(255, 255, 255);
-
-
+
0
0
-
-
- 952
- 362
-
-
- 30
+ Noto Sans
+ 20
color: rgb(255, 255, 255);
- <html><head/><body><p><br/></p></body></html>
+ No file
Qt::AlignCenter
@@ -315,7 +309,7 @@ color: rgb(255, 255, 255);
-
+
diff --git a/src/resources/asset/vis.png b/src/resources/vis.png
similarity index 100%
rename from src/resources/asset/vis.png
rename to src/resources/vis.png
diff --git a/src/target_info.py b/src/target_info.py
new file mode 100644
index 0000000..ce95a80
--- /dev/null
+++ b/src/target_info.py
@@ -0,0 +1,204 @@
+#!/usr/bin/env python3
+import os
+import pandas as pd
+import numpy as np
+
+import cal_ext_coef
+from model import JS08Settings
+
+
+def minprint(epoch, left_range, right_range, distance, cv_img, camera):
+ """A function that outputs pixels for calculating the dissipation coefficient in the specified areas"""
+
+ cp_image = cv_img.copy()
+ min_x = []
+ min_y = []
+
+ for upper_left, lower_right in zip(left_range, right_range):
+ result = minrgb(upper_left, lower_right, cp_image)
+ min_x.append(result[0])
+ min_y.append(result[1])
+
+ visibility = get_rgb(epoch, min_x, min_y, cp_image, distance, camera)
+
+ # print(f'minprint visibility: {visibility}')
+ return visibility
+
+
+def minrgb(upper_left, lower_right, cp_image):
+ """Extracts the minimum RGB value of the dragged area"""
+
+ up_y = min(upper_left[1], lower_right[1])
+ down_y = max(upper_left[1], lower_right[1])
+
+ left_x = min(upper_left[0], lower_right[0])
+ right_x = max(upper_left[0], lower_right[0])
+
+ target = cp_image[up_y:down_y, left_x:right_x, :]
+
+ r = target[:, :, 0]
+ g = target[:, :, 1]
+ b = target[:, :, 2]
+
+ r = np.clip(r, 0, 765)
+ sum_rgb = r + g + b
+
+ t_idx = np.where(sum_rgb == np.min(sum_rgb))
+
+ show_min_y = t_idx[0][0] + up_y
+ show_min_x = t_idx[1][0] + left_x
+
+ return show_min_x, show_min_y
+
+
+def get_rgb(epoch: str, min_x, min_y, cp_image, distance, camera):
+ """Gets the RGB values of the coordinates."""
+
+ r_list = []
+ g_list = []
+ b_list = []
+
+ for x, y in zip(min_x, min_y):
+ r_list.append(cp_image[y, x, 0])
+ g_list.append(cp_image[y, x, 1])
+ b_list.append(cp_image[y, x, 2])
+
+ visibility = save_rgb(r_list, g_list, b_list, epoch, distance, camera)
+
+ # print(f'get_rgb visibility: {visibility}')
+ return visibility
+
+
+def save_rgb(r_list, g_list, b_list, epoch, distance, camera):
+ """Save the rgb information for each target."""
+
+ save_path = os.path.join(f'rgb/{camera}')
+ os.makedirs(save_path, exist_ok=True)
+
+ try:
+ if r_list:
+ r_list = list(map(int, r_list))
+ g_list = list(map(int, g_list))
+ b_list = list(map(int, b_list))
+
+ col = ['target_name', 'r', 'g', 'b', 'distance']
+ result = pd.DataFrame(columns=col)
+ result['target_name'] = [f'target_{num}' for num in range(1, len(r_list) + 1)]
+ result['r'] = r_list
+ result['g'] = g_list
+ result['b'] = b_list
+ result['distance'] = distance
+ result.to_csv(f'{save_path}/{epoch}.csv', mode='w', index=False)
+ list1, list2, list3, select_color = cal_ext_coef.cal_curve(result)
+
+ # visibility = extinc_print(list1, list2, list3, select_color)
+ visibility = extinc_print(list3, select_color)
+
+ # print(f'save_rgb visibility: {visibility}')
+ return visibility
+
+ except TypeError:
+ pass
+
+
+def extinc_print(alp_list: list, select_color: str = ""):
+ """Select an appropriate value among visibility by wavelength."""
+ visibility = 0
+
+ if select_color == 'red':
+ visibility = visibility_print(alp_list[0])
+ elif select_color == 'green':
+ visibility = visibility_print(alp_list[1])
+ elif select_color == 'blue':
+ visibility = visibility_print(alp_list[2])
+
+ # print(f'extinc_print visibility: {visibility}')
+ return visibility
+
+
+def visibility_print(ext_g: float = 0.0):
+ """Print the visibility"""
+
+ vis_value = (3.912 / ext_g)
+ if vis_value > 20:
+ vis_value = 20
+ elif vis_value <= 0.01:
+ vis_value = 0.01
+
+ vis_value_str = f'{vis_value:.3f}'
+
+ return vis_value_str
+
+
+def get_target(camera_name: str):
+ """Retrieves target information of a specific camera."""
+
+ save_path = JS08Settings.get('target_csv_path')
+
+ if os.path.isfile(f'{save_path}/{camera_name}/{camera_name}.csv'):
+ target_df = pd.read_csv(f'{save_path}/{camera_name}/{camera_name}.csv')
+ target_name = target_df['target_name'].tolist()
+ left_range = str_to_tuple(target_df['left_range'].tolist())
+ right_range = str_to_tuple(target_df['right_range'].tolist())
+ distance = target_df['distance'].tolist()
+ azimuth = target_df['azimuth'].tolist()
+
+ return target_name, left_range, right_range, distance, azimuth
+
+ else:
+ return [], [], [], [], []
+
+
+def get_target_from_azimuth(camera_name: str, azimuth: str):
+ """Retrieves target information from azimuth of a specific camera"""
+
+ global target_name, left_range, right_range, distance
+ save_path = JS08Settings.get('target_csv_path')
+
+ if os.path.isfile(f'{save_path}/{camera_name}/{camera_name}.csv'):
+ target_df = pd.read_csv(f'{save_path}/{camera_name}/{camera_name}.csv')
+ azi_target = target_df.loc[(target_df['azimuth'] == f'{azimuth}'), :]
+
+ target_name = azi_target['target_name'].tolist()
+ left_range = str_to_tuple(azi_target['left_range'].tolist())
+ right_range = str_to_tuple(azi_target['right_range'].tolist())
+ distance = azi_target['distance'].tolist()
+
+ return target_name, left_range, right_range, distance, azimuth
+
+ else:
+
+
+ return [], [], [], [], []
+
+ # if select_data == 'target_name':
+ # return target_name
+ #
+ # elif select_data == 'left_range':
+ # return left_range
+ #
+ # elif select_data == 'right_range':
+ # return right_range
+ #
+ # elif select_data == 'distance':
+ # return distance
+
+
+def str_to_tuple(before_list):
+ """A function that converts the tuple list, which is the location information of the stored targets,
+ into a string and converts it back into a tuple form."""
+ tuple_list = [i.split(',') for i in before_list]
+ tuple_list = [(int(i[0][1:]), int(i[1][:-1])) for i in tuple_list]
+ return tuple_list
+
+
+if __name__ == '__main__':
+
+ front_target_name_W, front_left_range_W, front_right_range_W, front_distance_W, front_azimuth_W = \
+ target_info.get_target_from_azimuth(front_cap_name, 'W')
+
+ print(front_target_name_W)
+ print(front_left_range_W)
+ print(front_right_range_W)
+ print(front_distance_W)
+ print(front_azimuth_W)
diff --git a/src/test.png b/src/test.png
new file mode 100644
index 0000000..883cdae
Binary files /dev/null and b/src/test.png differ
diff --git a/src/video_thread_mp.py b/src/video_thread_mp.py
index b58d47b..95f1557 100644
--- a/src/video_thread_mp.py
+++ b/src/video_thread_mp.py
@@ -1,224 +1,157 @@
-# !/usr/bin/env python3
+#!/usr/bin/env python3
+#
+# Copyright 2021-2022 Sijung Co., Ltd.
+#
+# Authors:
+# cotjdals5450@gmail.com (Seong Min Chae)
+# 5jx2oh@gmail.com (Jongjin Oh)
+
import os
+
import cv2
import time
-import numpy as np
-import pandas as pd
-import multiprocessing as mp
-from multiprocessing import Process, Queue
-from PyQt5.QtCore import QThread, pyqtSignal, QObject
-import curve_save
-from model import JS06Settings
+from model import JS08Settings
+import target_info
def producer(q):
- # proc = mp.current_process()
- # print(f'{proc.name} multiprocessing start.')
-
- cap = cv2.VideoCapture("rtsp://admin:sijung5520@192.168.100.100/profile2/media.smp")
- while True:
- epoch = time.strftime("%Y%m%d%H%M%S", time.localtime(time.time()))
- date = epoch[2:6]
-
- if epoch[-2:] == "00":
- try:
- image_save_path = JS06Settings.get('image_save_path')
- os.makedirs(f'{image_save_path}/vista/{date}', exist_ok=True)
- os.makedirs(f'{image_save_path}/resize/{date}', exist_ok=True)
-
- _, frame = cap.read()
- cv2.imwrite(f'{image_save_path}/vista/{date}/{epoch}.png', frame)
- cv2.imwrite(f'{image_save_path}/resize/{date}/{epoch}.jpg', cv2.resize(frame, (315, 131)))
- cv2.destroyAllWindows()
-
- # left_range, right_range, distance = get_target("PNM_9030V")
- # visibility = minprint(epoch[:-2], left_range, right_range, distance, frame)
- #
- # q.put(visibility)
- time.sleep(1)
- except Exception as e:
- print(e)
- cap.release()
- cap = cv2.VideoCapture("rtsp://admin:sijung5520@192.168.100.100/profile2/media.smp")
- continue
-
-
-def minprint(epoch, left_range, right_range, distance, cv_img):
- """A function that outputs pixels for calculating the dissipation coefficient in the specified areas"""
- print("minprint 시작")
- # epoch = time.strftime("%Y%m%d%H%M", time.localtime(time.time()))
- cp_image = cv_img.copy()
- result = ()
- cnt = 1
- min_x = []
- min_y = []
-
- for upper_left, lower_right in zip(left_range, right_range):
- result = minrgb(upper_left, lower_right, cp_image)
- min_x.append(result[0])
- min_y.append(result[1])
- cnt += 1
-
- visibility = get_rgb(epoch, min_x, min_y, cp_image, distance)
- return visibility
-
-
-def minrgb(upper_left, lower_right, cp_image):
- """Extracts the minimum RGB value of the dragged area"""
-
- up_y = min(upper_left[1], lower_right[1])
- down_y = max(upper_left[1], lower_right[1])
-
- left_x = min(upper_left[0], lower_right[0])
- right_x = max(upper_left[0], lower_right[0])
-
- test = cp_image[up_y:down_y, left_x:right_x, :]
-
- r = test[:, :, 0]
- g = test[:, :, 1]
- b = test[:, :, 2]
-
- r = np.clip(r, 0, 765)
- sum_rgb = r + g + b
-
- t_idx = np.where(sum_rgb == np.min(sum_rgb))
+ front_cap_name = 'PNM_9031RV_front'
+ rear_cap_name = 'PNM_9031RV_rear'
+
+ front_cap = cv2.VideoCapture(JS08Settings.get('front_camera_rtsp'))
+ rear_cap = cv2.VideoCapture(JS08Settings.get('rear_camera_rtsp'))
+
+ if rear_cap.isOpened() and front_cap.isOpened():
+ while True:
+ epoch = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
+ date = epoch[2:8]
+
+ if epoch[-2:] == '00':
+ front_target_name, front_left_range, front_right_range, front_distance, front_azimuth = \
+ target_info.get_target(front_cap_name)
+
+ rear_target_name, rear_left_range, rear_right_range, rear_distance, rear_azimuth = \
+ target_info.get_target(rear_cap_name)
+
+ front_target_name_W, front_left_range_W, front_right_range_W, front_distance_W, front_azimuth_W = \
+ target_info.get_target_from_azimuth(front_cap_name, 'W')
+
+ front_target_name_NW, front_left_range_NW, front_right_range_NW, front_distance_NW, front_azimuth_NW = \
+ target_info.get_target_from_azimuth(front_cap_name, 'NW')
+
+ front_target_name_N, front_left_range_N, front_right_range_N, front_distance_N, front_azimuth_N = \
+ target_info.get_target_from_azimuth(front_cap_name, 'N')
+
+ front_target_name_NE, front_left_range_NE, front_right_range_NE, front_distance_NE, front_azimuth_NE = \
+ target_info.get_target_from_azimuth(front_cap_name, 'NE')
+
+ front_target_name_E, front_left_range_E, front_right_range_E, front_distance_E, front_azimuth_E = \
+ target_info.get_target_from_azimuth(front_cap_name, 'E')
+
+ rear_target_name_E, rear_left_range_E, rear_right_range_E, rear_distance_E, rear_azimuth_E = \
+ target_info.get_target_from_azimuth(rear_cap_name, 'E')
+
+ rear_target_name_SE, rear_left_range_SE, rear_right_range_SE, rear_distance_SE, rear_azimuth_SE = \
+ target_info.get_target_from_azimuth(rear_cap_name, 'SE')
+
+ rear_target_name_S, rear_left_range_S, rear_right_range_S, rear_distance_S, rear_azimuth_S = \
+ target_info.get_target_from_azimuth(rear_cap_name, 'S')
+
+ rear_target_name_SW, rear_left_range_SW, rear_right_range_SW, rear_distance_SW, rear_azimuth_SW = \
+ target_info.get_target_from_azimuth(rear_cap_name, 'SW')
+
+ rear_target_name_W, rear_left_range_W, rear_right_range_W, rear_distance_W, rear_azimuth_W = \
+ target_info.get_target_from_azimuth(rear_cap_name, 'W')
+
+ if len(front_left_range_W) < 4 and len(rear_left_range_W) < 4:
+ continue
+ else:
+ pass
+
+ image_save_path = JS08Settings.get('image_save_path')
+ os.makedirs(f'{image_save_path}/vista/{front_cap_name}/{date}', exist_ok=True)
+ os.makedirs(f'{image_save_path}/vista/{rear_cap_name}/{date}', exist_ok=True)
+ os.makedirs(f'{image_save_path}/resize/{front_cap_name}/{date}', exist_ok=True)
+ os.makedirs(f'{image_save_path}/resize/{rear_cap_name}/{date}', exist_ok=True)
+
+ front_ret, front_frame = front_cap.read()
+ rear_ret, rear_frame = rear_cap.read()
+
+ if not front_ret or not rear_ret:
+ print('Found Error; Rebuilding stream')
+
+ front_cap.release()
+ rear_cap.release()
+ front_cap = cv2.VideoCapture(JS08Settings.get('front_camera_rtsp'))
+ rear_cap = cv2.VideoCapture(JS08Settings.get('rear_camera_rtsp'))
+ front_ret, front_frame = front_cap.read()
+ rear_ret, rear_frame = rear_cap.read()
+
+ visibility_front = target_info.minprint(epoch[:-2], front_left_range, front_right_range,
+ front_distance, front_frame, front_cap_name)
+ visibility_rear = target_info.minprint(epoch[:-2], rear_left_range, rear_right_range,
+ rear_distance, rear_frame, rear_cap_name)
+
+ visibility_front_W = target_info.minprint(epoch[:-2], front_left_range_W, front_right_range_W,
+ front_distance_W, front_frame, front_cap_name)
+ visibility_front_NW = target_info.minprint(epoch[:-2], front_left_range_NW, front_right_range_NW,
+ front_distance_NW, front_frame, front_cap_name)
+ visibility_front_N = target_info.minprint(epoch[:-2], front_left_range_N, front_right_range_N,
+ front_distance_N, front_frame, front_cap_name)
+ visibility_front_NE = target_info.minprint(epoch[:-2], front_left_range_NE, front_right_range_NE,
+ front_distance_NE, front_frame, front_cap_name)
+ visibility_front_E = target_info.minprint(epoch[:-2], front_left_range_E, front_right_range_E,
+ front_distance_E, front_frame, front_cap_name)
+
+ visibility_rear_E = target_info.minprint(epoch[:-2], rear_left_range_E, rear_right_range_E,
+ rear_distance_E, rear_frame, rear_cap_name)
+ visibility_rear_SE = target_info.minprint(epoch[:-2], rear_left_range_SE, rear_right_range_SE,
+ rear_distance_SE, rear_frame, rear_cap_name)
+ visibility_rear_S = target_info.minprint(epoch[:-2], rear_left_range_S, rear_right_range_S,
+ rear_distance_S, rear_frame, rear_cap_name)
+ visibility_rear_SW = target_info.minprint(epoch[:-2], rear_left_range_SW, rear_right_range_SW,
+ rear_distance_SW, rear_frame, rear_cap_name)
+ visibility_rear_W = target_info.minprint(epoch[:-2], rear_left_range_W, rear_right_range_W,
+ rear_distance_W, rear_frame, rear_cap_name)
+
+ # print(f'visibility W, NW, N, NE, E - {visibility_front_W, visibility_front_NW, visibility_front_N, visibility_front_NE, visibility_front_E}')
+ # print(f'visibility E, SE, S, SW, W - {visibility_rear_E, visibility_rear_SE, visibility_rear_S, visibility_rear_SW, visibility_rear_W}')
+
+ visibility = {'visibility_front': visibility_front, 'visibility_rear': visibility_rear,
+ 'front_W': visibility_front_W, 'front_NW': visibility_front_NW,
+ 'front_N': visibility_front_N, 'front_NE': visibility_front_NE,
+ 'front_E': visibility_front_E, 'rear_E': visibility_rear_E,
+ 'rear_SE': visibility_rear_SE, 'rear_S': visibility_rear_S,
+ 'rear_SW': visibility_rear_SW, 'rear_W': visibility_rear_W}
+ q.put(visibility)
+
+ if JS08Settings.get('image_size') == 0: # Original size
+ cv2.imwrite(f'{image_save_path}/vista/{front_cap_name}/{date}/{epoch}.png', front_frame)
+ cv2.imwrite(f'{image_save_path}/vista/{rear_cap_name}/{date}/{epoch}.png', rear_frame)
+
+ elif JS08Settings.get('image_size') == 1: # FHD size
+ front_frame = cv2.resize(front_frame, (1920, 640), interpolation=cv2.INTER_LINEAR)
+ rear_frame = cv2.resize(rear_frame, (1920, 640), interpolation=cv2.INTER_LINEAR)
+
+ cv2.imwrite(
+ f'{image_save_path}/vista/{front_cap_name}/{date}/{epoch}_{front_cap_name}.png', front_frame)
+ cv2.imwrite(
+ f'{image_save_path}/vista/{rear_cap_name}/{date}/{epoch}_{rear_cap_name}.png', rear_frame)
+
+ front_frame = cv2.resize(front_frame, (393, 105), interpolation=cv2.INTER_NEAREST) # Thumbnail size
+ rear_frame = cv2.resize(rear_frame, (393, 105), interpolation=cv2.INTER_LINEAR)
+ cv2.imwrite(
+ f'{image_save_path}/resize/{front_cap_name}/{date}/{epoch}.jpg', front_frame)
+ cv2.imwrite(
+ f'{image_save_path}/resize/{rear_cap_name}/{date}/{epoch}.jpg', rear_frame)
- print("red : ", cp_image[t_idx[0][0] + up_y, t_idx[1][0] + left_x, 0])
- print("green : ", cp_image[t_idx[0][0] + up_y, t_idx[1][0] + left_x, 1])
- print("blue : ", cp_image[t_idx[0][0] + up_y, t_idx[1][0] + left_x, 2])
- show_min_y = t_idx[0][0] + up_y
- show_min_x = t_idx[1][0] + left_x
-
- return (show_min_x, show_min_y)
-
-
-def get_rgb(epoch: str, min_x, min_y, cp_image, distance):
- """Gets the RGB values of the coordinates."""
- r_list = []
- g_list = []
- b_list = []
-
- for x, y in zip(min_x, min_y):
- r_list.append(cp_image[y, x, 0])
- g_list.append(cp_image[y, x, 1])
- b_list.append(cp_image[y, x, 2])
-
- print("red list : ", r_list)
- print("green list : ", g_list)
- print("blue list : ", b_list)
-
- visibility = save_rgb(r_list, g_list, b_list, epoch, distance)
- return visibility
-
-
-def save_rgb(r_list, g_list, b_list, epoch, distance):
- """Save the rgb information for each target."""
- try:
- save_path = os.path.join(f"rgb/PNM_9030V")
- os.mkdir(save_path)
-
- except Exception as e:
- pass
-
- if r_list:
- r_list = list(map(int, r_list))
- g_list = list(map(int, g_list))
- b_list = list(map(int, b_list))
-
- col = ["target_name", "r", "g", "b", "distance"]
- result = pd.DataFrame(columns=col)
- result["target_name"] = [f"target_{num}" for num in range(1, len(r_list) + 1)]
- result["r"] = r_list
- result["g"] = g_list
- result["b"] = b_list
- result["distance"] = distance
- result.to_csv(f"{save_path}/{epoch}.csv", mode="w", index=False)
- list1, list2, list3, select_color = curve_save.cal_curve(result)
- visibility = extinc_print(list1, list2, list3, select_color)
- print(result)
- print("Save rgb")
-
- return visibility
-
-
-def extinc_print(c1_list: list = [0, 0, 0], c2_list: list = [0, 0, 0], alp_list: list = [0, 0, 0],
- select_color: str = ""):
- """Select an appropriate value among visibility by wavelength."""
- g_ext = round(alp_list[1], 1)
+ time.sleep(1)
+ front_cap.release()
+ rear_cap.release()
+ front_cap = cv2.VideoCapture(JS08Settings.get('front_camera_rtsp'))
+ rear_cap = cv2.VideoCapture(JS08Settings.get('rear_camera_rtsp'))
- if select_color == "red":
- visibility = visibility_print(alp_list[0])
- elif select_color == "green":
- visibility = visibility_print(alp_list[1])
+ cv2.destroyAllWindows()
else:
- visibility = visibility_print(alp_list[2])
-
- return visibility
-
-
-def visibility_print(ext_g: float = 0.0):
- """Print the visibility"""
- vis_value = 0
-
- vis_value = (3.912 / ext_g)
- if vis_value > 20:
- vis_value = 20
- elif vis_value < 0.01:
- vis_value = 0.01
-
- # self.data_storage(vis_value)
- vis_value_str = f"{vis_value:.2f}" + " km"
- return vis_value_str
-
-
-def get_target(camera_name: str):
- """Retrieves target information of a specific camera."""
-
- save_path = os.path.join(f"target/{camera_name}")
- print("Get target information")
- if os.path.isfile(f"{save_path}/{camera_name}.csv"):
- target_df = pd.read_csv(f"{save_path}/{camera_name}.csv")
- target_name = target_df["target_name"].tolist()
- left_range = target_df["left_range"].tolist()
- left_range = str_to_tuple(left_range)
- right_range = target_df["right_range"].tolist()
- right_range = str_to_tuple(right_range)
- distance = target_df["distance"].tolist()
- return left_range, right_range, distance
-
-
-def str_to_tuple(before_list):
- """A function that converts the tuple list, which is the location information of the stored targets,
- into a string and converts it back into a tuple form."""
- tuple_list = [i.split(',') for i in before_list]
- tuple_list = [(int(i[0][1:]), int(i[1][:-1])) for i in tuple_list]
- return tuple_list
-
-
-class VideoThread(QThread):
- update_pixmap_signal = pyqtSignal(str)
-
- def __init__(self, src: str = "", file_type: str = "None", q: Queue = None):
- super().__init__()
- self._run_flag = False
- self.src = src
- self.file_type = file_type
- self.q = q
-
- def run(self):
- self._run_flag = True
- ## 영상 입력이 카메라일 때
- if self.file_type == "Video":
- print("비디오 쓰레드 시작")
- while self._run_flag:
- if not self.q.empty():
- cv_img = self.q.get()
- self.update_pixmap_signal.emit(cv_img)
- # shut down capture system
-
- def stop(self):
- """Sets run flag to False and waits for thread to finish"""
- self._run_flag = False
- self.quit()
- self.wait()
+ print('cap closed')