changeset 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
files scripts/manual-video-analysis.py
diffstat 1 files changed, 84 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/manual-video-analysis.py	Fri Mar 24 14:20:01 2017 -0400
+++ b/scripts/manual-video-analysis.py	Tue Mar 28 17:17:02 2017 -0400
@@ -1,6 +1,6 @@
 #! /usr/bin/env python
 
-import sys, argparse, cv2
+import sys, argparse, cv2, numpy as np
 
 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.''',
                                  epilog = '''The output should give you a .csv file with the same name as your video file with columns in this format:
@@ -10,21 +10,20 @@
 parser.add_argument('-i', dest = 'videoFilename', help = 'name of the video file', required = True)
 parser.add_argument('-o', dest = 'outputFilename', help = 'name of the output file (csv file)')
 parser.add_argument('-f', dest = 'firstFrameNum', help = 'number of first frame number to display', default = 0, type = int)
+parser.add_argument('-n', dest = 'nAttributes', help = 'number of attributes characterizing users', default = 0, type = int)
 
 args = parser.parse_args()
 
 print('''Commands:
-u: New vehicle crossing the first line
-i: Vehicle crossing subsequent lines
-o: Press o when you make a mistake in input
-p: Press p for a new pedestrian event (eg crossing)
-d: Skip 100 frames
-s: Skip 10 frames
-c: Go back 100 frames
-x: Go back 10 frames
-Spacebar: Go forward one frame
-l: Skip to frame number
-q: Quit and end program''')
+Press o when you make a mistake in input
+Press d to skip 100 frames
+Press s to skip 10 frames
+Press c to go back 100 frames
+Press x to go back 10 frames
+Press spacebar to go forward one frame
+Press l to skip to frame number
+Press Enter to finish inputting user characteristics (if any in pop up window)
+Press q to quit and end program''')
 # configuration of keys and user types (see moving)
 userTypeNames = ['unknown',
                  'car',
@@ -34,13 +33,30 @@
                  'bus',
                  'truck']
 class UserConfiguration(object):
-    def __init__(self, name, keyNew, keyAddInstant):
+    def __init__(self, name, keyNew, keyAddInstant, nAttributes):
         self.name = name
         self.keyNew = ord(keyNew)
         self.keyAddInstant = ord(keyAddInstant)
         self.userNum = 0
+        self.nAttributes = nAttributes
+        self.resetAttributes()
+
+    def getHelpStr(self):
+        return 'Press {} for new {}, {} for new instant for current {}'.format(chr(self.keyNew), self.name, chr(self.keyAddInstant), self.name)
+        
+    def resetAttributes(self):
         self.userInstant = 0
+        self.attributes = [-1]*self.nAttributes
 
+    def setAttribute(self, i, value):
+        self.attributes[i%self.nAttributes] = value
+
+    def getAttributeStr(self):
+        if self.nAttributes > 0:
+            return ','.join([str(i) for i in self.attributes])+','
+        else:
+            return ''
+        
     def isKeyNew(self, k):
         return (k == self.keyNew)
 
@@ -48,21 +64,27 @@
         return (k == self.keyAddInstant)
     
     def isKey(self, k):
-        return self.isKeyNew() or self.isKeyAddInstant()
+        return self.isKeyNew(k) or self.isKeyAddInstant(k)
 
     @staticmethod
-    def isKey(configurations):
+    def getConfigurationWithKey(configurations, k):
         for c in configurations:
-            if c.isKey():
+            if c.isKey(k):
                 return c
         return None
 
-userConfigurations = [UserConfiguration(userTypeNames[1],1,'u','i'),
-                      UserConfiguration(userTypeNames[2],2,'j','k')]
+userConfigurations = [UserConfiguration(userTypeNames[1],'u','i', args.nAttributes),
+                      UserConfiguration(userTypeNames[2],'j','k', args.nAttributes)]
+
+print(' ')
+for c in userConfigurations:
+    print(c.getHelpStr())
 
 # start of program
 cap = cv2.VideoCapture(args.videoFilename)
 cap.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, args.firstFrameNum)
+fps = cap.get(cv2.cv.CV_CAP_PROP_FPS)
+print('Video at {} frames/s'.format(fps))
 cv2.namedWindow('Video', cv2.WINDOW_NORMAL)
 
 # output filename
@@ -89,45 +111,52 @@
     if key == ord('q'):
         break
     else:
-        config = UserConfiguration.isKey(userConfigurations)
+        config = UserConfiguration.getConfigurationWithKey(userConfigurations, key)
         if config is not None:
-            if c.isKeyNew():
-                pass # increment userNum
-            elif c.isKeyAddInstant():
-                pass # increment userInstant
-            # print/write
-        
-    elif key == ord('u') or key == ord('i'):
-        if key == ord('u'):
-            vehNumber += 1
-            lineNum = 0
-            print('New Vehicle')
-        out.write('{},{}\n'.format(vehNumber,frameNum))        
-        if vehNumber >= 1 and key == ord('i'):
-            lineNum = lineNum+1
-            print('Line number {}'.format(lineNum))
-    elif key == ord('o'):
-        out.write('{},SKIP\n'.format(vehNumber))
-        print('SKIPPED')
-    elif key == ord('p'):
-        print("New Pedestrian")
-        out.write('Pedestrian,{}\n'.format(frameNum))
-#Change the number of frames skipped or the keys in this section
-    elif key == ord('d'):
-        cap.set(1,frameNum+100)
-    elif key == ord('s'):
-        cap.set(1,frameNum+10)
-    elif key == ord('a'):
-        cap.set(1,frameNum+1)
-    elif key == ord('x'):
-        cap.set(1,frameNum-10)
-    elif key == ord('c'):
-        cap.set(1,frameNum-100)
-    elif key == ord('l'):
-        frameNum = int(raw_input("Please enter the frame number you would like to skip to\n"))
-        cap.set(cv2.cv.CV_CAP_PROP_POS_FRAMES,frameNum-5)
+            if config.isKeyNew(key):
+                config.userNum += 1
+                config.resetAttributes()
+                print('New {} {}'.format(config.name, config.userNum))
+                if args.nAttributes > 0:
+                    key2 = ord('1')
+                    cv2.namedWindow('Input', cv2.WINDOW_NORMAL)
+                    attributeNum = 0
+                    while key2 != ord('\n'):
+                        attrImg = 255*np.ones((20*args.nAttributes, 20, 3))
+                        for i in xrange(args.nAttributes):
+                            if i == (attributeNum%args.nAttributes):
+                                cv2.putText(attrImg, str(config.attributes[i]), (1,20*(i+1)), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 255))
+                            else:
+                                cv2.putText(attrImg, str(config.attributes[i]), (1,20*(i+1)), cv2.FONT_HERSHEY_PLAIN, 1, (0, 255, 0))
+                        cv2.imshow('Input', attrImg)
+                        key2 = cv2.waitKey(0)
+                        if chr(key2).isdigit():
+                            config.setAttribute(attributeNum, chr(key2))
+                            attributeNum += 1
+                    cv2.destroyWindow('Input')
+            elif config.isKeyAddInstant(key):
+                config.userInstant += 1
+                print('User {} no {} at line {}'.format(config.name, config.userNum, config.userInstant))
+            out.write('{},{},{}{}\n'.format(config.userNum, config.name, config.getAttributeStr(), config.userInstant))
+            oldUserConfig = config
+        if key == ord('o'):
+            print('SKIPPED')
+            out.write('{},{},SKIP\n'.format(oldUserConfig.userNum, oldUserConfig.name))
+        elif key == ord('d'):
+            cap.set(1,frameNum+100)
+        elif key == ord('s'):
+            cap.set(1,frameNum+10)
+        elif key == ord('a'):
+            cap.set(1,frameNum+1)
+        elif key == ord('x'):
+            cap.set(1,frameNum-10)
+        elif key == ord('c'):
+            cap.set(1,frameNum-100)
+        elif key == ord('l'):
+            frameNum = int(raw_input("Please enter the frame number you would like to skip to\n"))
+            cap.set(cv2.cv.CV_CAP_PROP_POS_FRAMES,frameNum)
     
-
+out.close()
 cap.release()
 cv2.destroyAllWindows()