-
Notifications
You must be signed in to change notification settings - Fork 37
Min brightness filter #254
Changes from 13 commits
11683ab
a8fe876
cf55564
3e814ab
51601e9
834ad07
a7e902d
4af7e51
fc6e4ae
379d6d3
ba55fdf
3b760c6
7b33fc7
6b28cd2
4991170
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,6 +43,8 @@ def __init__( | |
| filter_by_area: bool, | ||
| min_area_pixels: int, | ||
| max_area_pixels: int, | ||
| min_brightness_threshold: int, | ||
| min_average_brightness_threshold: int, | ||
| ) -> None: | ||
| """ | ||
| Initializes the configuration for DetectTargetBrightspot. | ||
|
|
@@ -62,6 +64,7 @@ def __init__( | |
| filter_by_area: Whether to filter by area. | ||
| min_area_pixels: Minimum area in pixels. | ||
| max_area_pixels: Maximum area in pixels. | ||
| min_brightness_threshold: Minimum brightness threshold for bright spots. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| """ | ||
| self.brightspot_percentile_threshold = brightspot_percentile_threshold | ||
| self.filter_by_color = filter_by_color | ||
|
|
@@ -78,6 +81,8 @@ def __init__( | |
| self.filter_by_area = filter_by_area | ||
| self.min_area_pixels = min_area_pixels | ||
| self.max_area_pixels = max_area_pixels | ||
| self.min_brightness_threshold = min_brightness_threshold | ||
| self.min_average_brightness_threshold = min_average_brightness_threshold | ||
|
|
||
|
|
||
| # pylint: enable=too-many-instance-attributes | ||
|
|
@@ -132,18 +137,25 @@ def run( | |
| ) | ||
| return False, None | ||
|
|
||
| # Calculate the percentile threshold for bright spots | ||
| brightspot_threshold = np.percentile( | ||
| grey_image, self.__config.brightspot_percentile_threshold | ||
| ) | ||
|
|
||
| # Apply thresholding to isolate bright spots | ||
| # Compute the maximum of the percentile threshold and the minimum brightness threshold | ||
| combined_threshold = max(brightspot_threshold, self.__config.min_brightness_threshold) | ||
|
|
||
| # Apply combined thresholding to isolate bright spots | ||
| threshold_used, bw_image = cv2.threshold( | ||
| grey_image, brightspot_threshold, 255, cv2.THRESH_BINARY | ||
| grey_image, combined_threshold, 255, cv2.THRESH_BINARY | ||
| ) | ||
| if threshold_used == 0: | ||
| self.__local_logger.error(f"{time.time()}: Failed to threshold image.") | ||
| self.__local_logger.error(f"{time.time()}: Failed to percentile threshold image.") | ||
|
||
| return False, None | ||
|
|
||
| # cv2.imshow("Thresholded", bw_image) # type: ignore | ||
| # cv2.waitKey(0) # type: ignore | ||
|
|
||
|
||
| # Set up SimpleBlobDetector | ||
| params = cv2.SimpleBlobDetector_Params() | ||
| params.filterByColor = self.__config.filter_by_color | ||
|
|
@@ -166,12 +178,57 @@ def run( | |
|
|
||
| # A lack of detections is not an error, but should still not be forwarded | ||
| if len(keypoints) == 0: | ||
| self.__local_logger.info(f"{time.time()}: No brightspots detected.") | ||
| self.__local_logger.info( | ||
| f"{time.time()}: No brightspots detected (before blob average filter)." | ||
|
||
| ) | ||
| return False, None | ||
|
|
||
| # Compute the average brightness of each blob | ||
| average_brightness_list = [] | ||
|
|
||
| for i, keypoint in enumerate(keypoints): | ||
| x, y = keypoint.pt # Center of the blob | ||
| radius = keypoint.size / 2 # Radius of the blob | ||
|
|
||
| # Define a square region of interest (ROI) around the blob | ||
| x_min = int(max(0, x - radius)) | ||
| x_max = int(min(grey_image.shape[1], x + radius)) | ||
| y_min = int(max(0, y - radius)) | ||
| y_max = int(min(grey_image.shape[0], y + radius)) | ||
|
|
||
| # Create a circular mask for the blob | ||
| mask = np.zeros((y_max - y_min, x_max - x_min), dtype=np.uint8) | ||
| # Circle centered at middle of mask | ||
| cv2.circle(mask, (int(radius), int(radius)), int(radius), 255, -1) | ||
|
|
||
| # Extract the ROI from the grayscale image | ||
| roi = grey_image[y_min:y_max, x_min:x_max] | ||
|
|
||
| # Apply the mask to the ROI | ||
| masked_roi = cv2.bitwise_and(roi, roi, mask=mask) | ||
|
|
||
| # Calculate the mean brightness of the blob | ||
| mean_brightness = cv2.mean(masked_roi, mask=mask)[0] | ||
| # append index into list to keep track of associated keypoint | ||
| average_brightness_list.append((mean_brightness, i)) | ||
|
|
||
| # filter the blobs by their average brightness | ||
| filtered_keypoints = [] | ||
| for brightness, idx in average_brightness_list: | ||
| # Only append associated keypoint if the blob average is bright enough | ||
| if brightness >= self.__config.min_average_brightness_threshold: | ||
| filtered_keypoints.append(keypoints[idx]) | ||
|
|
||
| # A lack of detections is not an error, but should still not be forwarded | ||
| if len(filtered_keypoints) == 0: | ||
| self.__local_logger.info( | ||
| f"{time.time()}: No brightspots detected (after blob average filter)." | ||
|
||
| ) | ||
| return False, None | ||
|
|
||
| # Annotate the image (green circle) with detected keypoints | ||
| image_annotated = cv2.drawKeypoints( | ||
| image, keypoints, None, (0, 255, 0), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS | ||
| image, filtered_keypoints, None, (0, 255, 0), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS | ||
| ) | ||
|
||
|
|
||
| # Process bright spot detection | ||
|
|
@@ -184,7 +241,7 @@ def run( | |
| assert detections is not None | ||
|
|
||
| # Draw bounding boxes around detected keypoints | ||
| for keypoint in keypoints: | ||
| for keypoint in filtered_keypoints: | ||
| x, y = keypoint.pt | ||
| size = keypoint.size | ||
| bounds = np.array([x - size / 2, y - size / 2, x + size / 2, y + size / 2]) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please make this a lot higher, like at least 200, probably 225
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I originally had it at 200, but was failing the unit and the integration tests. It was able to detect the brightspots in the integration test at 100, and passed the unit test at 50. What should I do?