Spaces:
Running
Running
import argparse | |
import numpy as np | |
import imageio | |
import torch | |
from tqdm import tqdm | |
import time | |
import scipy | |
import scipy.io | |
import scipy.misc | |
import os | |
import sys | |
from lib.model_test import D2Net | |
from lib.utils import preprocess_image | |
from lib.pyramid import process_multiscale | |
import cv2 | |
import matplotlib.pyplot as plt | |
from PIL import Image | |
from skimage.feature import match_descriptors | |
from skimage.measure import ransac | |
from skimage.transform import ProjectiveTransform, AffineTransform | |
import pydegensac | |
parser = argparse.ArgumentParser(description='Feature extraction script') | |
parser.add_argument('imgs', type=str, nargs=2) | |
parser.add_argument( | |
'--preprocessing', type=str, default='caffe', | |
help='image preprocessing (caffe or torch)' | |
) | |
parser.add_argument( | |
'--model_file', type=str, | |
help='path to the full model' | |
) | |
parser.add_argument( | |
'--no-relu', dest='use_relu', action='store_false', | |
help='remove ReLU after the dense feature extraction module' | |
) | |
parser.set_defaults(use_relu=True) | |
parser.add_argument( | |
'--sift', dest='use_sift', action='store_true', | |
help='Show sift matching as well' | |
) | |
parser.set_defaults(use_sift=False) | |
def extract(image, args, model, device): | |
if len(image.shape) == 2: | |
image = image[:, :, np.newaxis] | |
image = np.repeat(image, 3, -1) | |
input_image = preprocess_image( | |
image, | |
preprocessing=args.preprocessing | |
) | |
with torch.no_grad(): | |
keypoints, scores, descriptors = process_multiscale( | |
torch.tensor( | |
input_image[np.newaxis, :, :, :].astype(np.float32), | |
device=device | |
), | |
model, | |
scales=[1] | |
) | |
keypoints = keypoints[:, [1, 0, 2]] | |
feat = {} | |
feat['keypoints'] = keypoints | |
feat['scores'] = scores | |
feat['descriptors'] = descriptors | |
return feat | |
def rordMatching(image1, image2, feat1, feat2, matcher="BF"): | |
if(matcher == "BF"): | |
t0 = time.time() | |
bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=True) | |
matches = bf.match(feat1['descriptors'], feat2['descriptors']) | |
matches = sorted(matches, key=lambda x:x.distance) | |
t1 = time.time() | |
print("Time to extract matches: ", t1-t0) | |
print("Number of raw matches:", len(matches)) | |
match1 = [m.queryIdx for m in matches] | |
match2 = [m.trainIdx for m in matches] | |
keypoints_left = feat1['keypoints'][match1, : 2] | |
keypoints_right = feat2['keypoints'][match2, : 2] | |
np.random.seed(0) | |
t0 = time.time() | |
H, inliers = pydegensac.findHomography(keypoints_left, keypoints_right, 10.0, 0.99, 10000) | |
t1 = time.time() | |
print("Time for ransac: ", t1-t0) | |
n_inliers = np.sum(inliers) | |
print('Number of inliers: %d.' % n_inliers) | |
inlier_keypoints_left = [cv2.KeyPoint(point[0], point[1], 1) for point in keypoints_left[inliers]] | |
inlier_keypoints_right = [cv2.KeyPoint(point[0], point[1], 1) for point in keypoints_right[inliers]] | |
placeholder_matches = [cv2.DMatch(idx, idx, 1) for idx in range(n_inliers)] | |
draw_params = dict(matchColor = (0,255,0), | |
singlePointColor = (255,0,0), | |
# matchesMask = matchesMask, | |
flags = 0) | |
image3 = cv2.drawMatches(image1, inlier_keypoints_left, image2, inlier_keypoints_right, placeholder_matches, None, **draw_params) | |
plt.figure(figsize=(20, 20)) | |
plt.imshow(image3) | |
plt.axis('off') | |
plt.show() | |
def siftMatching(img1, img2): | |
img1 = np.array(cv2.cvtColor(np.array(img1), cv2.COLOR_BGR2RGB)) | |
img2 = np.array(cv2.cvtColor(np.array(img2), cv2.COLOR_BGR2RGB)) | |
# surf = cv2.xfeatures2d.SURF_create(100) | |
surf = cv2.xfeatures2d.SIFT_create() | |
kp1, des1 = surf.detectAndCompute(img1, None) | |
kp2, des2 = surf.detectAndCompute(img2, None) | |
FLANN_INDEX_KDTREE = 0 | |
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5) | |
search_params = dict(checks = 50) | |
flann = cv2.FlannBasedMatcher(index_params, search_params) | |
matches = flann.knnMatch(des1,des2,k=2) | |
good = [] | |
for m, n in matches: | |
if m.distance < 0.7*n.distance: | |
good.append(m) | |
src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1, 2) | |
dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1, 2) | |
model, inliers = pydegensac.findHomography(src_pts, dst_pts, 10.0, 0.99, 10000) | |
n_inliers = np.sum(inliers) | |
print('Number of inliers: %d.' % n_inliers) | |
inlier_keypoints_left = [cv2.KeyPoint(point[0], point[1], 1) for point in src_pts[inliers]] | |
inlier_keypoints_right = [cv2.KeyPoint(point[0], point[1], 1) for point in dst_pts[inliers]] | |
placeholder_matches = [cv2.DMatch(idx, idx, 1) for idx in range(n_inliers)] | |
image3 = cv2.drawMatches(img1, inlier_keypoints_left, img2, inlier_keypoints_right, placeholder_matches, None) | |
cv2.imshow('Matches', image3) | |
cv2.waitKey(0) | |
src_pts = np.float32([ inlier_keypoints_left[m.queryIdx].pt for m in placeholder_matches ]).reshape(-1, 2) | |
dst_pts = np.float32([ inlier_keypoints_right[m.trainIdx].pt for m in placeholder_matches ]).reshape(-1, 2) | |
return src_pts, dst_pts | |
if __name__ == '__main__': | |
use_cuda = torch.cuda.is_available() | |
device = torch.device("cuda:0" if use_cuda else "cpu") | |
args = parser.parse_args() | |
model = D2Net( | |
model_file=args.model_file, | |
use_relu=args.use_relu, | |
use_cuda=use_cuda | |
) | |
image1 = np.array(Image.open(args.imgs[0])) | |
image2 = np.array(Image.open(args.imgs[1])) | |
print('--\nRoRD\n--') | |
feat1 = extract(image1, args, model, device) | |
feat2 = extract(image2, args, model, device) | |
print("Features extracted.") | |
rordMatching(image1, image2, feat1, feat2, matcher="BF") | |
if(args.use_sift): | |
print('--\nSIFT\n--') | |
siftMatching(image1, image2) | |