diff 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
line wrap: on
line diff
--- a/python/cvutils.py	Tue Nov 03 13:48:56 2015 -0500
+++ b/python/cvutils.py	Mon May 09 15:33:11 2016 -0400
@@ -1,7 +1,7 @@
 #! /usr/bin/env python
 '''Image/Video utilities'''
 
-import utils
+import utils, moving
 
 try:
     import cv2
@@ -16,8 +16,16 @@
     print('Scikit-image library could not be loaded (HoG-based classification methods will not be available)')
     skimageAvailable = False
     
-from sys import stdout
-from numpy import dot, array, append, float32
+from sys import stdout, maxint
+from os import listdir
+from copy import deepcopy
+from math import floor, log10, ceil
+
+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
+from matplotlib.mlab import find
+from matplotlib.pyplot import imread, imsave
+
+
 
 #import aggdraw # agg on top of PIL (antialiased drawing)
 
@@ -77,27 +85,27 @@
 def matlab2PointCorrespondences(filename):
     '''Loads and converts the point correspondences saved 
     by the matlab camera calibration tool'''
-    from numpy.lib.io import loadtxt, savetxt
-    from numpy.lib.function_base import append
     points = loadtxt(filename, delimiter=',')
     savetxt(utils.removeExtension(filename)+'-point-correspondences.txt',append(points[:,:2].T, points[:,3:].T, axis=0))
 
 def loadPointCorrespondences(filename):
     '''Loads and returns the corresponding points in world (first 2 lines) and image spaces (last 2 lines)'''
-    from numpy import loadtxt, float32
     points = loadtxt(filename, dtype=float32)
     return  (points[:2,:].T, points[2:,:].T) # (world points, image points)
 
 def cvMatToArray(cvmat):
     '''Converts an OpenCV CvMat to numpy array.'''
     print('Deprecated, use new interface')
-    from numpy import zeros
     a = zeros((cvmat.rows, cvmat.cols))#array([[0.0]*cvmat.width]*cvmat.height)
     for i in xrange(cvmat.rows):
         for j in xrange(cvmat.cols):
             a[i,j] = cvmat[i,j]
     return a
 
+def createWhiteImage(height, width, filename):
+    img = ones((height, width, 3), uint8)*255
+    imsave(filename, img)
+
 if opencvAvailable:
     def computeHomography(srcPoints, dstPoints, method=0, ransacReprojThreshold=3.0):
         '''Returns the homography matrix mapping from srcPoints to dstPoints (dimension Nx2)'''
@@ -132,8 +140,6 @@
             cv2.imshow(windowName, img)
 
     def computeUndistortMaps(width, height, undistortedImageMultiplication, intrinsicCameraMatrix, distortionCoefficients):
-        from copy import deepcopy
-        from numpy import identity
         newImgSize = (int(round(width*undistortedImageMultiplication)), int(round(height*undistortedImageMultiplication)))
         newCameraMatrix = deepcopy(intrinsicCameraMatrix)
         newCameraMatrix[0,2] = newImgSize[0]/2.
@@ -155,7 +161,7 @@
             key = -1
             ret = True
             frameNum = firstFrameNum
-            capture.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, firstFrameNum)
+            capture.set(cv2.CAP_PROP_POS_FRAMES, firstFrameNum)
             while ret and not quitKey(key):
                 #ret, img = capture.read()
                 for i in xrange(step):
@@ -165,7 +171,7 @@
                         print('frame {0}'.format(frameNum))
                     frameNum+=step
                     if text is not None:
-                       cv2.putText(img, text, (10,50), cv2.cv.CV_FONT_HERSHEY_PLAIN, 1, cvRed) 
+                       cv2.putText(img, text, (10,50), cv2.FONT_HERSHEY_PLAIN, 1, cvRed) 
                     cvImshow(windowName, img, rescale)
                     key = cv2.waitKey(wait)
                     if saveKey(key):
@@ -176,37 +182,37 @@
 
     def infoVideo(filename):
         '''Provides all available info on video '''
