|
29 | 29 | import logging |
30 | 30 |
|
31 | 31 | import numpy as np |
| 32 | +import cv2 as cv |
32 | 33 |
|
33 | 34 |
|
34 | 35 | def mean_std_normalize(image, epsilon=1e-07): |
@@ -91,3 +92,51 @@ def min_max_normalize(image, clip=False): |
91 | 92 |
|
92 | 93 | image[batch, ..., channel] = normal_image |
93 | 94 | return image |
| 95 | + |
| 96 | + |
| 97 | +def blurred_laplacian_of_gaussian(images, clip=False): |
| 98 | + """ |
| 99 | + Applies a combination of bilateral filtering, Gaussian blurring, and Laplacian of Gaussian. |
| 100 | + First denoises the images using a bilateral filter, then applies a Gaussian blur, |
| 101 | + and finally enhances spots using the Laplacian of Gaussian method. |
| 102 | + |
| 103 | + Currently, this function only supports single-channel images. |
| 104 | + |
| 105 | + Args: |
| 106 | + image (numpy.array): 4D numpy array of image data. |
| 107 | + clip (boolean): Defaults to false. Determines if pixel |
| 108 | + values are clipped by percentile. |
| 109 | +
|
| 110 | + Returns: |
| 111 | + numpy.array: preprocessed image data. |
| 112 | + """ |
| 113 | + # Combination: Bilateral denoising to preserve edges, then Laplacian of Gaussian for spot enhancement |
| 114 | + processed_images_list = [] |
| 115 | + |
| 116 | + if not np.issubdtype(images.dtype, np.floating): |
| 117 | + logging.info('Converting image dtype to float') |
| 118 | + |
| 119 | + if not len(np.shape(images)) == 4: |
| 120 | + raise ValueError('Image must be 4D, input image shape was' |
| 121 | + ' {}.'.format(np.shape(images))) |
| 122 | + |
| 123 | + for img_array in images: |
| 124 | + img = np.copy(img_array) |
| 125 | + |
| 126 | + if clip: |
| 127 | + img = np.clip(img, a_min=np.percentile(img, 0.01), a_max=np.percentile(img, 99.9)) |
| 128 | + |
| 129 | + if img.ndim == 3 and img.shape[2] == 1: |
| 130 | + img = img[:, :, 0] |
| 131 | + img_float32 = cv.normalize(img, None, 0, 1, cv.NORM_MINMAX).astype(np.float32) |
| 132 | + # Bilateral filter to denoise while maintaining spot edges |
| 133 | + bilateral = cv.bilateralFilter(img_float32, d=5, sigmaColor=0.09, sigmaSpace=9) |
| 134 | + # Slight Gaussian blur before Laplacian |
| 135 | + gauss = cv.GaussianBlur(bilateral, (3,3), 0) |
| 136 | + lap = cv.Laplacian(gauss, cv.CV_32F, ksize=3) |
| 137 | + abs_lap = np.abs(lap) |
| 138 | + lap_norm = cv.normalize(abs_lap, None, 0, 1, cv.NORM_MINMAX).astype(np.float32) |
| 139 | + if img_array.ndim == 3 and img_array.shape[2] == 1: |
| 140 | + lap_norm = lap_norm[:, :, np.newaxis] |
| 141 | + processed_images_list.append(lap_norm) |
| 142 | + return np.array(processed_images_list, dtype=np.float32) |
0 commit comments