def normalize_in_place(img: ndarray, by="area"): """Normalize a ndarray in place. Only for float type arrays. Args: img: Input ndarray. by : Used normalization method. Available methods are:\n * 'area': normalize to sum one * 'peak': normalize to maximum value * 'l2': normalize by L2 norm of the array """ param_list = ["area", "peak", "l2"] if img.dtype not in [np.float16, np.float32, np.float64]: raise ValueError( "In place normalization only allowed for float arrays.") if by not in param_list: raise ValueError( "Specified argument type is not one of the recognized " f"methods: {param_list}") if by == "area": img /= img.sum() elif by == "peak": img /= img.max() elif by == "l2": img /= np.linalg.norm(img, ord='fro')
def get_demosaiced(img: ndarray, pattern: str = 'GRBG', method: str = 'bilinear') -> ndarray: """Get a demosaiced RGB image from a raw image. This function is a wrapper of the demosaicing functions supplied by the ``color_demosaicing`` package. Args: img: Input image, greyscale, of shape (x,y). pattern: Bayer filter pattern that the input image is modulated with. Patterns are: 'RGGB', 'BGGR', 'GRBG', 'GBRG'. Default: 'GRBG' method: Algorithm used to calculate the demosaiced image.\n * 'bilinear': Simple bilinear interpolation of color values * 'malvar2004': Algorithm introduced by Malvar et. al. [R3]_ * 'menon2007': Algorithm introduced by Menon et. al. [R4]_, Returns: Demosaiced RGB-color image of shape (x,y,3) of dtype :class:`numpy.float64`. References: .. [R3] H.S. Malvar, Li-wei He, and R. Cutler (2004). High-quality linear interpolation for demosaicing of Bayer-patterned color images. IEEE International Conference on Acoustics, Speech, and Signal Processing, Proceedings. (ICASSP '04). DOI: 10.1109/ICASSP.2004.1326587 .. [R4] D. Menon, S. Andriani, G. Calvagno (2007). Demosaicing With Directional Filtering and a posteriori Decision. IEEE Transactions on Image Processing (Volume: 16, Issue: 1) DOI: 10.1109/TIP.2006.884928 """ param_list = ["bilinear", "malvar2004", "menon2007"] # Do demosaicing with specified method if method not in param_list: raise ValueError( f"The specified method {method} is none of the supported " f"methods: {param_list}.") elif method == "bilinear": return demosaicing_CFA_Bayer_bilinear(img.astype(np.float64), pattern=pattern) elif method == "malvar2004": return demosaicing_CFA_Bayer_Malvar2004(img.astype(np.float64), pattern=pattern) elif method == "menon2007": return demosaicing_CFA_Bayer_Menon2007(img.astype(np.float64), pattern=pattern)
def build_model(maze: ndarray, lr=0.001): model = Sequential() model.add(Dense((maze.__sizeof__()), input_shape=(64,))) model.add(PReLU()) model.add(Dense(maze.__sizeof__())) model.add(PReLU()) model.add(Dense(Constants.num_actions)) model.compile(optimizer='adam', loss='mse') return model
def run(self, img: ndarray, road_ellipse: Ellipse, angle: float) -> ndarray: x_center = int(img.shape[1] / 2) if angle > 0: img_debug = cv2.arrowedLine( img.copy(), pt1=(x_center, 50), pt2=(int(x_center + (20 * math.sin(angle * math.pi / 2))), int(50 - (20 * math.cos(angle * math.pi / 2)))), color=(255, 20, 100), thickness=3, tipLength=0.5) else: img_debug = cv2.arrowedLine( img.copy(), pt1=(x_center, 50), pt2=(int(x_center - (20 * math.sin(-1 * angle * math.pi / 2))), int(50 - (20 * math.cos(angle * math.pi / 2)))), color=(255, 20, 100), thickness=3, tipLength=0.5) if not road_ellipse: return img if road_ellipse.axes: reduced_axes = (int(road_ellipse.axes[0] / 5), int(road_ellipse.axes[1] / 5)) else: reduced_axes = (1, 1) green = int(road_ellipse.trust * 255) red = 255 - int(road_ellipse.trust * 255) img_debug = cv2.ellipse(img_debug, center=road_ellipse.center, axes=reduced_axes, angle=road_ellipse.angle, startAngle=0, endAngle=360, color=(20, green, red), thickness=2) img_debug = cv2.circle(img_debug, center=road_ellipse.center, radius=5, color=(255, 0, 0)) img_debug = cv2.putText(img=img_debug, text='{0:.2f}'.format(angle), org=(10, 10), fontFace=cv2.FONT_HERSHEY_PLAIN, fontScale=1, color=(255, 255, 255)) return img_debug
def lasso_hetero_gs(X: ndarray, y: ndarray, lam: ndarray, w_init: ndarray, tol: float, verbose: bool=False) -> ndarray: n, m = X.shape scaler = np.sqrt(np.sum(X ** 2, axis=0)) X = X / scaler w = w_init.copy() if m == 0: return w def subgradient(w, r): return -r @ X + lam * np.sign(w) r = 0 for t in count(): if t % 100 == 0: r = y - X @ w sg = subgradient(w, r) eff_lam = lam * (w == 0) abs_g = abs(soft_threshold(sg, eff_lam)) i = np.argmax(abs_g) if verbose: print("lasso_hetero_gs: step: {}\tgrad: {}".format(t, abs_g[i])) if t % 100 == 99: import pdb pdb.set_trace() if abs_g[i] / np.fabs(w) < tol: break w_i_new = soft_threshold(w[i] + X[:, i] @ r, lam[i]) r += (w[i] - w_i_new) * X[:, i] w[i] = w_i_new return w * scaler
def normalize(img: ndarray, by="area", dtype=np.float64) -> ndarray: """Get a normalized copy of an ndarray, e.g. an image or kernel. The returned array will be a float. Args: img: Input ndarray. by : Used normalization method. Available methods are:\n * 'area': normalize to sum one * 'peak': normalize to maximum value * 'l2': normalize by L2 norm of the array dtype : Output dtype. Either np.float16, np.float32 or np.float64. If input is float, output will be of same word size. Returns: Normalized array of same shape as input array. See Also: Based on :func:`normalize_in_place()`. """ if img.dtype not in [np.float16, np.float32, np.float64]: d_type = dtype else: d_type = img.dtype res = img.copy().astype(d_type) normalize_in_place(res, by=by) return res
def create_combined_fits_file(cls, name: str, data: ndarray, file_type_code: int, image_type_string: str, exposure: float, temperature: float, filter_name: str, binning: int, comment: str): """Write a new FITS file with the given data and name. Create a FITS header in the file by copying the header from a given existing file and adding a given comment""" # Create header header = fits.Header() header["FILTER"] = filter_name header["COMMENT"] = comment header["EXPTIME"] = exposure header["CCD-TEMP"] = temperature header["SET-TEMP"] = temperature header["XBINNING"] = binning header["YBINNING"] = binning header["PICTTYPE"] = file_type_code header["IMAGETYP"] = image_type_string # Create primary HDU data_16_bit = data.round().astype("i2") primary_hdu = fits.PrimaryHDU(data_16_bit, header=header) # Create HDUL hdul = fits.HDUList([primary_hdu]) # Write to file hdul.writeto(name, output_verify="fix", overwrite=True, checksum=True)
def denoise_image_huber(img: ndarray, n_iter: int, w_lambda: Union[ndarray, float] = 0.5) -> ndarray: """Primal-dual algorithm for minimization of TV-Huber-norm-L1-functional. Algotirhm is based on [R1]_. Discrete functional: - TV_Huber-L1: min_x( ||_nabla x||_h + lambda*||x - f||_1 ) Args: img: Input image. n_iter: Number of iterations w_lambda: Weight factor of data term. Pixel-wise weight is possible. Returns: The filtered image of the same shape as the input image. """ L2 = 8.0 alpha = 0.05 gamma = 5 delta = alpha mu = 2 * np.sqrt(gamma * delta) / np.sqrt(L2) tau = mu / 2 / gamma theta = 1 / (1 + mu) sigma = mu / 2 / delta # Iterative primal-dual algorithm u = img.copy() y = _nabla(u) for i in range(n_iter): # Optimize dual variable ( prox_f ) TV y = y + sigma * _nabla(u) # Projection (TV with huber norm) y = _prox_tv(y, 1 + sigma * alpha) / (1 + sigma * alpha) # Optimize primal variable ( prox_g ) u_new = u - tau * _nablaT(y) # l1-norm (shrink) u_new = _prox_l1(u_new, img, w_lambda * tau) # Extrapolate u = u_new + theta * (u_new - u) # Break if max accuracy reached # if (np.abs(u[:]-u_new[:])).sum() < tol: # print(i) # break return u
def _apply_horizon(self, img: ndarray): horizon = int(img.shape[0] * self._config.horizon) if horizon < 1: return img.copy(), img.copy() img_horizon = cv2.rectangle(img=img.copy(), pt1=(0, 0), pt2=(img.shape[1], horizon - 1), thickness=cv2.FILLED, color=(0, )) img_debug = cv2.cvtColor(img.copy(), cv2.COLOR_GRAY2RGB) img_debug = cv2.line(img=img_debug, pt1=(0, horizon - 1), pt2=(img.shape[1], horizon - 1), thickness=2, color=(0, 0, 250)) return img_horizon, img_debug
def add_visual_box(img_orig: ndarray, left: int, top: int, right: int, bottom: int): img = img_orig.copy() max_value = np.max(img) img[top:bottom + 2, left:left + 3, :] = max_value # left img[top:bottom + 2, right - 1:right + 2, :] = max_value # right img[top:top + 3, left:right + 2, :] = max_value # top img[bottom - 1:bottom + 2, left:right + 2, :] = max_value # bottom return img
def denoise_image_tvl1(img: ndarray, n_iter: int, w_lambda: Union[ndarray, float] = 0.5) -> ndarray: """Primal-dual algorithm for minimization of TV-L1-functional. Algotirhm is based on [R1]_. Discrete functional: - TV-L1: min_x( ||_nabla x||_1 + lambda*||x - f||_1 ) Args: img: Input image. n_iter: Number of iterations w_lambda: Weight factor of data term. Pixel-wise weight is possible. Returns: The filtered image of the same shape as the input image. """ u = img.copy() y = _nabla(u) L2 = 8.0 tau = 0.02 sigma = 1.0 / (L2 * tau) theta = 1.0 # Iterative primal-dual algorithm for i in range(n_iter): # Calculate gradient u_grad = _nabla(u) # Optimize dual variable ( prox_f ) TV y = y + sigma * u_grad # Projection y = _prox_tv(y) # Optimize primal variable ( prox_g ) u_new = u - tau * _nablaT(y) # l1-norm (shrink) (TV-l1 denoising) u_new = _prox_l1(u_new, img, w_lambda * tau) # Extrapolate u = u_new + theta * (u_new - u) # Break if max accuracy reached # if (np.abs(u[:]-u_new[:])).sum() < tol: # print(i) # break return u
def draw_image_debug(self, centroid: Centroid, img_gray: ndarray, shape: Shape, value: int) -> ndarray: img_debug = cv2.cvtColor(img_gray.copy(), cv2.COLOR_GRAY2RGB) font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(img_debug, str(value), (20, 20), font, 1, (255, 255, 255), 1, cv2.LINE_AA) cv2.circle(img_debug, centroid, 3, (0, 100, 100), 1) cv2.drawContours(img_debug, shape, -1, (240, 40, 100), 1) self._video_frame = img_debug return img_debug
def run(self, img: ndarray, shapes: List[Shape]) -> ndarray: try: img_debug = img.copy() nb_contours = self._config.number_centroids_to_use colors = self._get_colors_index(nb_contours) for i in range(nb_contours): cv2.drawContours(img_debug, shapes[i:i + 1], -1, colors[i], 2) return img_debug except: logging.exception("Unexpected error") return np.zeros(img.shape)
def calculate_feature(array: ndarray): # assert array.shape[0] > 10 and array.shape[1] > 10 out = [] unit_width, unit_height = array.shape[1] // 10, array.shape[0] // 10 for row in range(10): for column in range(10): out.append(array[row * unit_height:(row + 1) * unit_height + 1, column * unit_width:(column + 1) * unit_width + 1, ].mean()) out.append(array.mean()) return out
def _process_contours(self, img_gray: ndarray) -> (ndarray, List[Centroid]): shapes, centroids = self._contours_detector.process_image(img_gray) img = cv2.cvtColor(img_gray.copy(), cv2.COLOR_GRAY2RGB) for centroid in centroids: cv2.circle(img, centroid, 3, (0, 100, 100), 1) cv2.drawContours(img, shapes, -1, (240, 40, 100), 1) logger.debug("Centroids founds: %s", centroids) return img, shapes, centroids
def run(self, img_gray: ndarray) -> int: try: (_, binary) = cv2.threshold(img_gray.copy(), self._config.centroid_value, 255, 0, cv2.THRESH_BINARY) (shapes, centroids) = self._contours_detector.process_image( img_binarized=binary) if not centroids: return self._config.centroid_value value = img_gray.item((centroids[0][1], centroids[0][0])) self._config.centroid_value = value logger.debug("Threshold value estimate: %s", value) self.draw_image_debug(centroids[0], img_gray, [shapes[0]], value) return value except Exception: import numpy logging.exception("Unexpected error") return self._config.centroid_value
def lasso_hetero(X: ndarray, y: ndarray, lam: ndarray, w_init: ndarray, tol: float, return_obj: bool=False, copy_X: bool=True, max_iter: int=100, verbose: bool=False) -> Union[ndarray, Tuple[ndarray, float]]: n, m = X.shape scale = np.sqrt(np.sum(X ** 2, axis=0)) if copy_X: X = X / scale else: X /= scale lam = lam / scale w = w_init.copy() if m == 0: return w r = y - X @ w gap = np.inf for t in range(max_iter): w_max = 0 d_w_max = 0 for i in range(m): w_i_new = soft_threshold(w[i] + X[:, i] @ r, lam[i]) d_w = w[i] - w_i_new r += d_w * X[:, i] w[i] = w_i_new w_max = max(w_max, np.fabs(w_i_new)) d_w_max = max(d_w_max, np.fabs(d_w)) gap = d_w_max / (w_max + 1e-16) if verbose: print("lasso_hetero_gs: step: {}\tgrad: {}".format(t, gap)) if gap < tol: break else: warnings.warn("not converged after {} iterations; gap: {}".format(max_iter, gap), ConvergenceWarning) ww: ndarray = w / scale if return_obj: obj: float = 0.5 * np.sum(r) + np.sum(lam * np.fabs(ww)) return ww, obj else: return ww
def run(self, img: ndarray) -> ndarray: try: rows, columns, channel = np.shape(img) middle = int(columns / 2) mask = np.zeros(img.shape, np.uint8) central_zone_delta = int( ((columns / 100) * self._config.central_zone_percent) / 2) # Draw safe zone cv2.rectangle(img=mask, pt1=(middle - central_zone_delta, 0), pt2=(middle + central_zone_delta, rows), color=(0, 255, 0), thickness=cv2.FILLED) out_zone_delta = int( ((columns / 100) * self._config.out_zone_percent) / 2) # Draw dangerous zone cv2.rectangle(img=mask, pt1=(0, 0), pt2=(out_zone_delta, rows), color=(255, 0, 0), thickness=cv2.FILLED) cv2.rectangle(img=mask, pt1=(columns - out_zone_delta, 0), pt2=(columns, rows), color=(255, 0, 0), thickness=cv2.FILLED) # Apply mask img_debug = cv2.addWeighted(src1=img.copy(), alpha=0.7, src2=mask, beta=0.3, gamma=0) # Draw central axes img_debug = cv2.line(img=img_debug, pt1=(middle, 0), pt2=(middle, img.shape[1]), color=(0, 0, 255), thickness=2) return img_debug except: logging.exception("Unexpected error") return np.zeros(img.shape)
def create_combined_fits_file(cls, name: str, data: ndarray, file_type_code: int, image_type_string: str, exposure: float, temperature: float, filter_name: str, binning: int, comment: str): """ Write a new FITS file with the given data and name. Create a FITS header in the file by copying the header from a given existing file and adding a given comment :param name: File name :param data: 2-dimensional array of pixel values, the file contents :param file_type_code: What kind of FITS image file is this (dark, bias, flat, etc.)? :param image_type_string: String for FITS filel "IMGTYP" parameter :param exposure: Exposure time in seconds :param temperature: Temperature in degrees if known, else 0 :param filter_name: Name of filter if known :param binning: Binning value of this frame (1, 2, 3, or 4) :param comment: General comment describing this file """ # Create header header = fits.Header() header["FILTER"] = filter_name header["COMMENT"] = comment header["EXPTIME"] = exposure header["CCD-TEMP"] = temperature header["SET-TEMP"] = temperature header["XBINNING"] = binning header["YBINNING"] = binning header["PICTTYPE"] = file_type_code header["IMAGETYP"] = image_type_string # Create primary HDU data_16_bit = data.round().astype("i2") primary_hdu = fits.PrimaryHDU(data_16_bit, header=header) # Create HDUL hdul = fits.HDUList([primary_hdu]) # Write to file hdul.writeto(name, output_verify="fix", overwrite=True, checksum=True)
def compute(img: ndarray, k_size: int = 3) -> ndarray: im = img.astype(np.float) width, height, c = im.shape if c > 1: img = 0.2126 * im[:, :, 0] + 0.7152 * im[:, :, 1] + 0.0722 * im[:, :, 2] else: img = im assert k_size == 3 or k_size == 5 if k_size == 3: kh = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]], dtype=np.float) kv = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]], dtype=np.float) else: kh = np.array( [ [-1, -2, 0, 2, 1], [-4, -8, 0, 8, 4], [-6, -12, 0, 12, 6], [-4, -8, 0, 8, 4], [-1, -2, 0, 2, 1], ], dtype=np.float, ) kv = np.array( [ [1, 4, 6, 4, 1], [2, 8, 12, 8, 2], [0, 0, 0, 0, 0], [-2, -8, -12, -8, -2], [-1, -4, -6, -4, -1], ], dtype=np.float, ) gx = convolve2d(img, kh, mode="same", boundary="symm") gy = convolve2d(img, kv, mode="same", boundary="symm") g = np.sqrt(gx * gx + gy * gy) g *= 255.0 / np.max(g) return g
def get_weights(edges_with_grouping_orig: ndarray, groups_members: ndarray, affinities: ndarray, left: int, top: int, right: int, bottom: int) -> List[float]: edges_with_grouping = edges_with_grouping_orig.copy() edges_with_grouping[top:bottom, left:right, 1] = -1 groups_not_in_box = np.unique(edges_with_grouping[:, :, 1]) def calculate_weight(affs: ndarray, group_id: int): def generate_paths(group_len: int, length: int): paths: list = [[group_id]] for _ in range(length): paths = [ p + [new_group_id] for p in paths for new_group_id in range(group_len) if new_group_id != p[-1] and affs[new_group_id, p[-1]] > 0.0 and not (new_group_id in p) ] return list(filter(lambda p: p[-1] in groups_not_in_box, paths)) if group_id in groups_not_in_box: return 0.0 max_path_length = 10 max_chained_affinity = 0.0 for i in range(max_path_length): for path in generate_paths(len(groups_members), i): path1 = path[0:-1] path2 = path[1:] adjacent_path = zip(path1, path2) affinity_path = map(lambda v12: affinities[v12[0], v12[1]], adjacent_path) affinity_reduced = reduce(lambda a1, a2: a1 * a2, affinity_path) max_chained_affinity = max(affinity_reduced, max_chained_affinity) return 1.0 - max_chained_affinity w = [ calculate_weight(affinities, group_id) for group_id in range(len(groups_members)) ] return w
def add_encoding(self, encoding: ndarray, associate_id: int, person: bool = False, image: bool = False) -> int: """ Adds an encoding to the database. They must be associated to an existing person or image. :param encoding: The encoding's payload :param associate_id: The id of the image or person this is associated with :param person: Is this associated to a person? :param image: Is this associated to an image? :return: Id of the newly-created encoding """ # Insert sql = "INSERT INTO Encoding (encoding) VALUES (?)" encoding_bytes = encoding.tobytes() dbresponse = self.connection.execute(sql, [encoding_bytes]) dbid = dbresponse.lastrowid self.get_or_associate_encoding(dbid, associate_id, person, image) return dbid
def kernel(self, seq: ndarray, table: ndarray): # def max_score(s1, s2): # if s1 >= s2: # return s1 # else: # return s2 # def match(b1, b2): return b1 + b2 == 3 table_flattened = table.ravel() # scop begin for i in range(self.N): diag_i = np.arange(0, self.N - i - 1) diag_j = np.arange(i + 1, self.N) slice_W = slice(i, i + self.N * (self.N - i - 1), self.N + 1) slice_center = slice(i + 1, i + 1 + self.N * (self.N - i - 1), self.N + 1) slice_SW = slice(i + self.N, i + self.N * (self.N - i), self.N + 1) slice_S = slice(i + 1 + self.N, i + 1 + self.N * (self.N - i), self.N + 1) table_flattened[slice_center] = np.maximum( table_flattened[slice_center], table_flattened[slice_W]) table_flattened[slice_center] = np.maximum( table_flattened[slice_center], table_flattened[slice_S]) if i > 0: table_flattened[slice_center] = np.maximum( table_flattened[slice_center], table_flattened[slice_SW] + match(seq[0:self.N - 1 - i], seq[i + 1:self.N])) else: table_flattened[slice_center] = np.maximum( table_flattened[slice_center], table_flattened[slice_SW]) if i < self.N - 1: table_flattened[slice_center] = np.maximum( table_flattened[slice_center], np.max(table[0:self.N - i - 1, i + 1:self.N], axis=0))
def denoise_image_rof(img: ndarray, n_iter: int, w_lambda: Union[ndarray, float] = 5) -> ndarray: """Primal-dual algorithm for minimization of ROF-functional (TV-L2). Fast form of primal-dual algorithm (faster than standard). Algotirhm is based on [R1]_. Discrete functional: - ROF: min_x( ||_nabla x||_1 + 0.5*lambda*(||x - f||_1)**2 ) Args: img: Input image. n_iter: Number of iterations w_lambda: Weight factor of data term. Pixel-wise weight is possible. Returns: The filtered image of the same shape as the input image. References: .. [R1] Chambolle, Antonin; Pock, Thomas (2011): A First-Order Primal-Dual Algorithm for Convex Problems with Applications to Imaging. In: Journal of Mathematical Imaging and Vision 40 (1) """ u = img.copy() y = _nabla(u) L2 = 8 tau = 0.02 sigma = 1.0 / (L2 * tau) gamma = 0.35 * w_lambda for i in range(n_iter): # Calculate gradient u_grad = _nabla(u) # Optimize dual variable ( prox_f ) y = y + sigma * u_grad # Projection y = _prox_tv(y) # Optimize primal variable ( prox_g ) u_new = u - tau * _nablaT(y) # l2-norm (ROF denoising) u_new = _prox_l2(u_new, img, w_lambda * tau) # Optimize step-size (faster convergence) theta = 1 / np.sqrt(1 + 2 * gamma * tau) tau = theta * tau sigma = sigma / theta # Extrapolate u = u_new + theta * (u_new - u) # Break if max accuracy reached # if (np.abs(u[:]-u_new[:])).sum() < tol: # print(i) # break return u
def _display_bbs(img: ndarray, bbs: List[Tuple[Point, Size2D]]) -> ndarray: _img = img.copy() for bb in bbs: _img = draw_bbox_on_image(_img, bb, color=(0, 255, 0)) return _img
def _blank_image(image: ndarray) -> ndarray: image = np.zeros((image.shape[0], image.shape[1]), dtype='uint8') image.fill(255) return image
def conv2d(data_in: ndarray, kernel: ndarray, stride: int = 1): """ Perform a 2D convolution over a batch of tensors. This is equivalent to output[b, i, j, k] = sum_{di, dj, q} input[b, strides[1] * i + di, strides[2] * j + dj, q] * filter[di, dj, q, k] :param data_in: Input data tensor with shape [batch, height, width, channels_in] :param kernel: Convolution kernel tensor with shape [kernel_height, kernel_width, channels_in, channels_out] :param stride: Integer for the step width :return: Tensor with shape [batch, height/stride, width/stride, channels_out] """ # Obtain shapes fh, fw, kin_ch, kout_ch = kernel.shape batch, in_h, in_w, in_ch = data_in.shape if kin_ch != in_ch: raise ValueError("Input channel mismatch") # Check if the filter has an uneven width assert (1 == fh % 2) assert (1 == fw % 2) # Find the midpoint of the filter. This only works for odd filter sizes fh2 = int((fh - 1) / 2) fw2 = int((fw - 1) / 2) # Given an input tensor of shape [batch, in_height, in_width, in_channels] and a filter / kernel tensor of # shape [filter_height, filter_width, in_channels, out_channels], this op performs the following: # # 1) Flattens the filter to a 2-D matrix with shape [filter_height * filter_width * in_channels, # output_channels]. # # 2) Extracts image patches from the input tensor to form a virtual tensor of shape [batch, # out_height, out_width, filter_height * filter_width * in_channels]. # # 3) For each patch, right-multiplies the # filter matrix and the image patch vector if kernel.dtype.kind in 'ui': # check if datatype is unsigned or integer out = np.zeros(shape=[batch, in_h, in_w, kout_ch], dtype=np.int32) else: out = np.zeros(shape=[batch, in_h, in_w, kout_ch], dtype=data_in.dtype) # pad input in_padded = np.pad(data_in, ((0, 0), (fh2, fh2), (fw2, fw2), (0, 0)), 'constant', constant_values=(0, 0)) # in_padded = np.pad(data_in, ((0, 0), (30, 30), (30, 30), (0, 0)), 'constant', constant_values=(0, 0)) # img = np.squeeze(in_padded) # fig, ax = plt.subplots() # _im = ax.imshow(img, cmap='gray') # fig.colorbar(_im) # plt.show() # kflat = np.reshape(kernel, newshape=(-1, kout_ch)) # vout = np.zeros(shape=(batch, in_h, in_w, fh * fw * in_ch)) # create virtual out # # for b in range(batch): # for i in range(in_h): # for j in range(in_w): # vout[b, i, j, :] = np.reshape(in_padded[b, i:i+fh, j:j+fw, :], newshape=(-1)) # # out = np.dot(vout, kflat) # output[b, i, j, k] = # sum_{di, dj, q} input[b, strides[1] * i + di, strides[2] * j + dj, q] * # filter[di, dj, q, k] for b in range(batch): for k in range(kout_ch): # k = kernel[:, :, q, k] # 2d kernel # Perform convolution i_out, j_out = 0, 0 for i in range(0, in_h, stride): for j in range(0, in_w, stride): patch = in_padded[b, i:i + fh, j:j + fw, :] # 3d tensor 3x3x16 if kernel.dtype.kind in 'ui': # check if datatype is unsigned or integer patch16 = patch.astype(np.int16) kernel16 = kernel.astype(np.int16) temp = patch16 * kernel16[:, :, :, k] temp = temp.flatten().astype(np.int64) # patch_sum = np.sum(patch * kernel[:, :, :, k], axis=(0, 1, 2)) # sum along all axis # min_value = np.iinfo(kernel.dtype).min # max_value = np.iinfo(kernel.dtype).max patch_sum = np.sum(temp) out[b, i_out, j_out, k] = patch_sum else: # patch_sum is always int64 patch_sum = np.sum(patch * kernel[:, :, :, k], axis=(0, 1, 2)) # sum along all axis out[b, i_out, j_out, k] = patch_sum j_out += 1 j_out = 0 i_out += 1 return out
def calculate_metrics(confusion_matrix: ndarray) -> tuple: tn, fp, fn, tp = confusion_matrix.ravel() accuracy = (tp + tn) / sum([tn, fp, fn, tp]) recall = tp / (tp + fn) precision = tp / (tp + fp) return accuracy, recall, precision
def right_generalized_inverse_jacobian(jacobian: ndarray) -> ndarray: jacobian_t = jacobian.transpose() try: return jacobian_t @ inv(jacobian @ jacobian_t) except TypeError: raise ValueError(jacobian @ jacobian_t)
def get_gradients(im: ndarray, method='sobel', **kwargs) -> Tuple[ndarray, ndarray]: """Get the gradients of a 2D-image using different methods. Args: im: Input image of shape (x, y). Only monochromatic images are supported here. method: Used method for gradient calculation. Possible values are: * 'scharr': Scharr filter. * 'sobel': Sobel filter. * 'dog': Difference of Gaussians. * 'gradient': Numpy's ``gradient()`` method Returns: Tuple (gx, gy). Gradient gx, gy in x- and y-direction, respectively. """ im = im.squeeze() if im.ndim != 2: raise ValueError( "Gradient calculation only works on 2D images right now. " "For multi-dimensional arrays, use numpy's gradient() instead.") x, y = im.shape # Get image gradients param_list = ["scharr", "sobel", "dog", "gradient"] method = method.lower() if method not in param_list: raise ValueError( f"Specified method '{method}' is not one of the recognized " f"methods: {param_list}") if method == 'scharr': h = np.array([[3, 10, 3], [0, 0, 0], [-3, -10, -3]]) grad_x = convolve(im, h.T) grad_y = convolve(im, h) elif method == 'sobel': h = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]]) grad_x = convolve(im, h.T) grad_y = convolve(im, h) elif method == 'dog': if not 'sigma' in kwargs: sigma_1 = min(x, y) / 800 else: sigma_1 = kwargs['sigma'] sigma_2 = 1.6 * sigma_1 grad_x = gaussian_filter(im, [sigma_1, 0]) - gaussian_filter( im, [sigma_2, 0]) grad_y = gaussian_filter(im, [0, sigma_1]) - gaussian_filter( im, [0, sigma_2]) elif method == 'gradient': grad_y, grad_x = np.gradient(im) # central differences return grad_x, grad_y