-        cvPropertyNames = {cv2.cv.CV_CAP_PROP_FORMAT: "format",
-                           cv2.cv.CV_CAP_PROP_FOURCC: "codec (fourcc)",
-                           cv2.cv.CV_CAP_PROP_FPS: "fps",
-                           cv2.cv.CV_CAP_PROP_FRAME_COUNT: "number of frames",
-                           cv2.cv.CV_CAP_PROP_FRAME_HEIGHT: "heigh",
-                           cv2.cv.CV_CAP_PROP_FRAME_WIDTH: "width",
-                           cv2.cv.CV_CAP_PROP_RECTIFICATION: "rectification",
-                           cv2.cv.CV_CAP_PROP_SATURATION: "saturation"}
+        cvPropertyNames = {cv2.CAP_PROP_FORMAT: "format",
+                           cv2.CAP_PROP_FOURCC: "codec (fourcc)",
+                           cv2.CAP_PROP_FPS: "fps",
+                           cv2.CAP_PROP_FRAME_COUNT: "number of frames",
+                           cv2.CAP_PROP_FRAME_HEIGHT: "heigh",
+                           cv2.CAP_PROP_FRAME_WIDTH: "width",
+                           cv2.CAP_PROP_RECTIFICATION: "rectification",
+                           cv2.CAP_PROP_SATURATION: "saturation"}
         capture = cv2.VideoCapture(filename)
         if capture.isOpened():
-            for cvprop in [#cv2.cv.CV_CAP_PROP_BRIGHTNESS
-                    #cv2.cv.CV_CAP_PROP_CONTRAST
-                    #cv2.cv.CV_CAP_PROP_CONVERT_RGB
-                    #cv2.cv.CV_CAP_PROP_EXPOSURE
-                    cv2.cv.CV_CAP_PROP_FORMAT,
-                    cv2.cv.CV_CAP_PROP_FOURCC,
-                    cv2.cv.CV_CAP_PROP_FPS,
-                    cv2.cv.CV_CAP_PROP_FRAME_COUNT,
-                    cv2.cv.CV_CAP_PROP_FRAME_HEIGHT,
-                    cv2.cv.CV_CAP_PROP_FRAME_WIDTH,
-                    #cv2.cv.CV_CAP_PROP_GAIN,
-                    #cv2.cv.CV_CAP_PROP_HUE
-                    #cv2.cv.CV_CAP_PROP_MODE
-                    #cv2.cv.CV_CAP_PROP_POS_AVI_RATIO
-                    #cv2.cv.CV_CAP_PROP_POS_FRAMES
-                    #cv2.cv.CV_CAP_PROP_POS_MSEC
-                    #cv2.cv.CV_CAP_PROP_RECTIFICATION,
-                    #cv2.cv.CV_CAP_PROP_SATURATION
+            for cvprop in [#cv2.CAP_PROP_BRIGHTNESS
+                    #cv2.CAP_PROP_CONTRAST
+                    #cv2.CAP_PROP_CONVERT_RGB
+                    #cv2.CAP_PROP_EXPOSURE
+                    cv2.CAP_PROP_FORMAT,
+                    cv2.CAP_PROP_FOURCC,
+                    cv2.CAP_PROP_FPS,
+                    cv2.CAP_PROP_FRAME_COUNT,
+                    cv2.CAP_PROP_FRAME_HEIGHT,
+                    cv2.CAP_PROP_FRAME_WIDTH,
+                    #cv2.CAP_PROP_GAIN,
+                    #cv2.CAP_PROP_HUE
+                    #cv2.CAP_PROP_MODE
+                    #cv2.CAP_PROP_POS_AVI_RATIO
+                    #cv2.CAP_PROP_POS_FRAMES
+                    #cv2.CAP_PROP_POS_MSEC
+                    #cv2.CAP_PROP_RECTIFICATION,
+                    #cv2.CAP_PROP_SATURATION
             ]:
                 prop = capture.get(cvprop)
-                if cvprop == cv2.cv.CV_CAP_PROP_FOURCC and prop > 0:
+                if cvprop == cv2.CAP_PROP_FOURCC and prop > 0:
                     prop = int2FOURCC(int(prop))
                 print('Video {}: {}'.format(cvPropertyNames[cvprop], prop))
         else:
@@ -214,16 +220,15 @@
 
     def getImagesFromVideo(videoFilename, firstFrameNum = 0, nFrames = 1, saveImage = False, outputPrefix = 'image'):
         '''Returns nFrames images from the video sequence'''
-        from math import floor, log10
         images = []
         capture = cv2.VideoCapture(videoFilename)
         if capture.isOpened():
-            rawCount = capture.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT)
+            rawCount = capture.get(cv2.CAP_PROP_FRAME_COUNT)
             if rawCount < 0:
                 rawCount = firstFrameNum+nFrames+1
             nDigits = int(floor(log10(rawCount)))+1
             ret = False
-            capture.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, firstFrameNum)
+            capture.set(cv2.CAP_PROP_POS_FRAMES, firstFrameNum)
             imgNum = 0
             while imgNum<nFrames:
                 ret, img = capture.read()
@@ -246,7 +251,7 @@
     def getFPS(videoFilename):
         capture = cv2.VideoCapture(videoFilename)
         if capture.isOpened():
