comparison scripts/manual-video-analysis.py @ 890:85bcc758ee5b

new version to manual annotation, easy to configure to add new road user type and characteristics
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Tue, 28 Mar 2017 17:17:02 -0400
parents 4ea296ee1ae2
children ab3a4cb524a9
comparison
equal deleted inserted replaced
889:4ea296ee1ae2 890:85bcc758ee5b
1 #! /usr/bin/env python 1 #! /usr/bin/env python
2 2
3 import sys, argparse, cv2 3 import sys, argparse, cv2, numpy as np
4 4
5 parser = argparse.ArgumentParser(description=''''The program replays the video and allows to manually id vehicles and mark instants, eg when they cross given areas in the scene. Use this program in combination with a screen marker program (For example, Presentation Assistant) to draw multiple lines on the screen.''', 5 parser = argparse.ArgumentParser(description=''''The program replays the video and allows to manually id vehicles and mark instants, eg when they cross given areas in the scene. Use this program in combination with a screen marker program (For example, Presentation Assistant) to draw multiple lines on the screen.''',
6 epilog = '''The output should give you a .csv file with the same name as your video file with columns in this format: 6 epilog = '''The output should give you a .csv file with the same name as your video file with columns in this format:
7 vehicle number, frame number 7 vehicle number, frame number
8 You can easily spot mistakes in the csv file for a line with number, SKIP. If this happens, just delete the previous vehicle observation.''', 8 You can easily spot mistakes in the csv file for a line with number, SKIP. If this happens, just delete the previous vehicle observation.''',
9 formatter_class=argparse.RawDescriptionHelpFormatter) 9 formatter_class=argparse.RawDescriptionHelpFormatter)
10 parser.add_argument('-i', dest = 'videoFilename', help = 'name of the video file', required = True) 10 parser.add_argument('-i', dest = 'videoFilename', help = 'name of the video file', required = True)
11 parser.add_argument('-o', dest = 'outputFilename', help = 'name of the output file (csv file)') 11 parser.add_argument('-o', dest = 'outputFilename', help = 'name of the output file (csv file)')
12 parser.add_argument('-f', dest = 'firstFrameNum', help = 'number of first frame number to display', default = 0, type = int) 12 parser.add_argument('-f', dest = 'firstFrameNum', help = 'number of first frame number to display', default = 0, type = int)
13 parser.add_argument('-n', dest = 'nAttributes', help = 'number of attributes characterizing users', default = 0, type = int)
13 14
14 args = parser.parse_args() 15 args = parser.parse_args()
15 16
16 print('''Commands: 17 print('''Commands:
17 u: New vehicle crossing the first line 18 Press o when you make a mistake in input
18 i: Vehicle crossing subsequent lines 19 Press d to skip 100 frames
19 o: Press o when you make a mistake in input 20 Press s to skip 10 frames
20 p: Press p for a new pedestrian event (eg crossing) 21 Press c to go back 100 frames
21 d: Skip 100 frames 22 Press x to go back 10 frames
22 s: Skip 10 frames 23 Press spacebar to go forward one frame
23 c: Go back 100 frames 24 Press l to skip to frame number
24 x: Go back 10 frames 25 Press Enter to finish inputting user characteristics (if any in pop up window)
25 Spacebar: Go forward one frame 26 Press q to quit and end program''')
26 l: Skip to frame number
27 q: Quit and end program''')
28 # configuration of keys and user types (see moving) 27 # configuration of keys and user types (see moving)
29 userTypeNames = ['unknown', 28 userTypeNames = ['unknown',
30 'car', 29 'car',
31 'pedestrian', 30 'pedestrian',
32 'motorcycle', 31 'motorcycle',
33 'bicycle', 32 'bicycle',
34 'bus', 33 'bus',
35 'truck'] 34 'truck']
36 class UserConfiguration(object): 35 class UserConfiguration(object):
37 def __init__(self, name, keyNew, keyAddInstant): 36 def __init__(self, name, keyNew, keyAddInstant, nAttributes):
38 self.name = name 37 self.name = name
39 self.keyNew = ord(keyNew) 38 self.keyNew = ord(keyNew)
40 self.keyAddInstant = ord(keyAddInstant) 39 self.keyAddInstant = ord(keyAddInstant)
41 self.userNum = 0 40 self.userNum = 0
41 self.nAttributes = nAttributes
42 self.resetAttributes()
43
44 def getHelpStr(self):
45 return 'Press {} for new {}, {} for new instant for current {}'.format(chr(self.keyNew), self.name, chr(self.keyAddInstant), self.name)
46
47 def resetAttributes(self):
42 self.userInstant = 0 48 self.userInstant = 0
49 self.attributes = [-1]*self.nAttributes
43 50
51 def setAttribute(self, i, value):
52 self.attributes[i%self.nAttributes] = value
53
54 def getAttributeStr(self):
55 if self.nAttributes > 0:
56 return ','.join([str(i) for i in self.attributes])+','
57 else:
58 return ''
59
44 def isKeyNew(self, k): 60 def isKeyNew(self, k):
45 return (k == self.keyNew) 61 return (k == self.keyNew)
46 62
47 def isKeyAddInstant(self, k): 63 def isKeyAddInstant(self, k):
48 return (k == self.keyAddInstant) 64 return (k == self.keyAddInstant)
49 65
50 def isKey(self, k): 66 def isKey(self, k):
51 return self.isKeyNew() or self.isKeyAddInstant() 67 return self.isKeyNew(k) or self.isKeyAddInstant(k)
52 68
53 @staticmethod 69 @staticmethod
54 def isKey(configurations): 70 def getConfigurationWithKey(configurations, k):
55 for c in configurations: 71 for c in configurations:
56 if c.isKey(): 72 if c.isKey(k):
57 return c 73 return c
58 return None 74 return None
59 75
60 userConfigurations = [UserConfiguration(userTypeNames[1],1,'u','i'), 76 userConfigurations = [UserConfiguration(userTypeNames[1],'u','i', args.nAttributes),
61 UserConfiguration(userTypeNames[2],2,'j','k')] 77 UserConfiguration(userTypeNames[2],'j','k', args.nAttributes)]
78
79 print(' ')
80 for c in userConfigurations:
81 print(c.getHelpStr())
62 82
63 # start of program 83 # start of program
64 cap = cv2.VideoCapture(args.videoFilename) 84 cap = cv2.VideoCapture(args.videoFilename)
65 cap.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, args.firstFrameNum) 85 cap.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, args.firstFrameNum)
86 fps = cap.get(cv2.cv.CV_CAP_PROP_FPS)
87 print('Video at {} frames/s'.format(fps))
66 cv2.namedWindow('Video', cv2.WINDOW_NORMAL) 88 cv2.namedWindow('Video', cv2.WINDOW_NORMAL)
67 89
68 # output filename 90 # output filename
69 if args.outputFilename is None: 91 if args.outputFilename is None:
70 i = args.videoFilename.rfind('.') 92 i = args.videoFilename.rfind('.')
87 key= cv2.waitKey(0) 109 key= cv2.waitKey(0)
88 110
89 if key == ord('q'): 111 if key == ord('q'):
90 break 112 break
91 else: 113 else:
92 config = UserConfiguration.isKey(userConfigurations) 114 config = UserConfiguration.getConfigurationWithKey(userConfigurations, key)
93 if config is not None: 115 if config is not None:
94 if c.isKeyNew(): 116 if config.isKeyNew(key):
95 pass # increment userNum 117 config.userNum += 1
96 elif c.isKeyAddInstant(): 118 config.resetAttributes()
97 pass # increment userInstant 119 print('New {} {}'.format(config.name, config.userNum))
98 # print/write 120 if args.nAttributes > 0:
99 121 key2 = ord('1')
100 elif key == ord('u') or key == ord('i'): 122 cv2.namedWindow('Input', cv2.WINDOW_NORMAL)
101 if key == ord('u'): 123 attributeNum = 0
102 vehNumber += 1 124 while key2 != ord('\n'):
103 lineNum = 0 125 attrImg = 255*np.ones((20*args.nAttributes, 20, 3))
104 print('New Vehicle') 126 for i in xrange(args.nAttributes):
105 out.write('{},{}\n'.format(vehNumber,frameNum)) 127 if i == (attributeNum%args.nAttributes):
106 if vehNumber >= 1 and key == ord('i'): 128 cv2.putText(attrImg, str(config.attributes[i]), (1,20*(i+1)), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 255))
107 lineNum = lineNum+1 129 else:
108 print('Line number {}'.format(lineNum)) 130 cv2.putText(attrImg, str(config.attributes[i]), (1,20*(i+1)), cv2.FONT_HERSHEY_PLAIN, 1, (0, 255, 0))
109 elif key == ord('o'): 131 cv2.imshow('Input', attrImg)
110 out.write('{},SKIP\n'.format(vehNumber)) 132 key2 = cv2.waitKey(0)
111 print('SKIPPED') 133 if chr(key2).isdigit():
112 elif key == ord('p'): 134 config.setAttribute(attributeNum, chr(key2))
113 print("New Pedestrian") 135 attributeNum += 1
114 out.write('Pedestrian,{}\n'.format(frameNum)) 136 cv2.destroyWindow('Input')
115 #Change the number of frames skipped or the keys in this section 137 elif config.isKeyAddInstant(key):
116 elif key == ord('d'): 138 config.userInstant += 1
117 cap.set(1,frameNum+100) 139 print('User {} no {} at line {}'.format(config.name, config.userNum, config.userInstant))
118 elif key == ord('s'): 140 out.write('{},{},{}{}\n'.format(config.userNum, config.name, config.getAttributeStr(), config.userInstant))
119 cap.set(1,frameNum+10) 141 oldUserConfig = config
120 elif key == ord('a'): 142 if key == ord('o'):
121 cap.set(1,frameNum+1) 143 print('SKIPPED')
122 elif key == ord('x'): 144 out.write('{},{},SKIP\n'.format(oldUserConfig.userNum, oldUserConfig.name))
123 cap.set(1,frameNum-10) 145 elif key == ord('d'):
124 elif key == ord('c'): 146 cap.set(1,frameNum+100)
125 cap.set(1,frameNum-100) 147 elif key == ord('s'):
126 elif key == ord('l'): 148 cap.set(1,frameNum+10)
127 frameNum = int(raw_input("Please enter the frame number you would like to skip to\n")) 149 elif key == ord('a'):
128 cap.set(cv2.cv.CV_CAP_PROP_POS_FRAMES,frameNum-5) 150 cap.set(1,frameNum+1)
151 elif key == ord('x'):
152 cap.set(1,frameNum-10)
153 elif key == ord('c'):
154 cap.set(1,frameNum-100)
155 elif key == ord('l'):
156 frameNum = int(raw_input("Please enter the frame number you would like to skip to\n"))
157 cap.set(cv2.cv.CV_CAP_PROP_POS_FRAMES,frameNum)
129 158
130 159 out.close()
131 cap.release() 160 cap.release()
132 cv2.destroyAllWindows() 161 cv2.destroyAllWindows()
133 162
134 #97a 163 #97a
135 #115s 164 #115s