Mercurial > hg > nsaunier > traffic-intelligence
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)
