comparison scripts/compute-homography.py @ 1166:7b4d732f82b3

adding an option to use image coordinates in point-correspondence file when undistorting
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Thu, 10 Jun 2021 23:51:42 -0400
parents 671426ce0f3e
children 6a6a4d5958f7
comparison
equal deleted inserted replaced
1165:c5863e04d302 1166:7b4d732f82b3
13 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 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
14 with the following format: 14 with the following format:
15 - the first two lines are the x and y coordinates in the projected space (usually world space) 15 - the first two lines are the x and y coordinates in the projected space (usually world space)
16 - the last two lines are the x and y coordinates in the origin space (usually image space) 16 - the last two lines are the x and y coordinates in the origin space (usually image space)
17 17
18 Image space is in ideal point space (no camera) if undistorting the camera
19
18 If providing video and world images, with a number of points to input 20 If providing video and world images, with a number of points to input
19 and a ration to convert pixels to world distance unit (eg meters per pixel), 21 and a ratio to convert pixels to world distance unit (eg meters per pixel),
20 the images will be shown in turn and the user should click 22 the images will be shown in turn and the user should click
21 in the same order the corresponding points in world and image spaces.''', formatter_class=argparse.RawDescriptionHelpFormatter) 23 in the same order the corresponding points in world and image spaces.''', formatter_class=argparse.RawDescriptionHelpFormatter)
22 24
23 parser.add_argument('-p', dest = 'pointCorrespondencesFilename', help = 'name of the text file containing the point correspondences') 25 parser.add_argument('-p', dest = 'pointCorrespondencesFilename', help = 'name of the text file containing the point correspondences')
24 parser.add_argument('--tsai', dest = 'tsaiCameraFilename', help = 'name of the text file containing the camera parameter following the pinhole camera model (Lund format)') # caution, this is Aliaksei's format 26 parser.add_argument('--tsai', dest = 'tsaiCameraFilename', help = 'name of the text file containing the camera parameter following the pinhole camera model (Lund format)') # caution, this is Aliaksei's format
29 parser.add_argument('-o', dest = 'homographyFilename', help = 'filename of the homography matrix', default = 'homography.txt') 31 parser.add_argument('-o', dest = 'homographyFilename', help = 'filename of the homography matrix', default = 'homography.txt')
30 parser.add_argument('--display', dest = 'displayPoints', help = 'display original and projected points on both images', action = 'store_true') 32 parser.add_argument('--display', dest = 'displayPoints', help = 'display original and projected points on both images', action = 'store_true')
31 parser.add_argument('--intrinsic', dest = 'intrinsicCameraMatrixFilename', help = 'name of the intrinsic camera file') 33 parser.add_argument('--intrinsic', dest = 'intrinsicCameraMatrixFilename', help = 'name of the intrinsic camera file')
32 parser.add_argument('--distortion-coefficients', dest = 'distortionCoefficients', help = 'distortion coefficients', nargs = '*', type = float) 34 parser.add_argument('--distortion-coefficients', dest = 'distortionCoefficients', help = 'distortion coefficients', nargs = '*', type = float)
33 parser.add_argument('--undistorted-multiplication', dest = 'undistortedImageMultiplication', help = 'undistorted image multiplication', type = float, default = 1.) 35 parser.add_argument('--undistorted-multiplication', dest = 'undistortedImageMultiplication', help = 'undistorted image multiplication', type = float, default = 1.)
34 parser.add_argument('--undistort', dest = 'undistort', help = 'undistort the video (because features have been extracted that way', action = 'store_true') 36 parser.add_argument('--undistort', dest = 'undistort', help = 'undistort the video (because features have been extracted that way)', action = 'store_true')
37 parser.add_argument('--correspondences-imagepoints-in-image-space', dest = 'correspondencesImagePointsInImageSpace', help = 'if image points are provided in the actual image space (before undistortion)', action = 'store_true')
35 parser.add_argument('--save', dest = 'saveImages', help = 'save the undistorted video frame (display option must be chosen)', action = 'store_true') 38 parser.add_argument('--save', dest = 'saveImages', help = 'save the undistorted video frame (display option must be chosen)', action = 'store_true')
36 39
37 args = parser.parse_args() 40 args = parser.parse_args()
38 41
39 homography = np.array([]) 42 homography = np.array([])
40 if args.pointCorrespondencesFilename is not None: 43 if args.pointCorrespondencesFilename is not None:
41 worldPts, videoPts = cvutils.loadPointCorrespondences(args.pointCorrespondencesFilename) 44 worldPts, videoPts = cvutils.loadPointCorrespondences(args.pointCorrespondencesFilename)
45 if args.correspondencesImagePointsInImageSpace:
46 videoPts = cv2.undistortPoints(videoPts.T, np.loadtxt(args.intrinsicCameraMatrixFilename), np.array(args.distortionCoefficients)).reshape(-1,2)
42 homography, mask = cv2.findHomography(videoPts, worldPts) # method=0, ransacReprojThreshold=3 47 homography, mask = cv2.findHomography(videoPts, worldPts) # method=0, ransacReprojThreshold=3
43 elif args.tsaiCameraFilename is not None: # hack using PDTV 48 elif args.tsaiCameraFilename is not None: # hack using PDTV
44 from pdtv import TsaiCamera 49 from pdtv import TsaiCamera
45 cameraData = storage.loadPinholeCameraModel(args.tsaiCameraFilename) 50 cameraData = storage.loadPinholeCameraModel(args.tsaiCameraFilename)
46 camera = TsaiCamera(Cx=cameraData['Cx'], Cy=cameraData['Cy'], Sx=cameraData['Sx'], Tx=cameraData['Tx'], Ty=cameraData['Ty'], Tz=cameraData['Tz'], dx=cameraData['dx'], dy=cameraData['dy'], f=cameraData['f'], k=cameraData['k'], r1=cameraData['r1'], r2=cameraData['r2'], r3=cameraData['r3'], r4=cameraData['r4'], r5=cameraData['r5'], r6=cameraData['r6'], r7=cameraData['r7'], r8=cameraData['r8'], r9=cameraData['r9']) 51 camera = TsaiCamera(Cx=cameraData['Cx'], Cy=cameraData['Cy'], Sx=cameraData['Sx'], Tx=cameraData['Tx'], Ty=cameraData['Ty'], Tz=cameraData['Tz'], dx=cameraData['dx'], dy=cameraData['dy'], f=cameraData['f'], k=cameraData['k'], r1=cameraData['r1'], r2=cameraData['r2'], r3=cameraData['r3'], r4=cameraData['r4'], r5=cameraData['r5'], r6=cameraData['r6'], r7=cameraData['r7'], r8=cameraData['r8'], r9=cameraData['r9'])