Mercurial Hosting > traffic-intelligence
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() |