-            fps = capture.get(cv2.cv.CV_CAP_PROP_FPS)
+            fps = capture.get(cv2.CAP_PROP_FPS)
             capture.release()
             return fps
         else:
@@ -283,12 +288,9 @@
 
     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 = {}):
         '''Displays the objects overlaid frame by frame over the video '''
-        from moving import userTypeNames
-        from math import ceil, log10
-
         capture = cv2.VideoCapture(videoFilename)
-        width = int(capture.get(cv2.cv.CV_CAP_PROP_FRAME_WIDTH))
-        height = int(capture.get(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT))
+        width = int(capture.get(cv2.CAP_PROP_FRAME_WIDTH))
+        height = int(capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
 
         windowName = 'frame'
         if rescale == 1.:
@@ -300,9 +302,8 @@
             key = -1
             ret = True
             frameNum = firstFrameNum
-            capture.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, firstFrameNum)
+            capture.set(cv2.CAP_PROP_POS_FRAMES, firstFrameNum)
             if lastFrameNumArg is None:
-                from sys import maxint
                 lastFrameNum = maxint
             else:
                 lastFrameNum = lastFrameNumArg
@@ -333,12 +334,12 @@
                                 imgcrop, yCropMin, yCropMax, xCropMin, xCropMax = imageBox(img, obj, frameNum, homography, width, height)
                                 cv2.rectangle(img, (xCropMin, yCropMin), (xCropMax, yCropMax), cvBlue, 1)
                             objDescription = '{} '.format(obj.num)
-                            if userTypeNames[obj.userType] != 'unknown':
-                                objDescription += userTypeNames[obj.userType][0].upper()
+                            if moving.userTypeNames[obj.userType] != 'unknown':
+                                objDescription += moving.userTypeNames[obj.userType][0].upper()
                             if len(annotations) > 0: # if we loaded annotations, but there is no match
                                 if frameNum not in toMatches[obj.getNum()]:
                                     objDescription += " FA"
-                            cv2.putText(img, objDescription, obj.projectedPositions[frameNum-obj.getFirstInstant()].asint().astuple(), cv2.cv.CV_FONT_HERSHEY_PLAIN, 1, cvColors[obj.getNum()])
+                            cv2.putText(img, objDescription, obj.projectedPositions[frameNum-obj.getFirstInstant()].asint().astuple(), cv2.FONT_HERSHEY_PLAIN, 1, cvColors[obj.getNum()])
                     # plot object bounding boxes
                     if frameNum in boundingBoxes.keys():
                         for rect in boundingBoxes[frameNum]:
@@ -351,7 +352,7 @@
                                     color = cvColors[gtMatches[gt.getNum()][frameNum]] # same color as object
                                 else:
                                     color = cvRed
-                                    cv2.putText(img, 'Miss', gt.topLeftPositions[frameNum-gt.getFirstInstant()].asint().astuple(), cv2.cv.CV_FONT_HERSHEY_PLAIN, 1, cvRed)
+                                    cv2.putText(img, 'Miss', gt.topLeftPositions[frameNum-gt.getFirstInstant()].asint().astuple(), cv2.FONT_HERSHEY_PLAIN, 1, cvRed)
                                 cv2.rectangle(img, gt.topLeftPositions[frameNum-gt.getFirstInstant()].asint().astuple(), gt.bottomRightPositions[frameNum-gt.getFirstInstant()].asint().astuple(), color)
                     # saving images and going to next
                     if not saveAllImages:
@@ -361,10 +362,10 @@
                         cv2.imwrite('image-{{:0{}}}.png'.format(nZerosFilename).format(frameNum), img)
                     frameNum += nFramesStep
                     if nFramesStep > 1:
-                        capture.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, frameNum)
+                        capture.set(cv2.CAP_PROP_POS_FRAMES, frameNum)
             cv2.destroyAllWindows()
         else:
-            print 'Cannot load file ' + videoFilename
+            print('Cannot load file ' + videoFilename)
 
     def computeHomographyFromPDTV(camera):
         '''Returns the homography matrix at ground level from PDTV camera
@@ -383,32 +384,27 @@
         map1 and map2 are the mapping functions from undistorted image
         to distorted (original image)
         map1(x,y) = originalx, originaly'''
-        from numpy import abs, logical_and, unravel_index, sum
-        from matplotlib.mlab import find
-        distx = abs(map1-x)
-        disty = abs(map2-y)
+        distx = npabs(map1-x)
+        disty = npabs(map2-y)
         indices = logical_and(distx<maxDistance, disty<maxDistance)
         closeCoordinates = unravel_index(find(indices), distx.shape) # returns i,j, ie y,x
         xWeights = 1-distx[indices]
         yWeights = 1-disty[indices]
-        return dot(xWeights, closeCoordinates[1])/sum(xWeights), dot(yWeights, closeCoordinates[0])/sum(yWeights)
+        return dot(xWeights, closeCoordinates[1])/npsum(xWeights), dot(yWeights, closeCoordinates[0])/npsum(yWeights)
 
     def undistortTrajectoryFromCVMapping(map1, map2, t):
         '''test 'perfect' inversion'''
-        from moving import Trajectory
-        from numpy import isnan
-        undistortedTrajectory = Trajectory()
+        undistortedTrajectory = moving.Trajectory()
         for i,p in enumerate(t):
             res = undistortedCoordinates(map1, map2, p.x,p.y)
             if not isnan(res).any():
                 undistortedTrajectory.addPositionXY(res[0], res[1])
             else:
-                print i,p,res
+                print('{} {} {}'.format(i,p,res))
         return undistortedTrajectory
 
     def computeInverseMapping(originalImageSize, map1, map2):
         'Computes inverse mapping from maps provided by cv2.initUndistortRectifyMap'
-        from numpy import ones, isnan
         invMap1 = -ones(originalImageSize)
         invMap2 = -ones(originalImageSize)
         for x in range(0,originalImageSize[1]):
@@ -432,7 +428,6 @@
             https://opencv-python-tutroals.readthedocs.org/en/latest/py_tutorials/py_calib3d/py_calibration/py_calibration.html
             Modified by Paul St-Aubin
             '''
-        from numpy import zeros, mgrid, float32, savetxt
         import glob, os
 
         # termination criteria
@@ -457,21 +452,22 @@
 
             # If found, add object points, image points (after refining them)
             if ret:
-                print 'Found pattern in '+fname
+                print('Found pattern in '+fname)
                 
-                if(secondPassSearch): 
+                if secondPassSearch:
                     corners = cv2.cornerSubPix(gray, corners, (11,11), (-1,-1), criteria)
 
                 objpoints.append(objp)
                 imgpoints.append(corners)
 
                 # Draw and display the corners
-                if(display):
+                if display:
                     img = cv2.drawChessboardCorners(img, (checkerBoardSize[1],checkerBoardSize[0]), corners, ret)
-                    if(img):
+                    if img is not None:
                         cv2.imshow('img',img)
                         cv2.waitKey(0)
-
+            else:
+                print('Pattern not found in '+fname)
         ## Close up image loading and calibrate
         cv2.destroyAllWindows()
         if len(objpoints) == 0 or len(imgpoints) == 0: 
@@ -533,9 +529,8 @@
     return invH
 
 def undistortTrajectory(invMap1, invMap2, positions):
-    from numpy import floor, ceil
-    floorPositions = floor(positions)
-    #ceilPositions = ceil(positions)
+    floorPositions = npfloor(positions)
+    #ceilPositions = npceil(positions)
     undistortedTrajectory = [[],[]]
     for i in xrange(len(positions[0])):
         x,y = None, None
@@ -563,7 +558,6 @@
         img1Points are used to compute the translation
 
         TODO add diagnostic if data is all over the place, and it most likely is not a translation (eg zoom, other non linear distortion)'''
-        from numpy import median, sum
 
         nextPoints = array([])
         (img2Points, status, track_error) = cv2.calcOpticalFlowPyrLK(img1, img2, img1Points, nextPoints, winSize=windowSize, maxLevel=level, criteria=criteria)
@@ -572,7 +566,7 @@
         for (k, (p1,p2)) in enumerate(zip(img1Points, img2Points)):
             if status[k] == 1:
                 dp = p2-p1
-                d = sum(dp**2)
+                d = npsum(dp**2)
                 if d < maxTranslation2:
                     delta.append(dp)
         if len(delta) >= minNMatches:
@@ -601,9 +595,6 @@
         return float32(features)
 
     def createHOGTrainingSet(imageDirectory, classLabel, rescaleSize = (64, 64), orientations=9, pixelsPerCell=(8, 8), cellsPerBlock=(2, 2), visualize=False, normalize=False):
-        from os import listdir
-        from matplotlib.pyplot import imread
-
         inputData = []
         for filename in listdir(imageDirectory):
             img = imread(imageDirectory+filename)
@@ -611,6 +602,6 @@
             inputData.append(features)
 
         nImages = len(inputData)
-        return array(inputData, dtype = float32), array([classLabel]*nImages, dtype = float32)
+        return array(inputData, dtype = float32), array([classLabel]*nImages)