diff --git a/calibrators/intrinsic_camera_calibrator/intrinsic_camera_calibrator/intrinsic_camera_calibrator/board_detections/array_board_detection.py b/calibrators/intrinsic_camera_calibrator/intrinsic_camera_calibrator/intrinsic_camera_calibrator/board_detections/array_board_detection.py index cef074f9..12f15819 100644 --- a/calibrators/intrinsic_camera_calibrator/intrinsic_camera_calibrator/intrinsic_camera_calibrator/board_detections/array_board_detection.py +++ b/calibrators/intrinsic_camera_calibrator/intrinsic_camera_calibrator/intrinsic_camera_calibrator/board_detections/array_board_detection.py @@ -65,8 +65,10 @@ def squared_error(p, p1, p2): squared_distance = np.abs(np.power(np.linalg.norm(p), 2) - np.power(np.dot(p, p2), 2)) return squared_distance - if self._cached_linear_error_rows_rms is not None and \ - self._cached_linear_error_cols_rms is not None: + if ( + self._cached_linear_error_rows_rms is not None + and self._cached_linear_error_cols_rms is not None + ): return self._cached_linear_error_rows_rms, self._cached_linear_error_cols_rms error_rows = 0 @@ -103,8 +105,12 @@ def squared_error(p, p1, p2): self._cached_linear_error_cols_rms = np.sqrt(error_cols / (self.cols * (self.rows - 2))) pct_err_cols = pct_err_cols / (self.cols * (self.rows - 2)) - return self._cached_linear_error_rows_rms, self._cached_linear_error_cols_rms, \ - pct_err_rows, pct_err_cols + return ( + self._cached_linear_error_rows_rms, + self._cached_linear_error_cols_rms, + pct_err_rows, + pct_err_cols, + ) def get_flattened_cell_sizes(self): if self._cached_flattened_cell_sizes is not None: @@ -122,13 +128,13 @@ def get_flattened_cell_sizes(self): self._cached_flattened_cell_sizes = cell_sizes.flatten() return self._cached_flattened_cell_sizes - + def get_aspect_ratio_pattern(self) -> float: """Get aspect ratio using the calibration pattern, wich should be squared.""" tilt, pan = self.get_rotation_angles() acceptance_angle = 10 - # dont update if we the detection has big angles, calculation will not be accurate + # dont update if we the detection has big angles, calculation will not be accurate if np.abs(tilt) > acceptance_angle or np.abs(pan) > acceptance_angle: return 0.0 # Calculate distances between adjacent corners @@ -143,7 +149,6 @@ def get_aspect_ratio_pattern(self) -> float: vertical_distance = np.linalg.norm(p - pcol) aspect_ratio = aspect_ratio + (horizontal_distance / vertical_distance) count += 1 - aspect_ratio = aspect_ratio / ((self.rows - 1) * (self.cols - 1)) + aspect_ratio = aspect_ratio / ((self.rows - 1) * (self.cols - 1)) return aspect_ratio - diff --git a/calibrators/intrinsic_camera_calibrator/intrinsic_camera_calibrator/intrinsic_camera_calibrator/camera_calibrator.py b/calibrators/intrinsic_camera_calibrator/intrinsic_camera_calibrator/intrinsic_camera_calibrator/camera_calibrator.py index 63e1e2ec..e663119d 100644 --- a/calibrators/intrinsic_camera_calibrator/intrinsic_camera_calibrator/intrinsic_camera_calibrator/camera_calibrator.py +++ b/calibrators/intrinsic_camera_calibrator/intrinsic_camera_calibrator/intrinsic_camera_calibrator/camera_calibrator.py @@ -421,9 +421,7 @@ def make_detection_group(self): self.raw_detection_results_group = QGroupBox("Detection results") self.raw_detection_results_group.setFlat(True) - self.single_shot_detection_results_group = QGroupBox( - "Single-shot detection results" - ) + self.single_shot_detection_results_group = QGroupBox("Single-shot detection results") self.single_shot_detection_results_group.setFlat(True) self.raw_detection_label = QLabel("Detected:") @@ -567,7 +565,7 @@ def draw_training_heatmap_callback(value): def draw_evaluation_heatmap_callback(value): self.image_view.set_draw_evaluation_heatmap(value == Qt.Checked) self.should_process_image.emit() - + def draw_linearity_heatmap_callback(value): self.image_view.set_draw_linearity_heatmap(value == Qt.Checked) self.should_process_image.emit() @@ -609,9 +607,7 @@ def on_restart_linearity_heatmap_clicked(): self.undistortion_alpha_spinbox.valueChanged.connect( lambda: self.should_process_image.emit() ) - self.undistortion_alpha_spinbox.valueChanged.connect( - on_restart_linearity_heatmap_clicked - ) + self.undistortion_alpha_spinbox.valueChanged.connect(on_restart_linearity_heatmap_clicked) self.undistortion_alpha_spinbox.setEnabled(False) indicators_alpha_label = QLabel("Indicators alpha:") @@ -696,9 +692,13 @@ def start( self.setEnabled(True) if self.operation_mode == OperationMode.CALIBRATION: - self.setWindowTitle(f"Camera intrinsics calibrator ({self.data_source.get_camera_name()})") + self.setWindowTitle( + f"Camera intrinsics calibrator ({self.data_source.get_camera_name()})" + ) if self.operation_mode == OperationMode.EVALUATION: - self.setWindowTitle(f"Camera intrinsics Evaluation Mode ({self.data_source.get_camera_name()})") + self.setWindowTitle( + f"Camera intrinsics Evaluation Mode ({self.data_source.get_camera_name()})" + ) logging.info("Init") logging.info(f"\tmode : {mode}") @@ -727,11 +727,13 @@ def start( self.evaluation_sample_slider.setEnabled(False) self.image_view_type_combobox.clear() # Order of of how items are added to the combobox matters, - # default index is 0, so rectified image is added first to be default view - self.image_view_type_combobox.addItem(ImageViewMode.SOURCE_RECTIFIED.value, \ - ImageViewMode.SOURCE_RECTIFIED) - self.image_view_type_combobox.addItem(ImageViewMode.SOURCE_UNRECTIFIED.value, \ - ImageViewMode.SOURCE_UNRECTIFIED) + # default index is 0, so rectified image is added first to be default view + self.image_view_type_combobox.addItem( + ImageViewMode.SOURCE_RECTIFIED.value, ImageViewMode.SOURCE_RECTIFIED + ) + self.image_view_type_combobox.addItem( + ImageViewMode.SOURCE_UNRECTIFIED.value, ImageViewMode.SOURCE_UNRECTIFIED + ) self.detector.moveToThread(self.detector_thread) self.detector.detection_results_signal.connect(self.process_detection_results) @@ -850,19 +852,21 @@ def process_evaluation_results( def on_consumed(self): self.data_source.consumed() - def save_parameters(self,filename): + def save_parameters(self, filename): data_coll_params = self.data_collector.parameters_value() board_params = self.board_parameters.parameters_value() detector_params = self.detector.parameters_value() calibrator_type = self.calibrator_type_combobox.currentData() print(calibrator_type.value["name"], flush=True) calib_params = self.calibrator_dict[calibrator_type].parameters_value() - with open(filename, 'w') as file: - yaml.dump({"board_parameters" : board_params}, file, default_flow_style=False) - yaml.dump({"calibrator_type" : calibrator_type.value["name"]}, file, default_flow_style=False) + with open(filename, "w") as file: + yaml.dump({"board_parameters": board_params}, file, default_flow_style=False) + yaml.dump( + {"calibrator_type": calibrator_type.value["name"]}, file, default_flow_style=False + ) yaml.dump({"calibration_parameters": calib_params}, file, default_flow_style=False) - yaml.dump({"data_collector" : data_coll_params}, file, default_flow_style=False) - yaml.dump({"detector_params" : detector_params}, file, default_flow_style=False) + yaml.dump({"data_collector": data_coll_params}, file, default_flow_style=False) + yaml.dump({"detector_params": detector_params}, file, default_flow_style=False) def on_save_clicked(self): output_folder = QFileDialog.getExistingDirectory( @@ -896,17 +900,25 @@ def on_save_clicked(self): for index, image in enumerate(self.data_collector.get_training_images()): cv2.imwrite(os.path.join(training_folder, f"{index:04d}.jpg"), image) # noqa E231 - np.savetxt(os.path.join(training_folder,f"{index:04d}_training_img_points.txt"), \ - self.data_collector.get_training_detection(index).get_flattened_image_points()) - np.savetxt(os.path.join(training_folder,f"{index:04d}_training_obj_points.txt"), \ - self.data_collector.get_training_detection(index).get_flattened_object_points()) + np.savetxt( + os.path.join(training_folder, f"{index:04d}_training_img_points.txt"), + self.data_collector.get_training_detection(index).get_flattened_image_points(), + ) + np.savetxt( + os.path.join(training_folder, f"{index:04d}_training_obj_points.txt"), + self.data_collector.get_training_detection(index).get_flattened_object_points(), + ) for index, image in enumerate(self.data_collector.get_evaluation_images()): cv2.imwrite(os.path.join(evaluation_folder, f"{index:04d}.jpg"), image) # noqa E231 - np.savetxt(os.path.join(evaluation_folder,f"{index:04d}_eval_img_points.txt"), \ - self.data_collector.get_evaluation_detection(index).get_flattened_image_points()) - np.savetxt(os.path.join(evaluation_folder,f"{index:04d}_eval_obj_points.txt"), \ - self.data_collector.get_evaluation_detection(index).get_flattened_object_points()) + np.savetxt( + os.path.join(evaluation_folder, f"{index:04d}_eval_img_points.txt"), + self.data_collector.get_evaluation_detection(index).get_flattened_image_points(), + ) + np.savetxt( + os.path.join(evaluation_folder, f"{index:04d}_eval_obj_points.txt"), + self.data_collector.get_evaluation_detection(index).get_flattened_object_points(), + ) def process_detection_results(self, img: np.array, detection: BoardDetection, img_stamp: float): """Process the results from an object detection.""" @@ -942,16 +954,21 @@ def process_detection_results(self, img: np.array, detection: BoardDetection, im self.single_shot_reprojection_error_avg_label.setText("Reprojection error (avg):") self.single_shot_reprojection_error_rms_label.setText("Reprojection error (rms):") board_speed = None - self.image_view.set_draw_indicators(board_speed, - self.data_collector.max_allowed_pixel_speed.value, - self.data_collector.get_skew_percentage(), - self.data_collector.get_size_percentage(), - 0, 0, # rows cols linear error - 0, 0, # rows cols percentage linear error - 0.0, # aspect ratio - 0, 0, - self.indicators_alpha_spinbox.value(), - False) + self.image_view.set_draw_indicators( + board_speed, + self.data_collector.max_allowed_pixel_speed.value, + self.data_collector.get_skew_percentage(), + self.data_collector.get_size_percentage(), + 0, + 0, # rows cols linear error + 0, + 0, # rows cols percentage linear error + 0.0, # aspect ratio + 0, + 0, + self.indicators_alpha_spinbox.value(), + False, + ) else: camera_model = ( @@ -969,9 +986,11 @@ def process_detection_results(self, img: np.array, detection: BoardDetection, im ) else: filter_result = CollectionStatus.NOT_EVALUATED - - if self.operation_mode == OperationMode.EVALUATION and \ - self.image_view_type_combobox.currentData() == ImageViewMode.SOURCE_RECTIFIED: + + if ( + self.operation_mode == OperationMode.EVALUATION + and self.image_view_type_combobox.currentData() == ImageViewMode.SOURCE_RECTIFIED + ): self.data_collector.process_detection_eval_mode( image=img, detection=detection, @@ -1025,7 +1044,9 @@ def process_detection_results(self, img: np.array, detection: BoardDetection, im rough_angles = detection.get_rotation_angles(camera_model) self.raw_detection_label.setText("Detected: True") - err_rms_rows, err_rms_cols, pct_err_rows, pct_err_cols = detection.get_linear_error_rms() + err_rms_rows, err_rms_cols, pct_err_rows, pct_err_cols = ( + detection.get_linear_error_rms() + ) self.raw_linear_error_rows_rms_label.setText( f"Linear error rows rms: {err_rms_rows:.2f} px" # noqa E231 ) @@ -1067,19 +1088,26 @@ def process_detection_results(self, img: np.array, detection: BoardDetection, im f"Evaluation occupancy: {100.0*self.data_collector.get_evaluation_occupancy_rate():.2f}" # noqa E231 ) - board_speed = 0 if self.last_detection is None else detection.get_speed(self.last_detection) + board_speed = ( + 0 if self.last_detection is None else detection.get_speed(self.last_detection) + ) self.last_detection = detection pan, tilt = detection.get_rotation_angles() - self.image_view.set_draw_indicators(board_speed, - self.data_collector.max_allowed_pixel_speed.value, - self.data_collector.get_skew_percentage(), - self.data_collector.get_size_percentage(), - err_rms_rows, err_rms_cols, - pct_err_rows, pct_err_cols, - detection.get_aspect_ratio_pattern(), - pan, tilt, - self.indicators_alpha_spinbox.value(), - self.draw_indicators_checkbox.isChecked()) + self.image_view.set_draw_indicators( + board_speed, + self.data_collector.max_allowed_pixel_speed.value, + self.data_collector.get_skew_percentage(), + self.data_collector.get_size_percentage(), + err_rms_rows, + err_rms_cols, + pct_err_rows, + pct_err_cols, + detection.get_aspect_ratio_pattern(), + pan, + tilt, + self.indicators_alpha_spinbox.value(), + self.draw_indicators_checkbox.isChecked(), + ) # Draw training / evaluation points self.image_view.set_draw_training_points(self.draw_training_points_checkbox.isChecked()) @@ -1089,9 +1117,7 @@ def process_detection_results(self, img: np.array, detection: BoardDetection, im self.draw_evaluation_heatmap_checkbox.isChecked() ) - self.image_view.set_draw_linearity_heatmap( - self.draw_linearity_heatmap_checkbox.isChecked() - ) + self.image_view.set_draw_linearity_heatmap(self.draw_linearity_heatmap_checkbox.isChecked()) if self.draw_training_points_checkbox.isChecked(): self.image_view.set_training_points( @@ -1114,9 +1140,7 @@ def process_detection_results(self, img: np.array, detection: BoardDetection, im ) if self.draw_linearity_heatmap_checkbox.isChecked(): - self.image_view.set_linearity_heatmap( - self.data_collector.get_linearity_heatmap() - ) + self.image_view.set_linearity_heatmap(self.data_collector.get_linearity_heatmap()) if self.operation_mode == OperationMode.CALIBRATION: if ( diff --git a/calibrators/intrinsic_camera_calibrator/intrinsic_camera_calibrator/intrinsic_camera_calibrator/data_collector.py b/calibrators/intrinsic_camera_calibrator/intrinsic_camera_calibrator/intrinsic_camera_calibrator/data_collector.py index ddb0f27d..813379d6 100644 --- a/calibrators/intrinsic_camera_calibrator/intrinsic_camera_calibrator/intrinsic_camera_calibrator/data_collector.py +++ b/calibrators/intrinsic_camera_calibrator/intrinsic_camera_calibrator/intrinsic_camera_calibrator/data_collector.py @@ -407,43 +407,45 @@ def update_collection_heatmap(self, heatmap: np.array, detection: BoardDetection def update_linearity_heatmap(self, heatmap: np.array, detection: BoardDetection) -> float: """Update a heatmap with a single detection's image points.""" + def squared_error(p, p1, p2): p = p - p1 p2 = p2 - p1 p2 /= np.linalg.norm(p2) squared_distance = np.abs(np.power(np.linalg.norm(p), 2) - np.power(np.dot(p, p2), 2)) return squared_distance + image_points = detection.get_ordered_image_points() max_pct_error_tolerance = 0.04 for j in range(detection.rows): p1 = image_points[j][0] p2 = image_points[j][-1] - points_dist = np.linalg.norm(p2 -p1) + points_dist = np.linalg.norm(p2 - p1) for i in range(1, detection.cols - 1): p = image_points[j][i] dist_error = np.sqrt(squared_error(p, p1, p2)) - if (dist_error/points_dist > max_pct_error_tolerance): + if dist_error / points_dist > max_pct_error_tolerance: # if distance is too big most likely is a miss detection dist_error = 0 x = int(heatmap.shape[1] * p[0] / detection.width) y = int(heatmap.shape[0] * p[1] / detection.height) - if (heatmap[y, x] < dist_error): + if heatmap[y, x] < dist_error: heatmap[y, x] = 1 * dist_error for j in range(detection.cols): p1 = image_points[0][j] p2 = image_points[-1][j] - points_dist = np.linalg.norm(p2 -p1) + points_dist = np.linalg.norm(p2 - p1) for i in range(1, detection.rows - 1): p = image_points[i][j] dist_error = np.sqrt(squared_error(p, p1, p2)) - if (dist_error/points_dist > max_pct_error_tolerance): + if dist_error / points_dist > max_pct_error_tolerance: # if distance is too big most likely is a miss detection dist_error = 0 x = int(heatmap.shape[1] * p[0] / detection.width) y = int(heatmap.shape[0] * p[1] / detection.height) - if (heatmap[y, x] < dist_error): + if heatmap[y, x] < dist_error: heatmap[y, x] = 1 * dist_error def restart_linearity_heatmap(self): @@ -592,7 +594,7 @@ def process_detection_eval_mode( mode: OperationMode = OperationMode.CALIBRATION, ) -> CollectionStatus: """Evaluate detections mad ein evaluation mode.""" - # process wihtout filtering detections + # process wihtout filtering detections self.update_linearity_heatmap(self.linearity_heatmap, detection) def get_skew_coverage(self): @@ -603,7 +605,7 @@ def get_skew_coverage(self): # Create a unique set to store covered intervals covered_intervals = set() # range in radians ToDo: define the range - skew_range = np.array([0,1.04]) + skew_range = np.array([0, 1.04]) for detection in self.training_data.get_detections(): if skew_range[0] <= detection.get_normalized_skew() < skew_range[1]: @@ -611,7 +613,7 @@ def get_skew_coverage(self): covered_intervals.add(interval_index) # Calculate the percentage of covered intervals - percentage_coverage = (len(covered_intervals) / num_intervals) # * 100 + percentage_coverage = len(covered_intervals) / num_intervals # * 100 return percentage_coverage @@ -627,7 +629,7 @@ def get_size_coverage(self): # Create a set to store covered intervals covered_intervals = set() # range for board size ToDo: define the range - size_range = np.array([0.08,0.21]) + size_range = np.array([0.08, 0.21]) for detection in self.training_data.get_detections(): if size_range[0] <= detection.get_normalized_size() < size_range[1]: @@ -635,7 +637,7 @@ def get_size_coverage(self): covered_intervals.add(interval_index) # Calculate the percentage of covered intervals - percentage_coverage = (len(covered_intervals) / num_intervals) # * 100 + percentage_coverage = len(covered_intervals) / num_intervals # * 100 return percentage_coverage diff --git a/calibrators/intrinsic_camera_calibrator/intrinsic_camera_calibrator/intrinsic_camera_calibrator/views/image_view.py b/calibrators/intrinsic_camera_calibrator/intrinsic_camera_calibrator/intrinsic_camera_calibrator/views/image_view.py index 8b0deded..05500bff 100644 --- a/calibrators/intrinsic_camera_calibrator/intrinsic_camera_calibrator/intrinsic_camera_calibrator/views/image_view.py +++ b/calibrators/intrinsic_camera_calibrator/intrinsic_camera_calibrator/intrinsic_camera_calibrator/views/image_view.py @@ -23,11 +23,11 @@ from PySide2.QtCore import Qt from PySide2.QtGui import QBrush from PySide2.QtGui import QColor +from PySide2.QtGui import QFont from PySide2.QtGui import QImage from PySide2.QtGui import QPainter from PySide2.QtGui import QPen from PySide2.QtGui import QPixmap -from PySide2.QtGui import QFont from PySide2.QtWidgets import QGraphicsItem from PySide2.QtWidgets import QGraphicsView import cv2 @@ -174,7 +174,7 @@ def set_draw_training_heatmap(self, value: bool): def set_draw_evaluation_heatmap(self, value: bool): """Set the flag of wether or not to draw the occupancy heatmap of the evaluation dataset.""" self.is_draw_evaluation_heatmap = value - + def set_draw_linearity_heatmap(self, value: bool): """Set the flag of wether or not to draw the linearity heatmap.""" self.is_draw_linearity_heatmap = value @@ -211,14 +211,22 @@ def set_rendering_alpha(self, value: float): """Set the alpha channel of the drawings.""" self.rendering_alpha = value - def set_draw_indicators(self, board_speed: float, max_allowed_board_speed: float, - skew_percentage: float, board_size_percentage: float, - rows_linear_error: float, cols_linear_error: float, - pct_err_rows: float, pct_err_cols: float, - aspect_ratio: float, - pan: float, tilt: float, - alpha_indicators: float, - value: bool): + def set_draw_indicators( + self, + board_speed: float, + max_allowed_board_speed: float, + skew_percentage: float, + board_size_percentage: float, + rows_linear_error: float, + cols_linear_error: float, + pct_err_rows: float, + pct_err_cols: float, + aspect_ratio: float, + pan: float, + tilt: float, + alpha_indicators: float, + value: bool, + ): """Set values for indicators.""" self.current_board_speed = board_speed self.max_board_allowed_speed = max_allowed_board_speed @@ -231,7 +239,7 @@ def set_draw_indicators(self, board_speed: float, max_allowed_board_speed: float self.aspect_ratio = aspect_ratio self.pan = pan self.tilt = tilt - self.alpha_indicators = alpha_indicators + self.alpha_indicators = alpha_indicators self.is_draw_indicators = value def draw_indicators(self, painter: QPainter, display_size): @@ -239,7 +247,7 @@ def draw_indicators(self, painter: QPainter, display_size): color_green = QColor(0.0, 255, 0.0, int(255 * self.alpha_indicators)) color_red = QColor(255, 0.0, 0.0, int(255 * self.alpha_indicators)) # Change color according tot he speed - if (self.current_board_speed < self.max_board_allowed_speed): + if self.current_board_speed < self.max_board_allowed_speed: pen = QPen(color_green) brush = QBrush(color_green) else: @@ -247,7 +255,9 @@ def draw_indicators(self, painter: QPainter, display_size): brush = QBrush(color_red) painter.setPen(pen) painter.setBrush(brush) - speed_indicator = QRectF(QPointF(0, 0), QSize(display_size.width(), int(display_size.height()*0.04))) + speed_indicator = QRectF( + QPointF(0, 0), QSize(display_size.width(), int(display_size.height() * 0.04)) + ) # Draw the rectangle for speed indication painter.drawRect(speed_indicator) @@ -255,7 +265,9 @@ def draw_indicators(self, painter: QPainter, display_size): font_size = max(10, display_size.height() / 40) font = QFont("Arial", font_size) painter.setFont(font) - position_text_speed = QPointF(int(display_size.width() * .01), int(display_size.height() * .10)) + position_text_speed = QPointF( + int(display_size.width() * 0.01), int(display_size.height() * 0.10) + ) painter.drawText(position_text_speed, "Speed") # ToDo: define percentage to change skew and pct size to change to green @@ -270,15 +282,22 @@ def draw_indicators(self, painter: QPainter, display_size): painter.setBrush(brush_skew) # Draw Skew text - position_text_skew = QPointF(int(display_size.width() * .01), int(display_size.height() * .88)) + position_text_skew = QPointF( + int(display_size.width() * 0.01), int(display_size.height() * 0.88) + ) painter.drawText(position_text_skew, "Skew " + str(int(self.skew_percentage * 100)) + "%") - skew_indicator = QRectF(QPointF(int(display_size.width() * .12), int(display_size.height() * .85)), - QSize(display_size.width() * 0.08 * self.skew_percentage, int(display_size.height()*0.03))) + skew_indicator = QRectF( + QPointF(int(display_size.width() * 0.12), int(display_size.height() * 0.85)), + QSize( + display_size.width() * 0.08 * self.skew_percentage, + int(display_size.height() * 0.03), + ), + ) # Draw the skew progrees bar painter.drawRect(skew_indicator) - # ToDo: define percentage to change skew and pct size to change to green + # ToDo: define percentage to change skew and pct size to change to green thresold_to_be_green = 0.2 if self.board_size_percentage < thresold_to_be_green: pen_size_board = QPen(color_red) @@ -291,29 +310,61 @@ def draw_indicators(self, painter: QPainter, display_size): painter.setBrush(brush_size_board) # Draw board size text - position_text_size = QPointF(int(display_size.width() * .01), int(display_size.height() * .93)) - painter.drawText(position_text_size, "Size " + str(int(self.board_size_percentage * 100)) + "%") - board_size_indicator = QRectF(QPointF(int(display_size.width() * .12), int(display_size.height() * .90)), - QSize(display_size.width() * 0.08 * self.board_size_percentage, int(display_size.height() * 0.03))) + position_text_size = QPointF( + int(display_size.width() * 0.01), int(display_size.height() * 0.93) + ) + painter.drawText( + position_text_size, "Size " + str(int(self.board_size_percentage * 100)) + "%" + ) + board_size_indicator = QRectF( + QPointF(int(display_size.width() * 0.12), int(display_size.height() * 0.90)), + QSize( + display_size.width() * 0.08 * self.board_size_percentage, + int(display_size.height() * 0.03), + ), + ) # Draw the board size progrees bar painter.drawRect(board_size_indicator) # Draw board pan tilt angle text - deg_sign = u'\N{DEGREE SIGN}' - position_text_pan = QPointF(int(display_size.width() * .01), int(display_size.height() * .98)) - painter.drawText(position_text_pan, "Pan " + str(int(self.pan)) + deg_sign + " Tilt " + str(int(self.tilt)) + deg_sign) + deg_sign = "\N{DEGREE SIGN}" + position_text_pan = QPointF( + int(display_size.width() * 0.01), int(display_size.height() * 0.98) + ) + painter.drawText( + position_text_pan, + "Pan " + str(int(self.pan)) + deg_sign + " Tilt " + str(int(self.tilt)) + deg_sign, + ) # Draw Linear errors text - position_text_err_rows = QPointF(int(display_size.width() * .80), int(display_size.height() * .88)) - painter.drawText(position_text_err_rows, "ErrRows " + str(round(self.rows_linear_error, 1)) + "px " + \ - str(round(self.pct_err_rows * 100, 1)) + "%") + position_text_err_rows = QPointF( + int(display_size.width() * 0.80), int(display_size.height() * 0.88) + ) + painter.drawText( + position_text_err_rows, + "ErrRows " + + str(round(self.rows_linear_error, 1)) + + "px " + + str(round(self.pct_err_rows * 100, 1)) + + "%", + ) - position_text_err_cols = QPointF(int(display_size.width() * .80), int(display_size.height() * .93)) - painter.drawText(position_text_err_cols, "ErrCols " + str(round(self.cols_linear_error, 1)) + "px " + \ - str(round(self.pct_err_cols *100, 1)) + "%") + position_text_err_cols = QPointF( + int(display_size.width() * 0.80), int(display_size.height() * 0.93) + ) + painter.drawText( + position_text_err_cols, + "ErrCols " + + str(round(self.cols_linear_error, 1)) + + "px " + + str(round(self.pct_err_cols * 100, 1)) + + "%", + ) # Draw the aspect ratio text indicator - position_text_aspect_ratio = QPointF(int(display_size.width() * .80), int(display_size.height() * .98)) + position_text_aspect_ratio = QPointF( + int(display_size.width() * 0.80), int(display_size.height() * 0.98) + ) painter.drawText(position_text_aspect_ratio, "AspectR " + str(round(self.aspect_ratio, 2))) def pixmap(self) -> QPixmap: