22
33import depthai as dai
44import cv2
5- import numpy
65import serial
76import numpy as np
87
98from PyQt5 import QtCore , QtGui , QtWidgets
10- from PyQt5 .QtWidgets import QDialog , QAbstractSpinBox
119import os
1210import time
1311from matplotlib import pyplot as plt
1412
13+
14+ def argument_parser ():
15+ import argparse
16+ msg = "PyQT5 app for depth testing"
17+ parser = argparse .ArgumentParser (description = msg )
18+ msg = "Threshold error for 2m distance (in meters), default is 0.09"
19+ parser .add_argument ('-t' , '--threshold' , type = float , default = 0.09 , help = msg )
20+ global THRESHOLD
21+ THRESHOLD = parser .parse_args ().threshold
22+
23+
1524colorMode = QtGui .QImage .Format_RGB888
1625try :
1726 colorMode = QtGui .QImage .Format_BGR888
@@ -40,10 +49,10 @@ def setupUi(self, DepthTest):
4049 font .setPointSize (18 )
4150 self .l_info .setFont (font )
4251 self .l_info .setStyleSheet ("QLabel {\n "
43- " .adjust-line-height {\n "
44- " line-height: 1em;\n "
45- " }\n "
46- "}" )
52+ " .adjust-line-height {\n "
53+ " line-height: 1em;\n "
54+ " }\n "
55+ "}" )
4756 self .l_info .setObjectName ("l_info" )
4857 self .l_result = QtWidgets .QLabel (self .centralwidget )
4958 self .l_result .setGeometry (QtCore .QRect (110 , 280 , 101 , 51 ))
@@ -196,17 +205,17 @@ def retranslateUi(self, DepthTest):
196205 _translate = QtCore .QCoreApplication .translate
197206 DepthTest .setWindowTitle (_translate ("DepthTest" , "Depth Test" ))
198207 self .l_info .setText (_translate ("DepthTest" , "<html>\n "
199- "<head/>\n "
200- "<body>\n "
201- "<div style=\" line-height:49px\" >\n "
202- "<p align=\" right\" >\n "
203- "LiDAR Depth:<br>\n "
204- "fillRate:<br>\n "
205- "gtPlaneRMSE:<br>\n "
206- "planeFitMSE:<br>\n "
207- "gtPlaneMSE:<br>\n "
208- "planeFitRMSE:<br>\n "
209- "pixelsNo:</span></p>" ))
208+ "<head/>\n "
209+ "<body>\n "
210+ "<div style=\" line-height:49px\" >\n "
211+ "<p align=\" right\" >\n "
212+ "LiDAR Depth:<br>\n "
213+ "fillRate:<br>\n "
214+ "gtPlaneRMSE:<br>\n "
215+ "planeFitMSE:<br>\n "
216+ "gtPlaneMSE:<br>\n "
217+ "planeFitRMSE:<br>\n "
218+ "pixelsNo:</span></p>" ))
210219 self .b_connect .setText (_translate ("DepthTest" , "Connect" ))
211220 self .l_test .setText (_translate ("DepthTest" , "Depth Test" ))
212221 self .l_lidar .setText (_translate ("DepthTest" , "-" ))
@@ -313,7 +322,8 @@ def __init__(self, lrcheck, subpixel, extended, distortion, resolution):
313322 product = calib_obj .eepromToJson ()['productMame' ]
314323 except KeyError :
315324 product = calib_obj .eepromToJson ()['boardName' ]
316- M_right = np .array (calib_obj .getCameraIntrinsics (calib_obj .getStereoRightCameraId (), self .resolution [0 ], self .resolution [1 ]))
325+ M_right = np .array (
326+ calib_obj .getCameraIntrinsics (calib_obj .getStereoRightCameraId (), self .resolution [0 ], self .resolution [1 ]))
317327 R2 = np .array (calib_obj .getStereoRightRectificationRotation ())
318328 H_right_inv = np .linalg .inv (np .matmul (np .matmul (M_right , R2 ), np .linalg .inv (M_right )))
319329 global inter_conv
@@ -407,8 +417,8 @@ def get_roi(self):
407417 if self .p1 is None and self .p2 is None :
408418 return None , None
409419 resolution = self .camera .get_resolution ()
410- sbox = [int (self .p1 [0 ]* resolution [0 ]/ self .width ), int (self .p1 [1 ]* resolution [1 ]/ self .height )]
411- ebox = [int (self .p2 [0 ]* resolution [0 ]/ self .width ), int (self .p2 [1 ]* resolution [1 ]/ self .height )]
420+ sbox = [int (self .p1 [0 ] * resolution [0 ] / self .width ), int (self .p1 [1 ] * resolution [1 ] / self .height )]
421+ ebox = [int (self .p2 [0 ] * resolution [0 ] / self .width ), int (self .p2 [1 ] * resolution [1 ] / self .height )]
412422 if sbox [0 ] > ebox [0 ]:
413423 sbox [0 ], ebox [0 ] = ebox [0 ], sbox [0 ]
414424 if sbox [1 ] > ebox [1 ]:
@@ -542,8 +552,8 @@ def search_depth(x, y, depth):
542552def fit_plane_LTSQ (XYZ ):
543553 (rows , cols ) = XYZ .shape
544554 G = np .ones ((rows , 3 ))
545- G [:, 0 ] = XYZ [:, 0 ] #X
546- G [:, 1 ] = XYZ [:, 1 ] #Y
555+ G [:, 0 ] = XYZ [:, 0 ] # X
556+ G [:, 1 ] = XYZ [:, 1 ] # Y
547557 Z = XYZ [:, 2 ]
548558 (a , b , c ), resid , rank , s = np .linalg .lstsq (G , Z , rcond = None )
549559 normal = (a , b , - 1 )
@@ -587,7 +597,7 @@ def __init__(self):
587597 self .timer = QtCore .QTimer ()
588598 self .timer .timeout .connect (self .timer_event )
589599 # self.timer.start(1000 // 30)
590- try : # TODO Find a way to scan for USB ports
600+ try : # TODO Find a way to scan for USB ports
591601 self .serial_reader = serial .Serial ("/dev/ttyUSB0" , 115200 )
592602 except :
593603 self .serial_reader = None
@@ -637,7 +647,9 @@ def button_event(self):
637647 self .ui .c_ir .setDisabled (True )
638648 self .ui .b_export .setDisabled (True )
639649 else :
640- self .scene .get_frame ().enable_camera (self .ui .c_lrcheck .isChecked (), self .ui .c_subpixel .isChecked (), self .ui .c_extended .isChecked (), self .ui .c_distrotion .isChecked (), self .ui .combo_res .currentText ())
650+ self .scene .get_frame ().enable_camera (self .ui .c_lrcheck .isChecked (), self .ui .c_subpixel .isChecked (),
651+ self .ui .c_extended .isChecked (), self .ui .c_distrotion .isChecked (),
652+ self .ui .combo_res .currentText ())
641653 self .count = 0
642654 self .pass_count = 0
643655 self .fail_count = 0
@@ -699,7 +711,7 @@ def calculate_errors(self):
699711 sbox , ebox = self .scene .get_frame ().get_roi ()
700712 if sbox is None or ebox is None :
701713 return False
702- self .pixels_no = (ebox [0 ]- sbox [0 ])* (ebox [1 ]- sbox [1 ])
714+ self .pixels_no = (ebox [0 ] - sbox [0 ]) * (ebox [1 ] - sbox [1 ])
703715 depth_roi = depth_frame [sbox [1 ]:ebox [1 ], sbox [0 ]:ebox [0 ]]
704716 coord = pixel_coord_np (* sbox , * ebox )
705717 # Removing Zeros from coordinates
@@ -708,8 +720,11 @@ def calculate_errors(self):
708720 # Removing outliers from Z coordinates. top and bottoom 0.5 percentile of valid depth
709721 try :
710722 valid_cam_coords = np .delete (cam_coords , np .where (cam_coords [2 , :] == 0.0 ), axis = 1 )
711- valid_cam_coords = np .delete (valid_cam_coords , np .where (valid_cam_coords [2 , :] <= np .percentile (valid_cam_coords [2 , :], 0.5 )), axis = 1 )
712- valid_cam_coords = np .delete (valid_cam_coords , np .where (valid_cam_coords [2 , :] >= np .percentile (valid_cam_coords [2 , :], 99.5 )), axis = 1 )
723+ valid_cam_coords = np .delete (valid_cam_coords ,
724+ np .where (valid_cam_coords [2 , :] <= np .percentile (valid_cam_coords [2 , :], 0.5 )),
725+ axis = 1 )
726+ valid_cam_coords = np .delete (valid_cam_coords , np .where (
727+ valid_cam_coords [2 , :] >= np .percentile (valid_cam_coords [2 , :], 99.5 )), axis = 1 )
713728 except IndexError :
714729 return
715730
@@ -746,7 +761,7 @@ def calculate_errors(self):
746761 absolute_error += gt_plane_dist
747762 planeR_ms_offset_rror += fitPlaneDist ** 2
748763 gtR_ms_offset_error += gt_plane_dist ** 2
749-
764+
750765 self .plane_fit_mse = plane_offset_error / valid_cam_coords .shape [1 ]
751766 self .gt_plane_mse = absolute_error / valid_cam_coords .shape [1 ]
752767 self .plane_fit_rmse = np .sqrt (planeR_ms_offset_rror / valid_cam_coords .shape [1 ])
@@ -823,10 +838,10 @@ def timer_event(self):
823838 if self .count < 30 :
824839 self .gt_plane_rmse_avg += self .gt_plane_rmse / 30
825840 self .gt_plane_rmse_arr .append (self .gt_plane_rmse_avg )
826- self .fill_plane_avg += self .fill_rate / 30
827- self .plane_fit_mse_avg += self .plane_fit_mse / 30
828- self .gt_plane_mse_avg += self .gt_plane_mse / 30
829- self .plane_fit_rmse_avg += self .plane_fit_rmse / 30
841+ self .fill_plane_avg += self .fill_rate / 30
842+ self .plane_fit_mse_avg += self .plane_fit_mse / 30
843+ self .gt_plane_mse_avg += self .gt_plane_mse / 30
844+ self .plane_fit_rmse_avg += self .plane_fit_rmse / 30
830845 self .count += 1
831846 else :
832847 self .ui .l_fill_rate .setText (f'{ self .fill_plane_avg } ' )
@@ -847,11 +862,11 @@ def timer_event(self):
847862 self .plane_fit_rmse_avg = 0
848863 self .gt_plane_rmse_med = np .median (self .gt_plane_rmse_arr )
849864 if self .true_distance <= 1 :
850- error_threshold = 0.03
865+ error_threshold = THRESHOLD / 2
851866 elif self .true_distance >= 2 :
852- error_threshold = 0.06
867+ error_threshold = THRESHOLD
853868 else :
854- error_threshold = self .true_distance * 0.03
869+ error_threshold = self .true_distance * THRESHOLD / 2
855870 if self .gt_plane_rmse_res < error_threshold and self .fill_plane_res > 0.98 :
856871 self .set_result ('PASS' )
857872 else :
@@ -861,7 +876,7 @@ def timer_event(self):
861876
862877if __name__ == "__main__" :
863878 import sys
864-
879+ argument_parser ()
865880 app = QtWidgets .QApplication (sys .argv )
866881 class_instance = Application ()
867882 class_instance .show ()
0 commit comments