def TracksPx_to_TracksMetric(filteredFeatures, minimumTrackedFeatures, interior_orient, eor_mat, unit_gcp, frame_rate_cam, TrackEveryNthFrame, waterlevel_pt, directoryOutput, dir_imgs, img_list, veloStdThresh, lspiv): #scale tracks in image space to tracks in object space to get flow velocity in m/s waterlevel = waterlevel_pt image = cv2.imread(dir_imgs + img_list[0], 0) if lspiv: xy_start_tr = np.asarray(filteredFeatures[['x','y']]) xy_tr = np.asarray(filteredFeatures[['x_tr', 'y_tr']]) id_features = np.asarray(filteredFeatures['id']) else: #get first and last position in image space of each tracked feature filteredFeatures_1st = filteredFeatures.groupby('id', as_index=False).head(1) filteredFeatures_last = filteredFeatures.groupby('id', as_index=False).tail(1) filteredFeatures_count = np.asarray(filteredFeatures.groupby('id', as_index=False).count())[:,2] xy_start_tr = np.asarray(filteredFeatures_1st[['x', 'y']]) xy_tr = np.asarray(filteredFeatures_last[['x_tr', 'y_tr']]) #intersect first and last position with waterlevel XY_start_tr = refF.LinePlaneIntersect(xy_start_tr, waterlevel, interior_orient, eor_mat, unit_gcp) / unit_gcp XY_tr = refF.LinePlaneIntersect(xy_tr, waterlevel, interior_orient, eor_mat, unit_gcp) / unit_gcp #get corresponding distance in object space dist_metric = np.sqrt(np.square(XY_start_tr[:,0] - XY_tr[:,0]) + (np.square(XY_start_tr[:,1] - XY_tr[:,1]))) #get corresponding temporal observation span if lspiv: trackingDuration = np.ones((id_features.shape[0],1), dtype=np.float) * TrackEveryNthFrame / np.float(frame_rate_cam) else: frame_rate_cam = np.ones((filteredFeatures_count.shape[0],1), dtype=np.float) * np.float(frame_rate_cam) nbrTrackedFrames = TrackEveryNthFrame * (filteredFeatures_count+1) trackingDuration = nbrTrackedFrames.reshape(frame_rate_cam.shape[0],1) / frame_rate_cam #get velocity velo = dist_metric.reshape(trackingDuration.shape[0],1) / trackingDuration if lspiv: filteredFeaturesPIV = pd.DataFrame(id_features, columns=['id']) filteredFeaturesPIV = filterFeatureOrganise(filteredFeaturesPIV, XY_start_tr, XY_tr, xy_tr, dist_metric, velo, False, None, filteredFeatures[['x','y']]) drawF.draw_tracks(filteredFeaturesPIV.groupby('id', as_index=False).mean(), image, directoryOutput, 'TracksReferenced_rawPIV.jpg', 'velo', True) filteredFeaturesPIV.to_csv(directoryOutput + 'TracksReferenced_rawPIV.txt', sep='\t', index=False) #filter outliers considering mean and std dev for each grid cell filteredFeaturesPIV.loc[:,'veloMean'] = pd.Series(np.empty((len(filteredFeaturesPIV)))) filteredFeaturesPIV.loc[:,'veloStd'] = pd.Series(np.empty((len(filteredFeaturesPIV)))) filteredFeatureMean = filteredFeaturesPIV.groupby('id', as_index=False).velo.mean() filteredFeaturesStd = filteredFeaturesPIV.groupby('id', as_index=False).velo.std() filteredFeaturesId = filteredFeaturesPIV.groupby('id', as_index=False).id.mean() featureCount = 0 while featureCount < len(filteredFeaturesId)-1: filteredFeaturesPIV.loc[filteredFeaturesPIV.id == filteredFeaturesId.loc[featureCount], 'veloMean'] = filteredFeatureMean.loc[featureCount,'velo'] filteredFeaturesPIV.loc[filteredFeaturesPIV.id == filteredFeaturesId.loc[featureCount], 'veloStd'] = filteredFeaturesStd.loc[featureCount,'velo'] featureCount = featureCount + 1 filteredFeaturesPIV.loc[:,'threshPos'] = filteredFeaturesPIV.veloMean + 5 * filteredFeaturesPIV.veloStd filteredFeaturesPIV.loc[:,'threshNeg'] = filteredFeaturesPIV.veloMean - 5 * filteredFeaturesPIV.veloStd filteredFeaturesPIV = filteredFeaturesPIV[filteredFeaturesPIV.velo < filteredFeaturesPIV.threshPos] filteredFeaturesPIV = filteredFeaturesPIV[filteredFeaturesPIV.velo > filteredFeaturesPIV.threshNeg] #also filter based on direction #... filteredFeaturesPIV_grouped = filteredFeaturesPIV.groupby('id', as_index=False).mean() filteredFeaturesCount = filteredFeaturesPIV.groupby('id', as_index=False).count() filteredFeaturesPIV_grouped.loc[:,'count'] = filteredFeaturesCount.loc[:,'velo'] filteredFeaturesPIV_grouped = filteredFeaturesPIV_grouped.drop(columns=['veloMean','veloStd','threshPos','threshNeg']) filteredFeatures = filteredFeaturesPIV_grouped else: filteredFeatures_1st = filterFeatureOrganise(filteredFeatures_1st, XY_start_tr, XY_tr, xy_tr, dist_metric, velo, True, filteredFeatures_count) filteredFeatures = filteredFeatures_1st #write referenced tracking results to file print('nbr of tracked features: ' + str(filteredFeatures.shape[0]) + '\n') filteredFeatures.to_csv(directoryOutput + 'TracksReferenced_raw.txt', sep='\t', index=False) drawF.draw_tracks(filteredFeatures, image, directoryOutput, 'TracksReferenced_raw.jpg', 'velo', True) #filter for outlier velocities MeanVeloAll = filteredFeatures.velo.mean() StdVeloAll = filteredFeatures.velo.std() threshVelo_Pos = MeanVeloAll + veloStdThresh * StdVeloAll threshVelo_Neg = MeanVeloAll - veloStdThresh * StdVeloAll filteredFeatures = filteredFeatures[filteredFeatures.velo < threshVelo_Pos] filteredFeatures = filteredFeatures[filteredFeatures.velo > threshVelo_Neg] #write filtered tracking results to file and draw final tracking results to image print('nbr of final tracked features: ' + str(filteredFeatures.shape[0]) + '\n') filteredFeatures.to_csv(directoryOutput + 'TracksFiltered.txt', sep='\t', index=False) drawF.draw_tracks(filteredFeatures, image, directoryOutput, 'TracksFiltered.jpg', 'velo', True)
def TracksPx_to_TracksMetric(filteredFeatures, interior_orient, eor_mat, unit_gcp, frame_rate_cam, TrackEveryNthFrame, waterlevel_pt, directoryOutput, img_name, veloStdThresh, lspiv, cellsizeFilter, searchMask): #scale tracks in image space to tracks in object space to get flow velocity in m/s waterlevel = waterlevel_pt image = cv2.imread(img_name, 0) if lspiv: xy_start_tr = np.asarray(filteredFeatures[['x', 'y']]) xy_tr = np.asarray(filteredFeatures[['x_tr', 'y_tr']]) id_features = np.asarray(filteredFeatures['id']) else: #get first and last position in image space of each tracked feature filteredFeatures_1st = filteredFeatures.groupby('id', as_index=False).head(1) filteredFeatures_last = filteredFeatures.groupby( 'id', as_index=False).tail(1) filteredFeatures_count = np.asarray( filteredFeatures.groupby('id', as_index=False).count())[:, 2] xy_start_tr = np.asarray(filteredFeatures_1st[['x', 'y']]) xy_tr = np.asarray(filteredFeatures_last[['x_tr', 'y_tr']]) #intersect first and last position with waterlevel XY_start_tr = refF.LinePlaneIntersect( xy_start_tr, waterlevel, interior_orient, eor_mat, unit_gcp) / unit_gcp XY_tr = refF.LinePlaneIntersect(xy_tr, waterlevel, interior_orient, eor_mat, unit_gcp) / unit_gcp #get corresponding distance in object space dist_metric = np.sqrt( np.square(XY_start_tr[:, 0] - XY_tr[:, 0]) + (np.square(XY_start_tr[:, 1] - XY_tr[:, 1]))) #get corresponding temporal observation span if lspiv: trackingDuration = np.ones( (id_features.shape[0], 1), dtype=np.float) * TrackEveryNthFrame / np.float(frame_rate_cam) else: frame_rate_cam = np.ones((filteredFeatures_count.shape[0], 1), dtype=np.float) * np.float(frame_rate_cam) nbrTrackedFrames = TrackEveryNthFrame * (filteredFeatures_count + 1) trackingDuration = nbrTrackedFrames.reshape(frame_rate_cam.shape[0], 1) / frame_rate_cam #get velocity velo = dist_metric.reshape(trackingDuration.shape[0], 1) / trackingDuration if lspiv: filteredFeaturesPIV = pd.DataFrame(id_features, columns=['id']) filteredFeaturesPIV = filterFeatureOrganise( filteredFeaturesPIV, XY_start_tr, XY_tr, xy_tr, dist_metric, velo, False, None, filteredFeatures[['x', 'y']]) drawF.draw_tracks( filteredFeaturesPIV.groupby('id', as_index=False).mean(), image, directoryOutput, 'TracksReferenced_raw_PIV.jpg', 'velo', True) filteredFeaturesPIVRawOut = filteredFeaturesPIV[[ 'X', 'Y', 'Z', 'velo', 'dist_metric' ]] filteredFeaturesPIVRawOut.columns = ['X', 'Y', 'Z', 'velo', 'dist'] filteredFeaturesPIVRawOut.rename(columns={"dist_metric": "dist"}) filteredFeaturesPIVRawOut.to_csv(directoryOutput + 'TracksReferenced_raw_PIV.txt', sep='\t', index=False) del filteredFeaturesPIVRawOut #write referenced tracking results to file print('nbr of tracked features: ' + str(filteredFeatures.shape[0]) + '\n') #filter outliers considering mean and std dev for each grid cell filteredFeaturesPIV.loc[:, 'veloMean'] = pd.Series( np.empty((len(filteredFeaturesPIV)))) filteredFeaturesPIV.loc[:, 'veloStd'] = pd.Series( np.empty((len(filteredFeaturesPIV)))) filteredFeatureMean = filteredFeaturesPIV.groupby( 'id', as_index=False).velo.mean() filteredFeaturesStd = filteredFeaturesPIV.groupby( 'id', as_index=False).velo.std() filteredFeaturesPIV["id_copy"] = filteredFeaturesPIV.id filteredFeaturesId = filteredFeaturesPIV.groupby( 'id_copy', as_index=False).id.mean() filteredFeaturesId = filteredFeaturesId.id featureCount = 0 while featureCount < len(filteredFeaturesId) - 1: filteredFeaturesPIV.loc[ filteredFeaturesPIV.id == filteredFeaturesId.loc[featureCount], 'veloMean'] = filteredFeatureMean.loc[featureCount, 'velo'] filteredFeaturesPIV.loc[ filteredFeaturesPIV.id == filteredFeaturesId.loc[featureCount], 'veloStd'] = filteredFeaturesStd.loc[featureCount, 'velo'] featureCount = featureCount + 1 filteredFeaturesPIV.loc[:, 'threshPos'] = filteredFeaturesPIV.veloMean + veloStdThresh * filteredFeaturesPIV.veloStd filteredFeaturesPIV.loc[:, 'threshNeg'] = filteredFeaturesPIV.veloMean - veloStdThresh * filteredFeaturesPIV.veloStd filteredFeaturesPIV = filteredFeaturesPIV[ filteredFeaturesPIV.velo < filteredFeaturesPIV.threshPos] filteredFeaturesPIV = filteredFeaturesPIV[ filteredFeaturesPIV.velo > filteredFeaturesPIV.threshNeg] filteredFeaturesPIV_grouped = filteredFeaturesPIV.groupby( 'id', as_index=False).mean() filteredFeaturesCount = filteredFeaturesPIV.groupby( 'id', as_index=False).count() filteredFeaturesPIV_grouped.loc[:, 'count'] = filteredFeaturesCount.loc[:, 'velo'] filteredFeaturesPIV_grouped = filteredFeaturesPIV_grouped.drop( columns=['veloMean', 'veloStd', 'threshPos', 'threshNeg']) filteredFeatures = filteredFeaturesPIV_grouped drawF.draw_tracks(filteredFeatures, image, directoryOutput, 'TracksFiltered_PIV.jpg', 'velo', True) filteredFeaturesPIVOut = filteredFeatures[[ 'X', 'Y', 'Z', 'velo', 'dist_metric' ]] filteredFeaturesPIVOut.columns = ['X', 'Y', 'Z', 'velo', 'dist'] filteredFeaturesPIVOut.rename(columns={"dist_metric": "dist"}) filteredFeaturesPIVOut.to_csv(directoryOutput + 'TracksFiltered_PIV.txt', sep='\t', index=False) del filteredFeaturesPIVOut else: filteredFeatures_1st = filterFeatureOrganise(filteredFeatures_1st, XY_start_tr, XY_tr, xy_tr, dist_metric, velo, True, filteredFeatures_count) filteredFeatures = filteredFeatures_1st.copy() filteredFeatures = filteredFeatures.reset_index(drop=True) filteredFeaturesRawPTVOut = filteredFeatures[[ 'X', 'Y', 'Z', 'velo', 'dist_metric', 'count' ]] filteredFeaturesRawPTVOut.columns = [ 'X', 'Y', 'Z', 'velo', 'dist', 'count' ] filteredFeaturesRawPTVOut.to_csv(directoryOutput + 'TracksReferenced_raw_PTV.txt', sep='\t', index=False) del filteredFeaturesRawPTVOut drawF.draw_tracks(filteredFeatures, image, directoryOutput, 'TracksReferenced_raw_PTV.jpg', 'velo', True) #write referenced tracking results to file print('nbr of tracked features: ' + str(filteredFeatures.shape[0]) + '\n') '''''' if not cellsizeFilter == 0: #filter outliers area-based with regular raster xy_cell = filterF.DefineRFeatures_forRasterbasedFilter( image, searchMask, cellsizeFilter * 4) XYZ_cell = refF.LinePlaneIntersect(xy_cell, waterlevel, interior_orient, eor_mat, unit_gcp) / unit_gcp XYZxy = pd.DataFrame(np.hstack((XYZ_cell, xy_cell))) XYZxy.columns = ['X', 'Y', 'Z', 'x', 'y'] XYZxy['id'] = range(1, len(XYZxy) + 1) filteredFeaturesRaster = filterF.NN_filter(filteredFeatures, XYZxy, cellsizeFilter * 4, False) filteredFeaturesRaster = filteredFeaturesRaster.reset_index( drop=True) del XYZxy drawF.draw_tracks(filteredFeaturesRaster, image, directoryOutput, 'filteredTracks_raster_PTV.jpg', 'velo', True) filteredFeaturesRaster = filteredFeaturesRaster[[ 'X', 'Y', 'Z', 'velo', 'dist', 'count' ]] filteredFeaturesRaster.to_csv(directoryOutput + 'tracksFiltered_rasterBased_PTV.txt', sep='\t', index=False) del filteredFeaturesRaster #filter outliers area-based with features in proximity filteredFeaturesLocally = filterF.NN_filter(filteredFeatures, filteredFeatures, cellsizeFilter, False) drawF.draw_tracks(filteredFeaturesLocally, image, directoryOutput, 'filteredTracks_locally_PTV.jpg', 'velo', True) filteredFeaturesLocally = filteredFeaturesLocally[[ 'X', 'Y', 'Z', 'velo', 'dist', 'count' ]] filteredFeaturesLocally.to_csv(directoryOutput + 'tracksFiltered_locally_PTV.txt', sep='\t', index=False) # else: #filter for outlier velocities using velocity threshold MeanVeloAll = filteredFeatures.velo.mean() StdVeloAll = filteredFeatures.velo.std() threshVelo_Pos = MeanVeloAll + veloStdThresh * StdVeloAll threshVelo_Neg = MeanVeloAll - veloStdThresh * StdVeloAll filteredFeatures = filteredFeatures[filteredFeatures.velo < threshVelo_Pos] filteredFeatures = filteredFeatures[filteredFeatures.velo > threshVelo_Neg] drawF.draw_tracks(filteredFeatures, image, directoryOutput, 'TracksFiltered_PTV_VeloThresh.jpg', 'velo', True) filteredFeatures = filteredFeatures[[ 'X', 'Y', 'Z', 'velo', 'dist_metric', 'count' ]] filteredFeatures.columns = ['X', 'Y', 'Z', 'velo', 'dist', 'count'] filteredFeatures.rename(columns={"dist_metric": "dist"}) filteredFeatures.to_csv(directoryOutput + 'TracksFiltered_PTV_VeloThresh.txt', sep='\t', index=False) #write filtered tracking results to file and draw final tracking results to image print('nbr of final tracked features: ' + str(filteredFeatures.shape[0]) + '\n')
def FilterTracks(trackedFeaturesOutput_undist, dir_imgs, img_list, directoryOutput, minDistance_px, maxDistance_px, minimumTrackedFeatures, threshAngleSteadiness, threshAngleRange, binNbrMainflowdirection, MainFlowAngleBuffer, lspiv): '''filter tracks considering several filter parameters''' #transform dataframe to numpy array and get feature ids trackedFeaturesOutput_undist = np.asarray(trackedFeaturesOutput_undist) trackedFeaturesOutput_undist = np.asarray(trackedFeaturesOutput_undist[:,1:4], dtype=np.float) featureIDs_fromTracking = np.unique(trackedFeaturesOutput_undist[:,0]) Features_px = np.empty((1,6)) for feature in featureIDs_fromTracking: processFeature = trackedFeaturesOutput_undist[trackedFeaturesOutput_undist[:,0] == feature, 1:3] #get distance between tracked features across subsequent frames in image space if lspiv: xy_start_tr = np.ones((processFeature.shape[0]-1,processFeature.shape[1])) * processFeature[0,:] else: xy_start_tr = processFeature[:-1,:] xy_tr = processFeature[1:,:] dist = np.sqrt(np.square(xy_start_tr[:,0] - xy_tr[:,0]) + (np.square(xy_start_tr[:,1] - xy_tr[:,1]))) feature_px = np.hstack((np.ones((xy_start_tr.shape[0],1)) * feature, xy_start_tr)) feature_px = np.hstack((feature_px, xy_tr)) feature_px = np.hstack((feature_px, dist.reshape(dist.shape[0],1))) Features_px = np.vstack((Features_px, feature_px)) Features_px = Features_px[1:,:] Features_px = pd.DataFrame({'id' : Features_px[:,0], 'x' : Features_px[:,1], 'y' : Features_px[:,2], 'x_tr' : Features_px[:,3], 'y_tr' : Features_px[:,4], 'dist' : Features_px[:,5]}) #draw all tracks from frame to frame into image image = cv2.imread(dir_imgs + img_list[0], 0) drawF.draw_tracks(Features_px, image, directoryOutput, 'TracksRaw_px.jpg', 'dist', False) print('nbr features prior filtering: ' + str(np.unique(Features_px.id).shape[0]) + '\n') nbr_features_raw = np.unique(Features_px.id).shape[0] #minimum tracking distance if lspiv: filteredFeatures = Features_px[Features_px.dist > minDistance_px] else: filteredFeatures_id = Features_px[Features_px.dist < minDistance_px] filteredFeatures_id = filteredFeatures_id.id.unique() filteredFeatures = Features_px[~Features_px.id.isin(filteredFeatures_id)] filteredFeatures = filteredFeatures.reset_index(drop=True) drawF.draw_tracks(filteredFeatures, image, directoryOutput, 'TracksFilteredMinDist.png', 'dist', True) print('nbr features after minimum distance filter: ' + str(np.unique(filteredFeatures.id).shape[0])) nbr_features_mindist = np.unique(filteredFeatures.id).shape[0] #maximum tracking distance if lspiv: filteredFeatures = filteredFeatures[filteredFeatures.dist < maxDistance_px] else: filteredFeatures_id = Features_px[Features_px.dist > maxDistance_px] filteredFeatures_id = filteredFeatures_id.id.unique() filteredFeatures = filteredFeatures[~filteredFeatures.id.isin(filteredFeatures_id)] filteredFeatures = filteredFeatures.reset_index(drop=True) drawF.draw_tracks(filteredFeatures, image, directoryOutput, 'TracksFilteredMaxDist.png', 'dist', True) print('nbr features after maximum distance filter: ' + str(np.unique(filteredFeatures.id).shape[0])) nbr_features_maxdist = np.unique(filteredFeatures.id).shape[0] #minimum tracking counts try: filteredFeatures = filterF.TrackFilterMinCount(filteredFeatures, minimumTrackedFeatures) drawF.draw_tracks(filteredFeatures, image, directoryOutput, 'TracksFilteredMinCount.png', 'dist', True) print('nbr features after minimum count filter: ' + str(np.unique(filteredFeatures.id).shape[0])) except: print('error during filtering minimum count') nbr_features_mincount = np.unique(filteredFeatures.id).shape[0] #get track vector for each tracked feature y_track = filteredFeatures.y_tr.values - filteredFeatures.y.values x_track = filteredFeatures.x_tr.values - filteredFeatures.x.values track = np.hstack((x_track.reshape(filteredFeatures.shape[0],1), y_track.reshape(filteredFeatures.shape[0],1))) #get angle for each track angle = filterF.angleBetweenVecAndXaxis(track) filteredFeatures['angle'] = pd.Series(angle, index=filteredFeatures.index) #directional steadiness filteredFeatures, steady_angle = filterF.TrackFilterSteadiness(filteredFeatures, threshAngleSteadiness) drawF.draw_tracks(filteredFeatures, image, directoryOutput, 'TracksFilteredSteady.png', 'dist', True) print('nbr features after steadiness filter: ' + str(np.unique(filteredFeatures.id).shape[0])) nbr_features_steady = np.unique(filteredFeatures.id).shape[0] #range of directions per track filteredFeatures, range_angle = filterF.TrackFilterAngleRange(filteredFeatures, threshAngleRange) drawF.draw_tracks(filteredFeatures, image, directoryOutput, 'TracksFilteredRangeAngle.png', 'dist', True) print('nbr features after range angle filter: ' + str(np.unique(filteredFeatures.id).shape[0])) nbr_features_rangeangle = np.unique(filteredFeatures.id).shape[0] #filter tracks outside main flow direction filteredFeatures, flowdir_angle = filterF.TrackFilterMainflowdirection(filteredFeatures, binNbrMainflowdirection, MainFlowAngleBuffer) drawF.draw_tracks(filteredFeatures, image, directoryOutput, 'TracksFilteredFlowDir.png', 'dist', True) print('nbr features after flow directions filter: ' + str(np.unique(filteredFeatures.id).shape[0])) nbr_features_mainflowdir = np.unique(filteredFeatures.id).shape[0] #save filter results filteredFeatures.to_csv(directoryOutput + 'TracksFiltered_px.txt', sep='\t', index=False) return filteredFeatures, [nbr_features_raw, nbr_features_mindist, nbr_features_maxdist, nbr_features_mincount, steady_angle, nbr_features_steady, range_angle, nbr_features_rangeangle, flowdir_angle, nbr_features_mainflowdir]
feature_px = np.hstack((feature_px, xy_tr)) feature_px = np.hstack((feature_px, dist.reshape(dist.shape[0], 1))) Features_px = np.vstack((Features_px, feature_px)) Features_px = Features_px[1:, :] Features_px = pd.DataFrame({ 'id': Features_px[:, 0], 'x': Features_px[:, 1], 'y': Features_px[:, 2], 'x_tr': Features_px[:, 3], 'y_tr': Features_px[:, 4], 'dist': Features_px[:, 5] }) image = cv2.imread(dir_imgs + img_list[0], 0) drawF.draw_tracks(Features_px, image, directoryOutput, 'TracksRaw_px.png', 'dist', False) print('nbr features prior filtering: ' + str(np.unique(Features_px.id).shape[0])) nbr_features_raw = np.unique(Features_px.id).shape[0] #minimum tracking distance # filteredFeatures = Features_px[Features_px.dist > minDistance_px] filteredFeatures_id = Features_px[Features_px.dist <= minDistance_px] filteredFeatures_id = filteredFeatures_id.id.unique() filteredFeatures = Features_px[~Features_px.id.isin(filteredFeatures_id)] filteredFeatures = filteredFeatures.reset_index(drop=True) try: drawF.draw_tracks(filteredFeatures, image, directoryOutput, 'TracksFilteredMinDist.png', 'dist', True) except: print('drawing minimum distance filtered tracks failed')