# HG changeset patch # User Nicolas Saunier # Date 1708024192 18000 # Node ID 2aa56b101041a72a613c9cb23b0babeffab5803e # Parent c4c50678c85689d896f5dd2cae647beaa49b0d9d added mask functionality for dltrack diff -r c4c50678c856 -r 2aa56b101041 scripts/compute-clearmot.py --- a/scripts/compute-clearmot.py Thu Feb 15 14:09:23 2024 -0500 +++ b/scripts/compute-clearmot.py Thu Feb 15 14:09:52 2024 -0500 @@ -45,9 +45,9 @@ if args.maskFilename is not None: maskObjects = [] from matplotlib.pyplot import imread - mask = imread(args.maskFilename) - if len(mask) > 1: - mask = mask[:,:,0] + mask = imread(args.maskFilename, cv2.IMREAD_GRAYSCALE) + #if len(mask) > 1: if loaded as RGB + # mask = mask[:,:,0] for obj in objects: maskObjects += obj.getObjectsInMask(mask, invHomography, 10) # TODO add option to keep object if at least one feature in mask objects = maskObjects diff -r c4c50678c856 -r 2aa56b101041 scripts/dltrack.py --- a/scripts/dltrack.py Thu Feb 15 14:09:23 2024 -0500 +++ b/scripts/dltrack.py Thu Feb 15 14:09:52 2024 -0500 @@ -26,14 +26,14 @@ parser.add_argument('-m', dest = 'detectorFilename', help = 'name of the detection model file', required = True) parser.add_argument('-t', dest = 'trackerFilename', help = 'name of the tracker file', required = True) parser.add_argument('-o', dest = 'homographyFilename', help = 'filename of the homography matrix') -#parser.add_argument('-k', dest = 'maskFilename', help = 'name of the mask file') +parser.add_argument('-k', dest = 'maskFilename', help = 'name of the mask file') parser.add_argument('--undistort', dest = 'undistort', help = 'undistort the video', action = 'store_true') parser.add_argument('--intrinsic', dest = 'intrinsicCameraMatrixFilename', help = 'name of the intrinsic camera file') parser.add_argument('--distortion-coefficients', dest = 'distortionCoefficients', help = 'distortion coefficients', nargs = '*', type = float) parser.add_argument('--display', dest = 'display', help = 'show the raw detection and tracking results', action = 'store_true') parser.add_argument('--no-image-coordinates', dest = 'notSavingImageCoordinates', help = 'not saving the raw detection and tracking results', action = 'store_true') parser.add_argument('-f', dest = 'firstFrameNum', help = 'number of first frame number to process', type = int, default = 0) -parser.add_argument('-l', dest = 'lastFrameNum', help = 'number of last frame number to process', type = int, default = float('Inf')) +parser.add_argument('-l', dest = 'lastFrameNum', help = 'number of last frame number to process', type = int, default = inf) parser.add_argument('--conf', dest = 'confidence', help = 'object confidence threshold for detection', type = float, default = 0.25) parser.add_argument('--bike-prop', dest = 'bikeProportion', help = 'minimum proportion of time a person classified as bike or motorbike to be classified as cyclist', type = float, default = 0.2) parser.add_argument('--cyclist-iou', dest = 'cyclistIou', help = 'IoU threshold to associate a bike and ped bounding box', type = float, default = 0.15) @@ -56,7 +56,13 @@ elif args.configFilename is not None: lastFrameNum = params.lastFrameNum else: - lastFrameNum = inf + lastFrameNum = args.lastFrameNum +if args.maskFilename is not None: + mask = cv2.imread(args.maskFilename, cv2.IMREAD_GRAYSCALE) +elif params.maskFilename is not None: + mask = cv2.imread(params.maskFilename, cv2.IMREAD_GRAYSCALE) +else: + mask = None # TODO use mask, remove short objects, smooth @@ -86,32 +92,37 @@ print('Input {} could not be read. Exiting'.format(args.videoFilename)) import sys; sys.exit() -results = model.track(frame, tracker=args.trackerFilename, classes=list(moving.cocoTypeNames.keys()), conf = args.confidence, persist=True, verbose=False) +results = model.track(source=frame, tracker=args.trackerFilename, classes=list(moving.cocoTypeNames.keys()), conf=args.confidence, persist=True, verbose=False) while capture.isOpened() and success and frameNum <= lastFrameNum: result = results[0] if frameNum %10 == 0: print(frameNum, len(result.boxes), 'objects') for box in result.boxes: - if box.id is not None: # None are objects with low confidence - num = int(box.id.item()) - if num in objects: - objects[num].timeInterval.last = frameNum - objects[num].features[0].timeInterval.last = frameNum - objects[num].features[1].timeInterval.last = frameNum - objects[num].bboxes[frameNum] = copy(box.xyxy) - objects[num].userTypes.append(moving.coco2Types[int(box.cls.item())]) - objects[num].features[0].tmpPositions[frameNum] = moving.Point(box.xyxy[0,0].item(), box.xyxy[0,1].item()) # min - objects[num].features[1].tmpPositions[frameNum] = moving.Point(box.xyxy[0,2].item(), box.xyxy[0,3].item()) # max - else: - inter = moving.TimeInterval(frameNum, frameNum) - objects[num] = moving.MovingObject(num, inter) - objects[num].bboxes = {frameNum: copy(box.xyxy)} - objects[num].userTypes = [moving.coco2Types[int(box.cls.item())]] - objects[num].features = [moving.MovingObject(featureNum, copy(inter)), moving.MovingObject(featureNum+1, copy(inter))] - objects[num].featureNumbers = [featureNum, featureNum+1] - objects[num].features[0].tmpPositions = {frameNum: moving.Point(box.xyxy[0,0].item(), box.xyxy[0,1].item())} - objects[num].features[1].tmpPositions = {frameNum: moving.Point(box.xyxy[0,2].item(), box.xyxy[0,3].item())} - featureNum += 2 + if box.id is not None:# None are objects with low confidence + xyxy = copy(box.xyxy) + minPoint = moving.Point(xyxy[0,0].item(), xyxy[0,1].item()) + maxPoint = moving.Point(xyxy[0,2].item(), xyxy[0,3].item()) + center = (minPoint+maxPoint).divide(2.).asint() + if mask is None or mask[center.y, center.x] > 0: + num = int(box.id.item()) + if num in objects: + objects[num].timeInterval.last = frameNum + objects[num].features[0].timeInterval.last = frameNum + objects[num].features[1].timeInterval.last = frameNum + objects[num].bboxes[frameNum] = xyxy + objects[num].userTypes.append(moving.coco2Types[int(box.cls.item())]) + objects[num].features[0].tmpPositions[frameNum] = minPoint # min + objects[num].features[1].tmpPositions[frameNum] = maxPoint # max + else: + inter = moving.TimeInterval(frameNum, frameNum) + objects[num] = moving.MovingObject(num, inter) + objects[num].bboxes = {frameNum: copy(xyxy)} + objects[num].userTypes = [moving.coco2Types[int(box.cls.item())]] + objects[num].features = [moving.MovingObject(featureNum, copy(inter)), moving.MovingObject(featureNum+1, copy(inter))] + objects[num].featureNumbers = [featureNum, featureNum+1] + objects[num].features[0].tmpPositions = {frameNum: minPoint} + objects[num].features[1].tmpPositions = {frameNum: maxPoint} + featureNum += 2 if args.display: cvutils.cvImshow(windowName, result.plot()) # original image in orig_img key = cv2.waitKey() @@ -119,7 +130,9 @@ break frameNum += 1 success, frame = capture.read() - results = model.track(frame, persist=True) + results = model.track(source=frame, persist=True) +capture.release() +cv2.destroyAllWindows() # classification for num, obj in objects.items(): @@ -221,10 +234,7 @@ else: t = [] for instant in obj.getTimeInterval(): - points = [] - for f in features: - if f.existsAtInstant(instant): - points.append(f.getPositionAtInstant(instant)) + points = [f.getPositionAtInstant(instant) for f in features if f.existsAtInstant(instant)] t.append(moving.Point.agg(points, np.mean).aslist()) #t = sum([f.getPositions().asArray() for f in features])/len(features) #t = (moving.Trajectory.add(t1, t2)*0.5).asArray() diff -r c4c50678c856 -r 2aa56b101041 scripts/undistort-video.py --- a/scripts/undistort-video.py Thu Feb 15 14:09:23 2024 -0500 +++ b/scripts/undistort-video.py Thu Feb 15 14:09:52 2024 -0500 @@ -39,7 +39,7 @@ height = int(capture.get(cv2.CAP_PROP_FRAME_HEIGHT)) [map1, map2], newCameraMatrix = cvutils.computeUndistortMaps(width, height, args.undistortedImageMultiplication, intrinsicCameraMatrix, args.distortionCoefficients) if args.maskFilename is not None: - mask = cv2.imread(args.maskFilename) + mask = cv2.imread(args.maskFilename, cv2.IMREAD_GRAYSCALE) undistortedMask = cv2.remap(mask, map1, map2, interpolation=cv2.INTER_LINEAR)/255 if capture.isOpened(): diff -r c4c50678c856 -r 2aa56b101041 trafficintelligence/moving.py --- a/trafficintelligence/moving.py Thu Feb 15 14:09:23 2024 -0500 +++ b/trafficintelligence/moving.py Thu Feb 15 14:09:52 2024 -0500 @@ -2,7 +2,7 @@ '''Libraries for moving objects, trajectories...''' import copy -from math import sqrt, atan2, cos, sin +from math import sqrt, atan2, cos, sin, inf from numpy import median, mean, array, arange, zeros, ones, hypot, NaN, std, floor, ceil, float32, argwhere, minimum, issubdtype, integer as npinteger, percentile from matplotlib.pyplot import plot, text, arrow @@ -295,7 +295,7 @@ return (self.x, self.y) def asint(self): - return Point(int(self.x), int(self.y)) + return Point(int(round(self.x)), int(round(self.y))) if shapelyAvailable: def asShapely(self): @@ -2054,7 +2054,7 @@ self.setUserType(utils.argmaxDict(userTypeProbabilities)) return userTypeProbabilities - def initClassifyUserTypeHoGSVM(self, aggregationFunc, pedBikeCarSVM, bikeCarSVM = None, pedBikeSpeedThreshold = float('Inf'), bikeCarSpeedThreshold = float('Inf'), nInstantsIgnoredAtEnds = 0, homography = None, intrinsicCameraMatrix = None, distortionCoefficients = None): + def initClassifyUserTypeHoGSVM(self, aggregationFunc, pedBikeCarSVM, bikeCarSVM = None, pedBikeSpeedThreshold = inf, bikeCarSpeedThreshold = float('Inf'), nInstantsIgnoredAtEnds = 0, homography = None, intrinsicCameraMatrix = None, distortionCoefficients = None): '''Initializes the data structures for classification TODO? compute speed for longest feature?''' diff -r c4c50678c856 -r 2aa56b101041 trafficintelligence/storage.py --- a/trafficintelligence/storage.py Thu Feb 15 14:09:23 2024 -0500 +++ b/trafficintelligence/storage.py Thu Feb 15 14:09:52 2024 -0500 @@ -1610,6 +1610,8 @@ distortionCoefficients = getValuesFromINIFile(filename, 'distortion-coefficients', '=') self.distortionCoefficients = [float(x) for x in distortionCoefficients] self.undistortedImageMultiplication = config.getfloat(self.sectionHeader, 'undistorted-size-multiplication') + self.maskFilename = utils.getRelativeFilename(parentPath, config.get(self.sectionHeader, 'mask-filename')) + self.undistort = config.getboolean(self.sectionHeader, 'undistort') self.firstFrameNum = config.getint(self.sectionHeader, 'frame1') self.videoFrameRate = config.getfloat(self.sectionHeader, 'video-fps')