eric-yyjau/pytorch-superpoint

Difference between function 'sample_homography' and 'sample_homography_np'

Closed this issue · 4 comments

The first parameter 'shape' is a constant, i.e., np.array([2, 2]) for 'sample_homography_np', while for 'smaple_homography', it is the shape of image. So could you please give me more detailed explanation about these two functions ?

If I remember correctly, the two should have no differences.

def sample_homography_np(

I was basically rewriting the function in order to be used in pytorch.

Let me know if you have further questions.

I'm doing the same thing,and i have rewrite your function as follows (little differen),
def sample_homography_np(shape, perspective=True, scaling=True, rotation=True, translation=True,
n_scales=5, n_angles=25, scaling_amplitude=0.1, perspective_amplitude_x=0.1,
perspective_amplitude_y=0.1, patch_ratio=0.5, max_angle=pi/2,
allow_artifacts=False, translation_overflow=0.):
"""
------------------m1----------------------
import tensorflow as tf
import matplotlib.pyplot as plt

c = tf.truncated_normal(shape=[10000, ], mean=0, stddev=0.05)

with tf.Session() as sess:
    sess.run(c)
    data = c.eval()
plt.hist(x=data, bins=100, color='steelblue', edgecolor='black')
plt.show()
------------------m2----------------------
import scipy.stats as stats

mu, sigma = 0, 0.05
lower, upper = mu - 2 * sigma, mu + 2 * sigma

X = stats.truncnorm(
    (lower - mu) / sigma, (upper - mu) / sigma, loc=mu, scale=sigma)

plt.hist(X.rvs(10000), bins=100, color='red', edgecolor='black')
plt.show()
------------------------------------------
c1==c2
"""

std_trunc = 2

# Corners of the input patch
margin = (1 - patch_ratio) / 2
pts1 = margin + np.array([[0, 0], [0, patch_ratio],
                             [patch_ratio, patch_ratio], [patch_ratio, 0]])
pts2 = pts1.copy()

# Random perspective and affine perturbations
if perspective:
    if not allow_artifacts:
        perspective_amplitude_x = min(perspective_amplitude_x, margin)
        perspective_amplitude_y = min(perspective_amplitude_y, margin)
    perspective_displacement = truncnorm(-std_trunc, std_trunc, loc=0., scale=perspective_amplitude_y/2).rvs(1)
    h_displacement_left = truncnorm(-std_trunc, std_trunc, loc=0., scale=perspective_amplitude_x/2).rvs(1)
    h_displacement_right = truncnorm(-std_trunc, std_trunc, loc=0., scale=perspective_amplitude_x/2).rvs(1)
    pts2 += np.array([[h_displacement_left, perspective_displacement],
                      [h_displacement_left, -perspective_displacement],
                      [h_displacement_right, perspective_displacement],
                      [h_displacement_right, -perspective_displacement]]).squeeze()

# Random scaling
# sample several scales, check collision with borders, randomly pick a valid one
if scaling:
    scales = truncnorm(-std_trunc, std_trunc, loc=1, scale=scaling_amplitude/2).rvs(n_scales)
    scales = np.concatenate((np.array([1]), scales), axis=0)

    center = np.mean(pts2, axis=0, keepdims=True)
    scaled = (pts2 - center)[np.newaxis, :, :] * scales[:, np.newaxis, np.newaxis] + center
    if allow_artifacts:
        valid = np.arange(n_scales)  # all scales are valid except scale=1
    else:
        valid = (scaled >= 0.) * (scaled < 1.)
        valid = valid.prod(axis=1).prod(axis=1)
        valid = np.where(valid)[0]
    idx = valid[np.random.randint(valid.shape[0], size=1)].squeeze().astype(int)
    pts2 = scaled[idx,:,:]

# Random translation
if translation:
    t_min, t_max = np.min(pts2, axis=0), np.min(1 - pts2, axis=0)
    if allow_artifacts:
        t_min += translation_overflow
        t_max += translation_overflow
    pts2 += np.array([uniform(-t_min[0], t_max[0],1), uniform(-t_min[1], t_max[1], 1)]).T

# Random rotation
# sample several rotations, check collision with borders, randomly pick a valid one
if rotation:
    angles = np.linspace(-max_angle, max_angle, num=n_angles)
    angles = np.concatenate((np.array([0.]),angles), axis=0)  # in case no rotation is valid
    center = np.mean(pts2, axis=0, keepdims=True)
    rot_mat = np.reshape(np.stack([np.cos(angles), -np.sin(angles), np.sin(angles),
                                   np.cos(angles)], axis=1), [-1, 2, 2])
    rotated = np.matmul( (pts2 - center)[np.newaxis,:,:], rot_mat) + center

    if allow_artifacts:
        valid = np.arange(n_angles)  # all scales are valid except scale=1
    else:
        valid = (rotated >= 0.) * (rotated < 1.)
        valid = valid.prod(axis=1).prod(axis=1)
        valid = np.where(valid)[0]
    idx = valid[np.random.randint(valid.shape[0], size=1)].squeeze().astype(int)
    pts2 = rotated[idx,:,:]

# Rescale to actual size
shape = shape[::-1]  # different convention [y, x]
pts1 *= shape[np.newaxis,:]
pts2 *= shape[np.newaxis,:]

homography = cv2.getPerspectiveTransform(np.float32(pts1), np.float32(pts2))
return homography

And it has the same function as the tensorflow code

I see.

Closing this issue due to no activity.