comparison python/cvutils.py @ 795:a34ec862371f

merged with dev branch
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Mon, 09 May 2016 15:33:11 -0400
parents 5b970a5bc233
children 5b99b676265e
comparison
equal deleted inserted replaced
758:0a05883216cf 795:a34ec862371f
1 #! /usr/bin/env python 1 #! /usr/bin/env python
2 '''Image/Video utilities''' 2 '''Image/Video utilities'''
3 3
4 import utils 4 import utils, moving
5 5
6 try: 6 try:
7 import cv2 7 import cv2
8 opencvAvailable = True 8 opencvAvailable = True
9 except ImportError: 9 except ImportError:
14 skimageAvailable = True 14 skimageAvailable = True
15 except ImportError: 15 except ImportError:
16 print('Scikit-image library could not be loaded (HoG-based classification methods will not be available)') 16 print('Scikit-image library could not be loaded (HoG-based classification methods will not be available)')
17 skimageAvailable = False 17 skimageAvailable = False
18 18
19 from sys import stdout 19 from sys import stdout, maxint
20 from numpy import dot, array, append, float32 20 from os import listdir
21 from copy import deepcopy
22 from math import floor, log10, ceil
23
24 from numpy import dot, array, append, float32, loadtxt, savetxt, append, zeros, ones, identity, abs as npabs, logical_and, unravel_index, sum as npsum, isnan, mgrid, median, floor as npfloor, ceil as npceil
25 from matplotlib.mlab import find
26 from matplotlib.pyplot import imread, imsave
27
28
21 29
22 #import aggdraw # agg on top of PIL (antialiased drawing) 30 #import aggdraw # agg on top of PIL (antialiased drawing)
23 31
24 32
25 cvRed = (0,0,255) 33 cvRed = (0,0,255)
75 return dot(rgb[...,:3], [0.299, 0.587, 0.144]) 83 return dot(rgb[...,:3], [0.299, 0.587, 0.144])
76 84
77 def matlab2PointCorrespondences(filename): 85 def matlab2PointCorrespondences(filename):
78 '''Loads and converts the point correspondences saved 86 '''Loads and converts the point correspondences saved
79 by the matlab camera calibration tool''' 87 by the matlab camera calibration tool'''
80 from numpy.lib.io import loadtxt, savetxt
81 from numpy.lib.function_base import append
82 points = loadtxt(filename, delimiter=',') 88 points = loadtxt(filename, delimiter=',')
83 savetxt(utils.removeExtension(filename)+'-point-correspondences.txt',append(points[:,:2].T, points[:,3:].T, axis=0)) 89 savetxt(utils.removeExtension(filename)+'-point-correspondences.txt',append(points[:,:2].T, points[:,3:].T, axis=0))
84 90
85 def loadPointCorrespondences(filename): 91 def loadPointCorrespondences(filename):
86 '''Loads and returns the corresponding points in world (first 2 lines) and image spaces (last 2 lines)''' 92 '''Loads and returns the corresponding points in world (first 2 lines) and image spaces (last 2 lines)'''
87 from numpy import loadtxt, float32
88 points = loadtxt(filename, dtype=float32) 93 points = loadtxt(filename, dtype=float32)
89 return (points[:2,:].T, points[2:,:].T) # (world points, image points) 94 return (points[:2,:].T, points[2:,:].T) # (world points, image points)
90 95
91 def cvMatToArray(cvmat): 96 def cvMatToArray(cvmat):
92 '''Converts an OpenCV CvMat to numpy array.''' 97 '''Converts an OpenCV CvMat to numpy array.'''
93 print('Deprecated, use new interface') 98 print('Deprecated, use new interface')
94 from numpy import zeros
95 a = zeros((cvmat.rows, cvmat.cols))#array([[0.0]*cvmat.width]*cvmat.height) 99 a = zeros((cvmat.rows, cvmat.cols))#array([[0.0]*cvmat.width]*cvmat.height)
96 for i in xrange(cvmat.rows): 100 for i in xrange(cvmat.rows):
97 for j in xrange(cvmat.cols): 101 for j in xrange(cvmat.cols):
98 a[i,j] = cvmat[i,j] 102 a[i,j] = cvmat[i,j]
99 return a 103 return a
104
105 def createWhiteImage(height, width, filename):
106 img = ones((height, width, 3), uint8)*255
107 imsave(filename, img)
100 108
101 if opencvAvailable: 109 if opencvAvailable:
102 def computeHomography(srcPoints, dstPoints, method=0, ransacReprojThreshold=3.0): 110 def computeHomography(srcPoints, dstPoints, method=0, ransacReprojThreshold=3.0):
103 '''Returns the homography matrix mapping from srcPoints to dstPoints (dimension Nx2)''' 111 '''Returns the homography matrix mapping from srcPoints to dstPoints (dimension Nx2)'''
104 H, mask = cv2.findHomography(srcPoints, dstPoints, method, ransacReprojThreshold) 112 H, mask = cv2.findHomography(srcPoints, dstPoints, method, ransacReprojThreshold)
130 cv2.imshow(windowName, resizedImg) 138 cv2.imshow(windowName, resizedImg)
131 else: 139 else:
132 cv2.imshow(windowName, img) 140 cv2.imshow(windowName, img)
133 141
134 def computeUndistortMaps(width, height, undistortedImageMultiplication, intrinsicCameraMatrix, distortionCoefficients): 142 def computeUndistortMaps(width, height, undistortedImageMultiplication, intrinsicCameraMatrix, distortionCoefficients):
135 from copy import deepcopy
136 from numpy import identity
137 newImgSize = (int(round(width*undistortedImageMultiplication)), int(round(height*undistortedImageMultiplication))) 143 newImgSize = (int(round(width*undistortedImageMultiplication)), int(round(height*undistortedImageMultiplication)))
138 newCameraMatrix = deepcopy(intrinsicCameraMatrix) 144 newCameraMatrix = deepcopy(intrinsicCameraMatrix)
139 newCameraMatrix[0,2] = newImgSize[0]/2. 145 newCameraMatrix[0,2] = newImgSize[0]/2.
140 newCameraMatrix[1,2] = newImgSize[1]/2. 146 newCameraMatrix[1,2] = newImgSize[1]/2.
141 return cv2.initUndistortRectifyMap(intrinsicCameraMatrix, array(distortionCoefficients), identity(3), newCameraMatrix, newImgSize, cv2.CV_32FC1) 147 return cv2.initUndistortRectifyMap(intrinsicCameraMatrix, array(distortionCoefficients), identity(3), newCameraMatrix, newImgSize, cv2.CV_32FC1)
153 capture = cv2.VideoCapture(filename) 159 capture = cv2.VideoCapture(filename)
154 if capture.isOpened(): 160 if capture.isOpened():
155 key = -1 161 key = -1
156 ret = True 162 ret = True
157 frameNum = firstFrameNum 163 frameNum = firstFrameNum
158 capture.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, firstFrameNum) 164 capture.set(cv2.CAP_PROP_POS_FRAMES, firstFrameNum)
159 while ret and not quitKey(key): 165 while ret and not quitKey(key):
160 #ret, img = capture.read() 166 #ret, img = capture.read()
161 for i in xrange(step): 167 for i in xrange(step):
162 ret, img = capture.read() 168 ret, img = capture.read()
163 if ret: 169 if ret:
164 if printFrames: 170 if printFrames:
165 print('frame {0}'.format(frameNum)) 171 print('frame {0}'.format(frameNum))
166 frameNum+=step 172 frameNum+=step
167 if text is not None: 173 if text is not None:
168 cv2.putText(img, text, (10,50), cv2.cv.CV_FONT_HERSHEY_PLAIN, 1, cvRed) 174 cv2.putText(img, text, (10,50), cv2.FONT_HERSHEY_PLAIN, 1, cvRed)
169 cvImshow(windowName, img, rescale) 175 cvImshow(windowName, img, rescale)
170 key = cv2.waitKey(wait) 176 key = cv2.waitKey(wait)
171 if saveKey(key): 177 if saveKey(key):
172 cv2.imwrite('image-{}.png'.format(frameNum), img) 178 cv2.imwrite('image-{}.png'.format(frameNum), img)
173 cv2.destroyAllWindows() 179 cv2.destroyAllWindows()
174 else: 180 else:
175 print('Video capture for {} failed'.format(filename)) 181 print('Video capture for {} failed'.format(filename))
176 182
177 def infoVideo(filename): 183 def infoVideo(filename):
178 '''Provides all available info on video ''' 184 '''Provides all available info on video '''
179 cvPropertyNames = {cv2.cv.CV_CAP_PROP_FORMAT: "format", 185 cvPropertyNames = {cv2.CAP_PROP_FORMAT: "format",
180 cv2.cv.CV_CAP_PROP_FOURCC: "codec (fourcc)", 186 cv2.CAP_PROP_FOURCC: "codec (fourcc)",
181 cv2.cv.CV_CAP_PROP_FPS: "fps", 187 cv2.CAP_PROP_FPS: "fps",
182 cv2.cv.CV_CAP_PROP_FRAME_COUNT: "number of frames", 188 cv2.CAP_PROP_FRAME_COUNT: "number of frames",
183 cv2.cv.CV_CAP_PROP_FRAME_HEIGHT: "heigh", 189 cv2.CAP_PROP_FRAME_HEIGHT: "heigh",
184 cv2.cv.CV_CAP_PROP_FRAME_WIDTH: "width", 190 cv2.CAP_PROP_FRAME_WIDTH: "width",
185 cv2.cv.CV_CAP_PROP_RECTIFICATION: "rectification", 191 cv2.CAP_PROP_RECTIFICATION: "rectification",
186 cv2.cv.CV_CAP_PROP_SATURATION: "saturation"} 192 cv2.CAP_PROP_SATURATION: "saturation"}
187 capture = cv2.VideoCapture(filename) 193 capture = cv2.VideoCapture(filename)
188 if capture.isOpened(): 194 if capture.isOpened():
189 for cvprop in [#cv2.cv.CV_CAP_PROP_BRIGHTNESS 195 for cvprop in [#cv2.CAP_PROP_BRIGHTNESS
190 #cv2.cv.CV_CAP_PROP_CONTRAST 196 #cv2.CAP_PROP_CONTRAST
191 #cv2.cv.CV_CAP_PROP_CONVERT_RGB 197 #cv2.CAP_PROP_CONVERT_RGB
192 #cv2.cv.CV_CAP_PROP_EXPOSURE 198 #cv2.CAP_PROP_EXPOSURE
193 cv2.cv.CV_CAP_PROP_FORMAT, 199 cv2.CAP_PROP_FORMAT,
194 cv2.cv.CV_CAP_PROP_FOURCC, 200 cv2.CAP_PROP_FOURCC,
195 cv2.cv.CV_CAP_PROP_FPS, 201 cv2.CAP_PROP_FPS,
196 cv2.cv.CV_CAP_PROP_FRAME_COUNT, 202 cv2.CAP_PROP_FRAME_COUNT,
197 cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 203 cv2.CAP_PROP_FRAME_HEIGHT,
198 cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 204 cv2.CAP_PROP_FRAME_WIDTH,
199 #cv2.cv.CV_CAP_PROP_GAIN, 205 #cv2.CAP_PROP_GAIN,
200 #cv2.cv.CV_CAP_PROP_HUE 206 #cv2.CAP_PROP_HUE
201 #cv2.cv.CV_CAP_PROP_MODE 207 #cv2.CAP_PROP_MODE
202 #cv2.cv.CV_CAP_PROP_POS_AVI_RATIO 208 #cv2.CAP_PROP_POS_AVI_RATIO
203 #cv2.cv.CV_CAP_PROP_POS_FRAMES 209 #cv2.CAP_PROP_POS_FRAMES
204 #cv2.cv.CV_CAP_PROP_POS_MSEC 210 #cv2.CAP_PROP_POS_MSEC
205 #cv2.cv.CV_CAP_PROP_RECTIFICATION, 211 #cv2.CAP_PROP_RECTIFICATION,
206 #cv2.cv.CV_CAP_PROP_SATURATION 212 #cv2.CAP_PROP_SATURATION
207 ]: 213 ]:
208 prop = capture.get(cvprop) 214 prop = capture.get(cvprop)
209 if cvprop == cv2.cv.CV_CAP_PROP_FOURCC and prop > 0: 215 if cvprop == cv2.CAP_PROP_FOURCC and prop > 0:
210 prop = int2FOURCC(int(prop)) 216 prop = int2FOURCC(int(prop))
211 print('Video {}: {}'.format(cvPropertyNames[cvprop], prop)) 217 print('Video {}: {}'.format(cvPropertyNames[cvprop], prop))
212 else: 218 else:
213 print('Video capture for {} failed'.format(filename)) 219 print('Video capture for {} failed'.format(filename))
214 220
215 def getImagesFromVideo(videoFilename, firstFrameNum = 0, nFrames = 1, saveImage = False, outputPrefix = 'image'): 221 def getImagesFromVideo(videoFilename, firstFrameNum = 0, nFrames = 1, saveImage = False, outputPrefix = 'image'):
216 '''Returns nFrames images from the video sequence''' 222 '''Returns nFrames images from the video sequence'''
217 from math import floor, log10
218 images = [] 223 images = []
219 capture = cv2.VideoCapture(videoFilename) 224 capture = cv2.VideoCapture(videoFilename)
220 if capture.isOpened(): 225 if capture.isOpened():
221 rawCount = capture.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT) 226 rawCount = capture.get(cv2.CAP_PROP_FRAME_COUNT)
222 if rawCount < 0: 227 if rawCount < 0:
223 rawCount = firstFrameNum+nFrames+1 228 rawCount = firstFrameNum+nFrames+1
224 nDigits = int(floor(log10(rawCount)))+1 229 nDigits = int(floor(log10(rawCount)))+1
225 ret = False 230 ret = False
226 capture.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, firstFrameNum) 231 capture.set(cv2.CAP_PROP_POS_FRAMES, firstFrameNum)
227 imgNum = 0 232 imgNum = 0
228 while imgNum<nFrames: 233 while imgNum<nFrames:
229 ret, img = capture.read() 234 ret, img = capture.read()
230 i = 0 235 i = 0
231 while not ret and i<10: 236 while not ret and i<10:
244 return images 249 return images
245 250
246 def getFPS(videoFilename): 251 def getFPS(videoFilename):
247 capture = cv2.VideoCapture(videoFilename) 252 capture = cv2.VideoCapture(videoFilename)
248 if capture.isOpened(): 253 if capture.isOpened():
249 fps = capture.get(cv2.cv.CV_CAP_PROP_FPS) 254 fps = capture.get(cv2.CAP_PROP_FPS)
250 capture.release() 255 capture.release()
251 return fps 256 return fps
252 else: 257 else:
253 print('Video capture for {} failed'.format(videoFilename)) 258 print('Video capture for {} failed'.format(videoFilename))
254 return None 259 return None
281 return croppedImg, yCropMin, yCropMax, xCropMin, xCropMax 286 return croppedImg, yCropMin, yCropMax, xCropMin, xCropMax
282 287
283 288
284 def displayTrajectories(videoFilename, objects, boundingBoxes = {}, homography = None, firstFrameNum = 0, lastFrameNumArg = None, printFrames = True, rescale = 1., nFramesStep = 1, saveAllImages = False, undistort = False, intrinsicCameraMatrix = None, distortionCoefficients = None, undistortedImageMultiplication = 1., annotations = [], gtMatches = {}, toMatches = {}): 289 def displayTrajectories(videoFilename, objects, boundingBoxes = {}, homography = None, firstFrameNum = 0, lastFrameNumArg = None, printFrames = True, rescale = 1., nFramesStep = 1, saveAllImages = False, undistort = False, intrinsicCameraMatrix = None, distortionCoefficients = None, undistortedImageMultiplication = 1., annotations = [], gtMatches = {}, toMatches = {}):
285 '''Displays the objects overlaid frame by frame over the video ''' 290 '''Displays the objects overlaid frame by frame over the video '''
286 from moving import userTypeNames
287 from math import ceil, log10
288
289 capture = cv2.VideoCapture(videoFilename) 291 capture = cv2.VideoCapture(videoFilename)
290 width = int(capture.get(cv2.cv.CV_CAP_PROP_FRAME_WIDTH)) 292 width = int(capture.get(cv2.CAP_PROP_FRAME_WIDTH))
291 height = int(capture.get(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT)) 293 height = int(capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
292 294
293 windowName = 'frame' 295 windowName = 'frame'
294 if rescale == 1.: 296 if rescale == 1.:
295 cv2.namedWindow(windowName, cv2.WINDOW_NORMAL) 297 cv2.namedWindow(windowName, cv2.WINDOW_NORMAL)
296 298
298 [map1, map2] = computeUndistortMaps(width, height, undistortedImageMultiplication, intrinsicCameraMatrix, distortionCoefficients) 300 [map1, map2] = computeUndistortMaps(width, height, undistortedImageMultiplication, intrinsicCameraMatrix, distortionCoefficients)
299 if capture.isOpened(): 301 if capture.isOpened():
300 key = -1 302 key = -1
301 ret = True 303 ret = True
302 frameNum = firstFrameNum 304 frameNum = firstFrameNum
303 capture.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, firstFrameNum) 305 capture.set(cv2.CAP_PROP_POS_FRAMES, firstFrameNum)
304 if lastFrameNumArg is None: 306 if lastFrameNumArg is None:
305 from sys import maxint
306 lastFrameNum = maxint 307 lastFrameNum = maxint
307 else: 308 else:
308 lastFrameNum = lastFrameNumArg 309 lastFrameNum = lastFrameNumArg
309 nZerosFilename = int(ceil(log10(lastFrameNum))) 310 nZerosFilename = int(ceil(log10(lastFrameNum)))
310 objectToDeleteIds = [] 311 objectToDeleteIds = []
331 cvPlot(img, obj.projectedPositions, cvColors[obj.getNum()], frameNum-obj.getFirstInstant()) 332 cvPlot(img, obj.projectedPositions, cvColors[obj.getNum()], frameNum-obj.getFirstInstant())
332 if frameNum not in boundingBoxes.keys() and obj.hasFeatures(): 333 if frameNum not in boundingBoxes.keys() and obj.hasFeatures():
333 imgcrop, yCropMin, yCropMax, xCropMin, xCropMax = imageBox(img, obj, frameNum, homography, width, height) 334 imgcrop, yCropMin, yCropMax, xCropMin, xCropMax = imageBox(img, obj, frameNum, homography, width, height)
334 cv2.rectangle(img, (xCropMin, yCropMin), (xCropMax, yCropMax), cvBlue, 1) 335 cv2.rectangle(img, (xCropMin, yCropMin), (xCropMax, yCropMax), cvBlue, 1)
335 objDescription = '{} '.format(obj.num) 336 objDescription = '{} '.format(obj.num)
336 if userTypeNames[obj.userType] != 'unknown': 337 if moving.userTypeNames[obj.userType] != 'unknown':
337 objDescription += userTypeNames[obj.userType][0].upper() 338 objDescription += moving.userTypeNames[obj.userType][0].upper()
338 if len(annotations) > 0: # if we loaded annotations, but there is no match 339 if len(annotations) > 0: # if we loaded annotations, but there is no match
339 if frameNum not in toMatches[obj.getNum()]: 340 if frameNum not in toMatches[obj.getNum()]:
340 objDescription += " FA" 341 objDescription += " FA"
341 cv2.putText(img, objDescription, obj.projectedPositions[frameNum-obj.getFirstInstant()].asint().astuple(), cv2.cv.CV_FONT_HERSHEY_PLAIN, 1, cvColors[obj.getNum()]) 342 cv2.putText(img, objDescription, obj.projectedPositions[frameNum-obj.getFirstInstant()].asint().astuple(), cv2.FONT_HERSHEY_PLAIN, 1, cvColors[obj.getNum()])
342 # plot object bounding boxes 343 # plot object bounding boxes
343 if frameNum in boundingBoxes.keys(): 344 if frameNum in boundingBoxes.keys():
344 for rect in boundingBoxes[frameNum]: 345 for rect in boundingBoxes[frameNum]:
345 cv2.rectangle(img, rect[0].asint().astuple(), rect[1].asint().astuple(), cvColors[obj.getNum()]) 346 cv2.rectangle(img, rect[0].asint().astuple(), rect[1].asint().astuple(), cvColors[obj.getNum()])
346 # plot ground truth 347 # plot ground truth
349 if gt.existsAtInstant(frameNum): 350 if gt.existsAtInstant(frameNum):
350 if frameNum in gtMatches[gt.getNum()]: 351 if frameNum in gtMatches[gt.getNum()]:
351 color = cvColors[gtMatches[gt.getNum()][frameNum]] # same color as object 352 color = cvColors[gtMatches[gt.getNum()][frameNum]] # same color as object
352 else: 353 else:
353 color = cvRed 354 color = cvRed
354 cv2.putText(img, 'Miss', gt.topLeftPositions[frameNum-gt.getFirstInstant()].asint().astuple(), cv2.cv.CV_FONT_HERSHEY_PLAIN, 1, cvRed) 355 cv2.putText(img, 'Miss', gt.topLeftPositions[frameNum-gt.getFirstInstant()].asint().astuple(), cv2.FONT_HERSHEY_PLAIN, 1, cvRed)
355 cv2.rectangle(img, gt.topLeftPositions[frameNum-gt.getFirstInstant()].asint().astuple(), gt.bottomRightPositions[frameNum-gt.getFirstInstant()].asint().astuple(), color) 356 cv2.rectangle(img, gt.topLeftPositions[frameNum-gt.getFirstInstant()].asint().astuple(), gt.bottomRightPositions[frameNum-gt.getFirstInstant()].asint().astuple(), color)
356 # saving images and going to next 357 # saving images and going to next
357 if not saveAllImages: 358 if not saveAllImages:
358 cvImshow(windowName, img, rescale) 359 cvImshow(windowName, img, rescale)
359 key = cv2.waitKey() 360 key = cv2.waitKey()
360 if saveAllImages or saveKey(key): 361 if saveAllImages or saveKey(key):
361 cv2.imwrite('image-{{:0{}}}.png'.format(nZerosFilename).format(frameNum), img) 362 cv2.imwrite('image-{{:0{}}}.png'.format(nZerosFilename).format(frameNum), img)
362 frameNum += nFramesStep 363 frameNum += nFramesStep
363 if nFramesStep > 1: 364 if nFramesStep > 1:
364 capture.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, frameNum) 365 capture.set(cv2.CAP_PROP_POS_FRAMES, frameNum)
365 cv2.destroyAllWindows() 366 cv2.destroyAllWindows()
366 else: 367 else:
367 print 'Cannot load file ' + videoFilename 368 print('Cannot load file ' + videoFilename)
368 369
369 def computeHomographyFromPDTV(camera): 370 def computeHomographyFromPDTV(camera):
370 '''Returns the homography matrix at ground level from PDTV camera 371 '''Returns the homography matrix at ground level from PDTV camera
371 https://bitbucket.org/hakanardo/pdtv''' 372 https://bitbucket.org/hakanardo/pdtv'''
372 # camera = pdtv.load(cameraFilename) 373 # camera = pdtv.load(cameraFilename)
381 def undistortedCoordinates(map1, map2, x, y, maxDistance = 1.): 382 def undistortedCoordinates(map1, map2, x, y, maxDistance = 1.):
382 '''Returns the coordinates of a point in undistorted image 383 '''Returns the coordinates of a point in undistorted image
383 map1 and map2 are the mapping functions from undistorted image 384 map1 and map2 are the mapping functions from undistorted image
384 to distorted (original image) 385 to distorted (original image)
385 map1(x,y) = originalx, originaly''' 386 map1(x,y) = originalx, originaly'''
386 from numpy import abs, logical_and, unravel_index, sum 387 distx = npabs(map1-x)
387 from matplotlib.mlab import find 388 disty = npabs(map2-y)
388 distx = abs(map1-x)
389 disty = abs(map2-y)
390 indices = logical_and(distx<maxDistance, disty<maxDistance) 389 indices = logical_and(distx<maxDistance, disty<maxDistance)
391 closeCoordinates = unravel_index(find(indices), distx.shape) # returns i,j, ie y,x 390 closeCoordinates = unravel_index(find(indices), distx.shape) # returns i,j, ie y,x
392 xWeights = 1-distx[indices] 391 xWeights = 1-distx[indices]
393 yWeights = 1-disty[indices] 392 yWeights = 1-disty[indices]
394 return dot(xWeights, closeCoordinates[1])/sum(xWeights), dot(yWeights, closeCoordinates[0])/sum(yWeights) 393 return dot(xWeights, closeCoordinates[1])/npsum(xWeights), dot(yWeights, closeCoordinates[0])/npsum(yWeights)
395 394
396 def undistortTrajectoryFromCVMapping(map1, map2, t): 395 def undistortTrajectoryFromCVMapping(map1, map2, t):
397 '''test 'perfect' inversion''' 396 '''test 'perfect' inversion'''
398 from moving import Trajectory 397 undistortedTrajectory = moving.Trajectory()
399 from numpy import isnan
400 undistortedTrajectory = Trajectory()
401 for i,p in enumerate(t): 398 for i,p in enumerate(t):
402 res = undistortedCoordinates(map1, map2, p.x,p.y) 399 res = undistortedCoordinates(map1, map2, p.x,p.y)
403 if not isnan(res).any(): 400 if not isnan(res).any():
404 undistortedTrajectory.addPositionXY(res[0], res[1]) 401 undistortedTrajectory.addPositionXY(res[0], res[1])
405 else: 402 else:
406 print i,p,res 403 print('{} {} {}'.format(i,p,res))
407 return undistortedTrajectory 404 return undistortedTrajectory
408 405
409 def computeInverseMapping(originalImageSize, map1, map2): 406 def computeInverseMapping(originalImageSize, map1, map2):
410 'Computes inverse mapping from maps provided by cv2.initUndistortRectifyMap' 407 'Computes inverse mapping from maps provided by cv2.initUndistortRectifyMap'
411 from numpy import ones, isnan
412 invMap1 = -ones(originalImageSize) 408 invMap1 = -ones(originalImageSize)
413 invMap2 = -ones(originalImageSize) 409 invMap2 = -ones(originalImageSize)
414 for x in range(0,originalImageSize[1]): 410 for x in range(0,originalImageSize[1]):
415 for y in range(0,originalImageSize[0]): 411 for y in range(0,originalImageSize[0]):
416 res = undistortedCoordinates(x,y, map1, map2) 412 res = undistortedCoordinates(x,y, map1, map2)
430 426
431 The code below is based off of: 427 The code below is based off of:
432 https://opencv-python-tutroals.readthedocs.org/en/latest/py_tutorials/py_calib3d/py_calibration/py_calibration.html 428 https://opencv-python-tutroals.readthedocs.org/en/latest/py_tutorials/py_calib3d/py_calibration/py_calibration.html
433 Modified by Paul St-Aubin 429 Modified by Paul St-Aubin
434 ''' 430 '''
435 from numpy import zeros, mgrid, float32, savetxt
436 import glob, os 431 import glob, os
437 432
438 # termination criteria 433 # termination criteria
439 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) 434 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
440 435
455 # Find the chess board corners 450 # Find the chess board corners
456 ret, corners = cv2.findChessboardCorners(gray, (checkerBoardSize[1],checkerBoardSize[0]), None) 451 ret, corners = cv2.findChessboardCorners(gray, (checkerBoardSize[1],checkerBoardSize[0]), None)
457 452
458 # If found, add object points, image points (after refining them) 453 # If found, add object points, image points (after refining them)
459 if ret: 454 if ret:
460 print 'Found pattern in '+fname 455 print('Found pattern in '+fname)
461 456
462 if(secondPassSearch): 457 if secondPassSearch:
463 corners = cv2.cornerSubPix(gray, corners, (11,11), (-1,-1), criteria) 458 corners = cv2.cornerSubPix(gray, corners, (11,11), (-1,-1), criteria)
464 459
465 objpoints.append(objp) 460 objpoints.append(objp)
466 imgpoints.append(corners) 461 imgpoints.append(corners)
467 462
468 # Draw and display the corners 463 # Draw and display the corners
469 if(display): 464 if display:
470 img = cv2.drawChessboardCorners(img, (checkerBoardSize[1],checkerBoardSize[0]), corners, ret) 465 img = cv2.drawChessboardCorners(img, (checkerBoardSize[1],checkerBoardSize[0]), corners, ret)
471 if(img): 466 if img is not None:
472 cv2.imshow('img',img) 467 cv2.imshow('img',img)
473 cv2.waitKey(0) 468 cv2.waitKey(0)
474 469 else:
470 print('Pattern not found in '+fname)
475 ## Close up image loading and calibrate 471 ## Close up image loading and calibrate
476 cv2.destroyAllWindows() 472 cv2.destroyAllWindows()
477 if len(objpoints) == 0 or len(imgpoints) == 0: 473 if len(objpoints) == 0 or len(imgpoints) == 0:
478 return False 474 return False
479 try: 475 try:
531 invH = inv(homography) 527 invH = inv(homography)
532 invH /= invH[2,2] 528 invH /= invH[2,2]
533 return invH 529 return invH
534 530
535 def undistortTrajectory(invMap1, invMap2, positions): 531 def undistortTrajectory(invMap1, invMap2, positions):
536 from numpy import floor, ceil 532 floorPositions = npfloor(positions)
537 floorPositions = floor(positions) 533 #ceilPositions = npceil(positions)
538 #ceilPositions = ceil(positions)
539 undistortedTrajectory = [[],[]] 534 undistortedTrajectory = [[],[]]
540 for i in xrange(len(positions[0])): 535 for i in xrange(len(positions[0])):
541 x,y = None, None 536 x,y = None, None
542 if positions[0][i]+1 < invMap1.shape[1] and positions[1][i]+1 < invMap1.shape[0]: 537 if positions[0][i]+1 < invMap1.shape[1] and positions[1][i]+1 < invMap1.shape[0]:
543 floorX = invMap1[floorPositions[1][i], floorPositions[0][i]] 538 floorX = invMap1[floorPositions[1][i], floorPositions[0][i]]
561 '''Computes the translation of img2 with respect to img1 556 '''Computes the translation of img2 with respect to img1
562 (loaded using OpenCV as numpy arrays) 557 (loaded using OpenCV as numpy arrays)
563 img1Points are used to compute the translation 558 img1Points are used to compute the translation
564 559
565 TODO add diagnostic if data is all over the place, and it most likely is not a translation (eg zoom, other non linear distortion)''' 560 TODO add diagnostic if data is all over the place, and it most likely is not a translation (eg zoom, other non linear distortion)'''
566 from numpy import median, sum
567 561
568 nextPoints = array([]) 562 nextPoints = array([])
569 (img2Points, status, track_error) = cv2.calcOpticalFlowPyrLK(img1, img2, img1Points, nextPoints, winSize=windowSize, maxLevel=level, criteria=criteria) 563 (img2Points, status, track_error) = cv2.calcOpticalFlowPyrLK(img1, img2, img1Points, nextPoints, winSize=windowSize, maxLevel=level, criteria=criteria)
570 # calcOpticalFlowPyrLK(prevImg, nextImg, prevPts[, nextPts[, status[, err[, winSize[, maxLevel[, criteria[, derivLambda[, flags]]]]]]]]) -> nextPts, status, err 564 # calcOpticalFlowPyrLK(prevImg, nextImg, prevPts[, nextPts[, status[, err[, winSize[, maxLevel[, criteria[, derivLambda[, flags]]]]]]]]) -> nextPts, status, err
571 delta = [] 565 delta = []
572 for (k, (p1,p2)) in enumerate(zip(img1Points, img2Points)): 566 for (k, (p1,p2)) in enumerate(zip(img1Points, img2Points)):
573 if status[k] == 1: 567 if status[k] == 1:
574 dp = p2-p1 568 dp = p2-p1
575 d = sum(dp**2) 569 d = npsum(dp**2)
576 if d < maxTranslation2: 570 if d < maxTranslation2:
577 delta.append(dp) 571 delta.append(dp)
578 if len(delta) >= minNMatches: 572 if len(delta) >= minNMatches:
579 return median(delta, axis=0) 573 return median(delta, axis=0)
580 else: 574 else:
599 subplot(1,2,2) 593 subplot(1,2,2)
600 imshow(hogViz) 594 imshow(hogViz)
601 return float32(features) 595 return float32(features)
602 596
603 def createHOGTrainingSet(imageDirectory, classLabel, rescaleSize = (64, 64), orientations=9, pixelsPerCell=(8, 8), cellsPerBlock=(2, 2), visualize=False, normalize=False): 597 def createHOGTrainingSet(imageDirectory, classLabel, rescaleSize = (64, 64), orientations=9, pixelsPerCell=(8, 8), cellsPerBlock=(2, 2), visualize=False, normalize=False):
604 from os import listdir
605 from matplotlib.pyplot import imread
606
607 inputData = [] 598 inputData = []
608 for filename in listdir(imageDirectory): 599 for filename in listdir(imageDirectory):
609 img = imread(imageDirectory+filename) 600 img = imread(imageDirectory+filename)
610 features = HOG(img, rescaleSize, orientations, pixelsPerCell, cellsPerBlock, visualize, normalize) 601 features = HOG(img, rescaleSize, orientations, pixelsPerCell, cellsPerBlock, visualize, normalize)
611 inputData.append(features) 602 inputData.append(features)
612 603
613 nImages = len(inputData) 604 nImages = len(inputData)
614 return array(inputData, dtype = float32), array([classLabel]*nImages, dtype = float32) 605 return array(inputData, dtype = float32), array([classLabel]*nImages)
615 606
616 607