comparison scripts/compute-homography.py @ 476:6551a3cf1750

modified compute-homography to work with argparse
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Tue, 25 Mar 2014 19:43:28 -0400
parents 51810d737d86
children d337bffd7283
comparison
equal deleted inserted replaced
474:59903d14d244 476:6551a3cf1750
1 #! /usr/bin/env python 1 #! /usr/bin/env python
2 2
3 import sys,getopt 3 import sys, argparse
4 4
5 import matplotlib.pyplot as plt 5 import matplotlib.pyplot as plt
6 import numpy as np 6 import numpy as np
7 import cv2 7 import cv2
8 8
9 import cvutils 9 import cvutils
10 import utils 10 import utils
11 11
12 options, args = getopt.getopt(sys.argv[1:], 'hp:i:w:n:u:',['help']) 12 parser = argparse.ArgumentParser(description='The program computes the homography matrix from at least 4 non-colinear point correspondences inputed in the same order in a video frame and a aerial photo/ground map, or from the list of corresponding points in the two planes.', epilog = '''The point correspondence file contains at least 4 non-colinear point coordinates
13 options = dict(options) 13 with the following format:
14 - the first two lines are the x and y coordinates in the projected space (usually world space)
15 - the last two lines are the x and y coordinates in the origin space (usually image space)
16
17 If providing video and world images, with a number of points to input
18 and a ration to convert pixels to world distance unit (eg meters per pixel),
19 the images will be shown in turn and the user should click
20 in the same order the corresponding points in world and image spaces.''', formatter_class=argparse.RawDescriptionHelpFormatter,)
21
22 parser.add_argument('-p', dest = 'pointCorrespondencesFilename', help = 'name of the text file containing the point correspondences')
23 parser.add_argument('-i', dest = 'videoFrameFilename', help = 'filename of the video frame')
24 parser.add_argument('-w', dest = 'worldFilename', help = 'filename of the aerial photo/ground map')
25 parser.add_argument('-n', dest = 'nPoints', help = 'number of corresponding points to input', default = 4, type = int)
26 parser.add_argument('-u', dest = 'unitsPerPixel', help = 'number of units per pixel', default = 1., type = float)
27 parser.add_argument('--display', dest = 'displayPoints', help = 'display original and projected points on both images', action = 'store_true')
28
29 args = parser.parse_args()
14 30
15 # TODO process camera intrinsic and extrinsic parameters to obtain image to world homography, taking example from Work/src/python/generate-homography.py script 31 # TODO process camera intrinsic and extrinsic parameters to obtain image to world homography, taking example from Work/src/python/generate-homography.py script
16 # cameraMat = load(videoFilenamePrefix+'-camera.txt'); 32 # cameraMat = load(videoFilenamePrefix+'-camera.txt');
17 # T1 = cameraMat[3:6,:].copy(); 33 # T1 = cameraMat[3:6,:].copy();
18 # A = cameraMat[0:3,0:3].copy(); 34 # A = cameraMat[0:3,0:3].copy();
50 66
51 # H = cvCreateMat(3, 3, CV_64FC1); 67 # H = cvCreateMat(3, 3, CV_64FC1);
52 68
53 # cvFindHomography(imagePoints, worldPoints, H); 69 # cvFindHomography(imagePoints, worldPoints, H);
54 70
55 if '--help' in options.keys() or '-h' in options.keys() or len(options) == 0:
56 print('Usage: {0} --help|-h [-p point-correspondences.txt] [ -i video-frame] [ -w world-frame] [n number-points] [-u unit-per-pixel=1]'.format(sys.argv[0]))
57 print('''The input data can be provided either as point correspondences already saved
58 in a text file or inputed by clicking a certain number of points (>=4)
59 in a video frame and a world image.
60
61 The point correspondence file contains at least 4 non-colinear point coordinates
62 with the following format:
63 - the first two lines are the x and y coordinates in the projected space (usually world space)
64 - the last two lines are the x and y coordinates in the origin space (usually image space)
65
66 If providing video and world images, with a number of points to input
67 and a ration to convert pixels to world distance unit (eg meters per pixel),
68 the images will be shown in turn and the user should click
69 in the same order the corresponding points in world and image spaces. ''')
70 sys.exit()
71 71
72 homography = np.array([]) 72 homography = np.array([])
73 if '-p' in options.keys(): 73 if args.pointCorrespondencesFilename != None:
74 worldPts, videoPts = cvutils.loadPointCorrespondences(options['-p']) 74 worldPts, videoPts = cvutils.loadPointCorrespondences(args.pointCorrespondencesFilename)
75 homography, mask = cv2.findHomography(videoPts, worldPts) # method=0, ransacReprojThreshold=3 75 homography, mask = cv2.findHomography(videoPts, worldPts) # method=0, ransacReprojThreshold=3
76 elif '-i' in options.keys() and '-w' in options.keys(): 76 elif args.videoFrameFilename != None and args.worldFilename != None:
77 nPoints = 4 77 worldImg = plt.imread(args.worldFilename)
78 if '-n' in options.keys(): 78 videoImg = plt.imread(args.videoFrameFilename)
79 nPoints = int(options['-n']) 79 print('Click on {0} points in the video frame'.format(args.nPoints))
80 unitsPerPixel = 1
81 if '-u' in options.keys():
82 unitsPerPixel = float(options['-u'])
83 worldImg = plt.imread(options['-w'])
84 videoImg = plt.imread(options['-i'])
85 print('Click on {0} points in the video frame'.format(nPoints))
86 plt.figure() 80 plt.figure()
87 plt.imshow(videoImg) 81 plt.imshow(videoImg)
88 videoPts = np.array(plt.ginput(nPoints, timeout=3000)) 82 videoPts = np.array(plt.ginput(args.nPoints, timeout=3000))
89 print('Click on {0} points in the world image'.format(nPoints)) 83 print('Click on {0} points in the world image'.format(args.nPoints))
90 plt.figure() 84 plt.figure()
91 plt.imshow(worldImg) 85 plt.imshow(worldImg)
92 worldPts = unitsPerPixel*np.array(plt.ginput(nPoints, timeout=3000)) 86 worldPts = args.unitsPerPixel*np.array(plt.ginput(args.nPoints, timeout=3000))
93 plt.close('all') 87 plt.close('all')
94 homography, mask = cv2.findHomography(videoPts, worldPts) 88 homography, mask = cv2.findHomography(videoPts, worldPts)
95 # save the points in file 89 # save the points in file
96 f = open('point-correspondences.txt', 'a') 90 f = open('point-correspondences.txt', 'a')
97 np.savetxt(f, worldPts.T) 91 np.savetxt(f, worldPts.T)
99 f.close() 93 f.close()
100 94
101 if homography.size>0: 95 if homography.size>0:
102 np.savetxt('homography.txt',homography) 96 np.savetxt('homography.txt',homography)
103 97
104 if '-i' in options.keys() and homography.size>0: 98 if args.displayPoints and args.videoFrameFilename != None and args.worldFilename != None and homography.size>0:
105 videoImg = cv2.imread(options['-i']) 99 worldImg = plt.imread(args.worldFilename)
106 worldImg = cv2.imread(options['-w']) 100 videoImg = plt.imread(args.videoFrameFilename)
107 invHomography = np.linalg.inv(homography) 101 invHomography = np.linalg.inv(homography)
108 projectedWorldPts = cvutils.projectArray(invHomography, worldPts.T).T 102 projectedWorldPts = cvutils.projectArray(invHomography, worldPts.T).T
109 if '-u' in options.keys(): 103 projectedVideoPts = cvutils.projectArray(invHomography, videoPts.T).T
110 unitsPerPixel = float(options['-u'])
111 projectedVideoPts = cvutils.projectArray(invHomography, videoPts.T).T
112 for i in range(worldPts.shape[0]): 104 for i in range(worldPts.shape[0]):
113 cv2.circle(videoImg,tuple(np.int32(np.round(videoPts[i]))),2,cvutils.cvRed) 105 cv2.circle(worldImg,tuple(np.int32(np.round(worldPts[i]/args.unitsPerPixel))),2,cvutils.cvRed)
114 cv2.circle(videoImg,tuple(np.int32(np.round(projectedWorldPts[i]))),2,cvutils.cvBlue) 106 cv2.circle(worldImg,tuple(np.int32(np.round(projectedVideoPts[i]/args.unitsPerPixel))),2,cvutils.cvRed)
115 if '-u' in options.keys(): 107 # TODO print numbers and in image space
116 cv2.circle(worldImg,tuple(np.int32(np.round(worldPts[i]/unitsPerPixel))),2,cvutils.cvRed)
117 cv2.circle(worldImg,tuple(np.int32(np.round(projectedVideoPts[i]/unitsPerPixel))),2,cvutils.cvRed)
118 #print('img: {0} / projected: {1}'.format(videoPts[i], p))
119 cv2.imshow('video frame',videoImg) 108 cv2.imshow('video frame',videoImg)
120 if '-u' in options.keys(): 109 #cv2.imshow('world image',worldImg)
121 cv2.imshow('world image',worldImg)
122 cv2.waitKey() 110 cv2.waitKey()
123 cv2.destroyAllWindows() 111 cv2.destroyAllWindows()