Mercurial Hosting > traffic-intelligence
changeset 1271:b2f90cada58f
removed complex merging of bikes and peds, may result in more fragmentation
author | Nicolas Saunier <nicolas.saunier@polymtl.ca> |
---|---|
date | Fri, 14 Jun 2024 15:56:01 -0400 |
parents | 20a5e1292321 |
children | 785c86013d2c 655a1646f0d5 |
files | scripts/dltrack.py |
diffstat | 1 files changed, 45 insertions(+), 40 deletions(-) [+] |
line wrap: on
line diff
--- a/scripts/dltrack.py Mon Jun 10 16:44:19 2024 -0400 +++ b/scripts/dltrack.py Fri Jun 14 15:56:01 2024 -0400 @@ -38,7 +38,7 @@ 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) parser.add_argument('--cyclist-match-prop', dest = 'cyclistMatchingProportion', help = 'minimum proportion of time a bike exists and is associated with a pedestrian to be merged as cyclist', type = float, default = 0.3) -parser.add_argument('--max-temp-overal', dest = 'maxTemporalOverlap', help = 'maximum proportion of time to merge 2 bikes associated with same pedestrian', type = float, default = 0.05) +#parser.add_argument('--max-temp-overal', dest = 'maxTemporalOverlap', help = 'maximum proportion of time to merge 2 bikes associated with same pedestrian', type = float, default = 0.05) args = parser.parse_args() params, videoFilename, databaseFilename, homography, invHomography, intrinsicCameraMatrix, distortionCoefficients, undistortedImageMultiplication, undistort, firstFrameNum = storage.processVideoArguments(args) @@ -65,8 +65,10 @@ mask = None if params is not None: smoothingHalfWidth = params.smoothingHalfWidth + minObjectDuration = params.minFeatureTime else: smoothingHalfWidth = None + minObjectDuration = 3 # TODO use mask, remove short objects, smooth @@ -142,7 +144,7 @@ # classification shortObjectNumbers = [] for num, obj in objects.items(): - if obj.length() < 3: + if obj.length() < minObjectDuration: shortObjectNumbers.append(num) else: obj.setUserType(utils.mostCommon(obj.userTypes)) # improve? mix with speed? @@ -181,39 +183,39 @@ # before matching, scan for pedestrians with good non-overlapping temporal match with different bikes for pedInd in range(costs.shape[1]): nMatchedBikes = (costs[:,pedInd] < -args.cyclistMatchingProportion).sum() - if nMatchedBikes == 0: # peds that have no bike matching: see if they have been classified as bikes sometimes + if nMatchedBikes == 0: # peds that have no bike matching: see if they have been classified as bikes sometimes (more than args.bikeProportion) userTypeStats = Counter(obj.userTypes) if (moving.userType2Num['cyclist'] in userTypeStats or (moving.userType2Num['motorcyclist'] in userTypeStats and moving.userType2Num['cyclist'] in userTypeStats and userTypeStats[moving.userType2Num['motorcyclist']]<=userTypeStats[moving.userType2Num['cyclist']])) and userTypeStats[moving.userType2Num['motorcyclist']]+userTypeStats[moving.userType2Num['cyclist']] > args.bikeProportion*userTypeStats.total(): # verif if not turning all motorbike into cyclists obj.setUserType(moving.userType2Num['cyclist']) - elif nMatchedBikes > 1: # try to merge bikes first - twIndices = np.nonzero(costs[:,pedInd] < -args.cyclistMatchingProportion)[0] - # we have to compute temporal overlaps of all 2 wheels among themselves, then remove the ones with the most overlap (sum over column) one by one until there is little left - nTwoWheels = len(twIndices) - twTemporalOverlaps = np.zeros((nTwoWheels,nTwoWheels)) - for i in range(nTwoWheels): - for j in range(i): - twi = objects[twowheels[twIndices[i]]] - twj = objects[twowheels[twIndices[j]]] - twTemporalOverlaps[i,j] = len(set(twi.bboxes).intersection(set(twj.bboxes)))/max(len(twi.bboxes), len(twj.bboxes)) - #twTemporalOverlaps[j,i] = twTemporalOverlaps[i,j] - tw2merge = list(range(nTwoWheels)) - while len(tw2merge)>0 and (twTemporalOverlaps[np.ix_(tw2merge, tw2merge)] > args.maxTemporalOverlap).sum(0).max() >= 2: - i = (twTemporalOverlaps[np.ix_(tw2merge, tw2merge)] > args.maxTemporalOverlap).sum(0).argmax() - del tw2merge[i] - twIndices = [twIndices[i] for i in tw2merge] - tw1 = objects[twowheels[twIndices[0]]] - twCost = costs[twIndices[0],:]*tw1.nBBoxes - nBBoxes = tw1.nBBoxes - for twInd in twIndices[1:]: - mergeObjects(tw1, objects[twowheels[twInd]]) - twCost = twCost + costs[twInd,:]*objects[twowheels[twInd]].nBBoxes - nBBoxes += objects[twowheels[twInd]].nBBoxes - twIndicesToKeep = list(range(costs.shape[0])) - for twInd in twIndices[1:]: - twIndicesToKeep.remove(twInd) - del objects[twowheels[twInd]] - twowheels = [twowheels[i] for i in twIndicesToKeep] - costs = costs[twIndicesToKeep,:] + # elif nMatchedBikes > 1: # try to merge bikes first + # twIndices = np.nonzero(costs[:,pedInd] < -args.cyclistMatchingProportion)[0] + # # we have to compute temporal overlaps of all 2 wheels among themselves, then remove the ones with the most overlap (sum over column) one by one until there is little left + # nTwoWheels = len(twIndices) + # twTemporalOverlaps = np.zeros((nTwoWheels,nTwoWheels)) + # for i in range(nTwoWheels): + # for j in range(i): + # twi = objects[twowheels[twIndices[i]]] + # twj = objects[twowheels[twIndices[j]]] + # twTemporalOverlaps[i,j] = len(set(twi.bboxes).intersection(set(twj.bboxes)))/max(len(twi.bboxes), len(twj.bboxes)) + # #twTemporalOverlaps[j,i] = twTemporalOverlaps[i,j] + # tw2merge = list(range(nTwoWheels)) + # while len(tw2merge)>0 and (twTemporalOverlaps[np.ix_(tw2merge, tw2merge)] > args.maxTemporalOverlap).sum(0).max() >= 2: + # i = (twTemporalOverlaps[np.ix_(tw2merge, tw2merge)] > args.maxTemporalOverlap).sum(0).argmax() + # del tw2merge[i] + # twIndices = [twIndices[i] for i in tw2merge] + # tw1 = objects[twowheels[twIndices[0]]] + # twCost = costs[twIndices[0],:]*tw1.nBBoxes + # nBBoxes = tw1.nBBoxes + # for twInd in twIndices[1:]: + # mergeObjects(tw1, objects[twowheels[twInd]]) + # twCost = twCost + costs[twInd,:]*objects[twowheels[twInd]].nBBoxes + # nBBoxes += objects[twowheels[twInd]].nBBoxes + # twIndicesToKeep = list(range(costs.shape[0])) + # for twInd in twIndices[1:]: + # twIndicesToKeep.remove(twInd) + # del objects[twowheels[twInd]] + # twowheels = [twowheels[i] for i in twIndicesToKeep] + # costs = costs[twIndicesToKeep,:] twIndices, matchingPedIndices = linear_sum_assignment(costs) for twInd, pedInd in zip(twIndices, matchingPedIndices): # caution indices in the cost matrix @@ -222,8 +224,11 @@ ped = objects[pedestrians[pedInd]] mergeObjects(tw, ped) del objects[pedestrians[pedInd]] + # link ped to each assigned bike, remove bike from cost (and ped is temporal match is high) + #TODO Verif overlap piéton vélo : si long hors overlap, changement mode (trouver exemples) - + # TODO continue assigning if leftover bikes (if non temporally overlapping with existing bikes assigned to ped) + # interpolate and save image coordinates for num, obj in objects.items(): for f in obj.getFeatures(): @@ -233,7 +238,7 @@ f.positions = moving.Trajectory.fromPointList(list(f.tmpPositions.values())) if not args.notSavingImageCoordinates: storage.saveTrajectoriesToSqlite(utils.removeExtension(args.databaseFilename)+'-bb.sqlite', list(objects.values()), 'object') -# project, smooth and save +# project and smooth for num, obj in objects.items(): features = obj.getFeatures() # possible to save bottom pedestrians? not consistent with other users @@ -251,13 +256,13 @@ #t = (moving.Trajectory.add(t1, t2)*0.5).asArray() projected = cvutils.imageToWorldProject(np.array(t).T, intrinsicCameraMatrix, distortionCoefficients, homography) featureNum = features[0].getNum() - obj.features=[moving.MovingObject(featureNum, obj.getTimeInterval(), moving.Trajectory(projected.tolist()))] + feature = moving.MovingObject(featureNum, obj.getTimeInterval(), moving.Trajectory(projected.tolist())) + if smoothingHalfWidth is not None: # smoothing + feature.smoothPositions(smoothingHalfWidth, replace = True)#f.positions = f.getPositions().filterMovingWindow(smoothingHalfWidth) + feature.computeVelocities() + obj.features=[feature] obj.featureNumbers = [featureNum] -if smoothingHalfWidth is not None: # smoothing - for num, obj in objects.items(): - for f in obj.getFeatures(): - f.smoothPositions(smoothingHalfWidth, replace = True)#f.positions = f.getPositions().filterMovingWindow(smoothingHalfWidth) - f.computeVelocities() +#saving storage.saveTrajectoriesToSqlite(args.databaseFilename, list(objects.values()), 'object')