def get2d_histogram(x, y, value_range, nbins=100, dtype=tf.dtypes.int32): """ Bins x, y coordinates of points onto simple square 2d histogram Given the tensor x and y: x: x coordinates of points y: y coordinates of points this operation returns a rank 2 `Tensor` representing the indices of a histogram into which each element of `values` would be binned. The bins are equal width and determined by the arguments `value_range` and `nbins`. Args: x: Numeric `Tensor`. y: Numeric `Tensor`. value_range[0] lims for x value_range[1] lims for y nbins: Scalar `int32 Tensor`. Number of histogram bins. dtype: dtype for returned histogram. """ x_range = value_range[0] y_range = value_range[1] histy_bins = tf.histogram_fixed_width_bins(y, y_range, nbins=nbins, dtype=dtype) H = tf.map_fn( lambda i: tf.histogram_fixed_width( x[histy_bins == i], x_range, nbins=nbins), tf.range(nbins)) return H # Matrix!
def scale_channel(im, c): """Scale the data in the channel to implement equalize.""" im = tf.cast(im[:, :, c], tf.int32) # Compute the histogram of the image channel. histo = tf.histogram_fixed_width(im, [0, 255], nbins=256) # For the purposes of computing the step, filter out the nonzeros. nonzero = tf.where(tf.not_equal(histo, 0)) nonzero_histo = tf.reshape(tf.gather(histo, nonzero), [-1]) step = (tf.reduce_sum(nonzero_histo) - nonzero_histo[-1]) // 255 def build_lut(histo, step): # Compute the cumulative sum, shifting by step // 2 # and then normalization by step. lut = (tf.cumsum(histo) + (step // 2)) // step # Shift lut, prepending with 0. lut = tf.concat([[0], lut[:-1]], 0) # Clip the counts to be in range. This is done # in the C code for image.point. return tf.clip_by_value(lut, 0, 255) # If step is zero, return the original image. Otherwise, build # lut from the full histogram and step and then index from it. result = tf.cond(tf.equal(step, 0), lambda: im, lambda: tf.gather(build_lut(histo, step), im)) return tf.cast(result, tf.uint8)
def tf_batch_histogram(values, value_range, axis, nbins=100, dtype=tf.int32, use_map=True): """ Computes histogram with fixed width considering batch dimensions :param values: Numeric `Tensor` containing the values for histogram computation. :param value_range: Shape [2] `Tensor` of same `dtype` as `values`. values <= value_range[0] will be mapped to hist[0], values >= value_range[1] will be mapped to hist[-1]. :param axis: Number of batch dimensions. First axis to apply histogram computation to. :param nbins: Scalar `int32 Tensor`. Number of histogram bins. :param dtype: dtype for returned histogram, can be either tf.int32 or tf.int64. :return: histogram with batch dimensions. """ # Get shape values_shape = tf.shape(values) batch_dim = values_shape[:axis] rest_dim = values_shape[axis:] num_batch = tf.reduce_prod(batch_dim) if use_map: values_reshaped = tf.reshape(values, tf.concat([[num_batch], rest_dim], 0)) hist = tf.map_fn(lambda x: tf.histogram_fixed_width(x, value_range, nbins=nbins, dtype=dtype), values_reshaped, dtype=dtype, parallel_iterations=64) else: # Normalize values_float = tf.cast(values, tf.float32) value_range_float = tf.cast(value_range, tf.float32) # Clip values values_norm = (values_float - value_range_float[0]) / (value_range_float[1] - value_range_float[0]) values_clip1 = tf.maximum(values_norm, 0.5 / tf.cast(nbins, tf.float32)) values_clip2 = tf.minimum(values_clip1, 1.0 - 0.5 / tf.cast(nbins, tf.float32)) # Shift values values_shift = values_clip2 + tf.reshape(tf.range(tf.cast(num_batch, tf.float32), dtype=tf.float32), tf.concat([batch_dim, tf.ones(tf.size(rest_dim), tf.int32)], 0)) # Get histogram hist = tf.histogram_fixed_width(values_shift, [0., tf.cast(num_batch, tf.float32)], nbins=num_batch * nbins, dtype=dtype) return tf.reshape(hist, tf.concat([batch_dim, [nbins]], 0))
def contrast(image, factor): """Equivalent of PIL Contrast.""" degenerate = tf.image.rgb_to_grayscale(image) # Cast before calling tf.histogram. degenerate = tf.cast(degenerate, tf.int32) # Compute the grayscale histogram, then compute the mean pixel value, # and create a constant image size of that value. Use that as the # blending degenerate target of the original image. hist = tf.histogram_fixed_width(degenerate, [0, 255], nbins=256) mean = tf.reduce_sum(tf.cast(hist, tf.float32)) / 256.0 degenerate = tf.ones_like(degenerate, dtype=tf.float32) * mean degenerate = tf.clip_by_value(degenerate, 0.0, 255.0) degenerate = tf.image.grayscale_to_rgb(tf.cast(degenerate, tf.uint8)) return blend(degenerate, image, factor)
def get_jh(x, y, value_range, nbins): dtype = tf.dtypes.int32 x_range = value_range[0] y_range = value_range[1] histy_bins = tf.histogram_fixed_width_bins(y, y_range, nbins=nbins, dtype=dtype) def masking_info(tf_val): return tf.math.equal(histy_bins, tf_val) H = tf.map_fn( lambda i: tf.histogram_fixed_width( x[masking_info(i)], x_range, nbins=nbins), tf.range(nbins)) return H
def idx2csr(indices, rows, columns): """Convert index format meta-data to compressed sparse row format. Args: indices: Tensor, the linear indices for the sparse matrix. rows: Tensor, the number of rows in the sparse matrix. columns: Tensor, the number of columns in the sparse matrix. Returns: row_indices: Tensor, the row indices sorted by size. row_offset: Tensor, the offsets for each row in the sparse matrix. column_indices: Tensor, the column indices for each nonzero in the matrix. """ # Calculate the length of each row by histogramming the indices. row_lengths = tf.histogram_fixed_width(indices, [0, rows * columns], nbins=rows) row_offsets = tf.concat([[0], tf.cumsum(row_lengths)], axis=0) row_indices = tf.argsort(row_lengths, direction="DESCENDING") column_indices = tf.mod(indices, columns) return row_indices, row_offsets, column_indices
def add_single_image_info(self, image_id, eval_dict): groundtruth_boxes = eval_dict[ standard_fields.InputDataFields.groundtruth_boxes] groundtruth_classes = eval_dict[ standard_fields.InputDataFields.groundtruth_classes] detection_boxes = eval_dict[ standard_fields.DetectionResultFields.detection_boxes] detection_scores = eval_dict[ standard_fields.DetectionResultFields.detection_scores] detection_classes = eval_dict[ standard_fields.DetectionResultFields.detection_classes] groundtruth_has_rotation = groundtruth_classes > 1 groundtruth_boxes_with_rotation = groundtruth_boxes[ groundtruth_has_rotation] #ensure classes are both not 'dot' class, so they have a meaningful rotation value detection_within_score = detection_scores > self._score_threshold detection_class_has_rotation = detection_classes > 1 detection_has_rotation_and_score = tf.logical_and( detection_within_score, detection_class_has_rotation) detection_boxes_within_score = detection_boxes[ detection_has_rotation_and_score] detection_classes_within_score = detection_classes[ detection_has_rotation_and_score] gt_boxlist = box_list.BoxList( tf.convert_to_tensor(groundtruth_boxes_with_rotation)) det_boxlist = box_list.BoxList( tf.convert_to_tensor(detection_boxes_within_score)) detection_y_rotation_angles = eval_dict[ additional_fields.DetectionResultFields.y_rotation_angles] groundtruth_y_rotation_angles = eval_dict[ additional_fields.GroundtruthResultFields.y_rotation_angles] detection_y_rotation_angles_within_score = detection_y_rotation_angles[ detection_has_rotation_and_score] for iou_threshold, assigner in self._iou_thresholds_and_assigners: cls_targets, cls_weights, reg_targets, reg_weights, match = assigner.assign( det_boxlist, gt_boxlist) fg_detections = match >= 0 fg_detection_boxes = detection_boxes_within_score[fg_detections, :] fg_matches = match[fg_detections] fg_matches_argsort = tf.argsort(fg_matches) fg_matches_sorted = tf.gather(fg_matches, fg_matches_argsort) gt_match_indices, fg_match_sorted_indices_with_repeats, fg_match_sorted_indices_counts = tf.unique_with_counts( fg_matches_sorted) fg_match_sorted_indices_no_repeats = tf.cumsum( tf.pad(fg_match_sorted_indices_counts, [[1, 0]]))[:-1] fg_match_indices_no_repeats = tf.gather( fg_matches_argsort, fg_match_sorted_indices_no_repeats) def get_matches_and_angle_difference(fg_match_idx_tensor, gt_match_idx_tensor): if debug_get_matching_boxes: gt_matching_detection_boxes = tf.gather( groundtruth_boxes_with_rotation, gt_match_idx_tensor, axis=0) fg_matching_detection_boxes = tf.gather( fg_detection_boxes, fg_match_idx_tensor, axis=0) pass fg_matching_detection_y_rot_angles = tf.gather( detection_y_rotation_angles_within_score, fg_match_idx_tensor, axis=0) groundtruth_y_rotation_angles_matches = tf.gather( groundtruth_y_rotation_angles, gt_match_idx_tensor, axis=0) groundtruth_has_y_rot = tf.math.logical_not( tf.math.equal(groundtruth_y_rotation_angles_matches, 0)) groundtruth_existant_y_rot_angle = groundtruth_y_rotation_angles_matches[ groundtruth_has_y_rot] detection_existant_y_rot_angle = fg_matching_detection_y_rot_angles[ groundtruth_has_y_rot] angle_diff = detection_existant_y_rot_angle - groundtruth_existant_y_rot_angle angle_diff_unwrapped = tf.math.atan2(tf.math.sin(angle_diff), tf.math.cos(angle_diff)) angle_diff_abs = tf.math.abs(angle_diff_unwrapped) n_angle_matches = len(angle_diff) return n_angle_matches, angle_diff_abs num_angle_matches, abs_angle_differences = get_matches_and_angle_difference( fg_match_indices_no_repeats, gt_match_indices) angle_diff_sum_square = tf.reduce_sum( tf.math.square(abs_angle_differences * 180 / np.pi)) match_angle_diff_histogram = tf.histogram_fixed_width( abs_angle_differences * 180 / np.pi, self._histogram_range, nbins=self._num_angle_bins, dtype=tf.dtypes.int32) self.total_num_angle_matches[iou_threshold] += num_angle_matches self.total_angle_diff_sum_squared[ iou_threshold] += angle_diff_sum_square self.angle_histograms[iou_threshold] += match_angle_diff_histogram