diff --git a/core/leras/ops/__init__.py b/core/leras/ops/__init__.py index 0cf23a8..7107ec4 100644 --- a/core/leras/ops/__init__.py +++ b/core/leras/ops/__init__.py @@ -212,7 +212,9 @@ def gaussian_blur(input, radius=2.0): return np.exp(-(float(x) - float(mu)) ** 2 / (2 * sigma ** 2)) def make_kernel(sigma): - kernel_size = max(3, int(2 * 2 * sigma + 1)) + kernel_size = max(3, int(2 * 2 * sigma)) + if kernel_size % 2 == 0: + kernel_size += 1 mean = np.floor(0.5 * kernel_size) kernel_1d = np.array([gaussian(x, mean, sigma) for x in range(kernel_size)]) np_kernel = np.outer(kernel_1d, kernel_1d).astype(np.float32) @@ -402,4 +404,70 @@ def tf_suppress_lower_mean(t, eps=0.00001): q = tf.clip_by_value(q-t_mean_eps, 0, eps) q = q * (t/eps) return q -""" \ No newline at end of file +""" + + + +def _get_pixel_value(img, x, y): + shape = tf.shape(x) + batch_size = shape[0] + height = shape[1] + width = shape[2] + + batch_idx = tf.range(0, batch_size) + batch_idx = tf.reshape(batch_idx, (batch_size, 1, 1)) + b = tf.tile(batch_idx, (1, height, width)) + + indices = tf.stack([b, y, x], 3) + + return tf.gather_nd(img, indices) + +def bilinear_sampler(img, x, y): + H = tf.shape(img)[1] + W = tf.shape(img)[2] + H_MAX = tf.cast(H - 1, tf.int32) + W_MAX = tf.cast(W - 1, tf.int32) + + # grab 4 nearest corner points for each (x_i, y_i) + x0 = tf.cast(tf.floor(x), tf.int32) + x1 = x0 + 1 + y0 = tf.cast(tf.floor(y), tf.int32) + y1 = y0 + 1 + + # clip to range [0, H-1/W-1] to not violate img boundaries + x0 = tf.clip_by_value(x0, 0, W_MAX) + x1 = tf.clip_by_value(x1, 0, W_MAX) + y0 = tf.clip_by_value(y0, 0, H_MAX) + y1 = tf.clip_by_value(y1, 0, H_MAX) + + # get pixel value at corner coords + Ia = _get_pixel_value(img, x0, y0) + Ib = _get_pixel_value(img, x0, y1) + Ic = _get_pixel_value(img, x1, y0) + Id = _get_pixel_value(img, x1, y1) + + # recast as float for delta calculation + x0 = tf.cast(x0, tf.float32) + x1 = tf.cast(x1, tf.float32) + y0 = tf.cast(y0, tf.float32) + y1 = tf.cast(y1, tf.float32) + + # calculate deltas + wa = (x1-x) * (y1-y) + wb = (x1-x) * (y-y0) + wc = (x-x0) * (y1-y) + wd = (x-x0) * (y-y0) + + # add dimension for addition + wa = tf.expand_dims(wa, axis=3) + wb = tf.expand_dims(wb, axis=3) + wc = tf.expand_dims(wc, axis=3) + wd = tf.expand_dims(wd, axis=3) + + # compute output + out = tf.add_n([wa*Ia, wb*Ib, wc*Ic, wd*Id]) + + return out + +nn.bilinear_sampler = bilinear_sampler +