You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

162 lines
5.8 KiB

  1. import argparse
  2. import multiprocessing as mp
  3. import os
  4. import threading as th
  5. import time
  6. from datetime import datetime
  7. from queue import Queue
  8. import numpy as np
  9. os.environ['DISPLAY'] = ':0'
  10. import cv2
  11. inputQueue = mp.Queue()
  12. vehicleDetectionQueue = mp.Queue()
  13. outputQueue = mp.Queue()
  14. IMAGE_HEIGHT = mp.Value('i',0)
  15. IMAGE_WIDTH = mp.Value('i',0)
  16. class ReadFrame(th.Thread):
  17. global inputQueue
  18. global IMAGE_HEIGHT,IMAGE_WIDTH
  19. def __init__(self,source,name='Input thread',custom_id=1) -> None:
  20. super().__init__()
  21. self.frameId = 1
  22. self.stopped = False
  23. self.grabbed = True
  24. self.name = f'{name} {custom_id}'
  25. self.videoCaptureObject = cv2.VideoCapture(source)
  26. if(self.videoCaptureObject.isOpened()):
  27. IMAGE_HEIGHT.value = int(self.videoCaptureObject.get(cv2.CAP_PROP_FRAME_HEIGHT))
  28. IMAGE_WIDTH.value = int(self.videoCaptureObject.get(cv2.CAP_PROP_FRAME_WIDTH))
  29. print(f'Reading from source = {source}')
  30. def run(self):
  31. while (self.grabbed):
  32. (self.grabbed, self.frame) = self.videoCaptureObject.read()
  33. IMAGE_HEIGHT.value = int(self.videoCaptureObject.get(cv2.CAP_PROP_FRAME_HEIGHT))
  34. IMAGE_WIDTH.value = int(self.videoCaptureObject.get(cv2.CAP_PROP_FRAME_WIDTH))
  35. inputQueue.put((self.frame,self.frameId))
  36. print(f"{self.name} frame added with id {self.frameId}\n")
  37. self.frameId+=1
  38. print('--Done reading frames--\n')
  39. self.videoCaptureObject.release()
  40. return
  41. class VehicleDetection(mp.Process):
  42. global inputQueue
  43. global vehicleDetectionQueue
  44. def __init__(self,name='Vehicle Detection Process',custom_id=1):
  45. super(VehicleDetection,self).__init__()
  46. self.name = f'{name} {custom_id}'
  47. def run(self):
  48. while (True):
  49. if(inputQueue.qsize() == 0):
  50. vehicleDetectionQueue.put(None)
  51. print(f'{self.name} exiting !! \n')
  52. return
  53. (frame,frameId) = inputQueue.get()
  54. print(f"{self.name} Got frame with ID {frameId} qsize = {inputQueue.qsize()}\n")
  55. #do some processing here.
  56. time.sleep(.5)
  57. vehicleDetectionQueue.put((frame,frameId))
  58. class NumberPlateOcr(mp.Process):
  59. global vehicleDetectionQueue
  60. global outputQueue
  61. def __init__(self,name='Number plate OCR Process',custom_id=1):
  62. super(NumberPlateOcr,self).__init__()
  63. self.name=f'{name} {custom_id}'
  64. def run(self):
  65. while True:
  66. value = vehicleDetectionQueue.get()
  67. if(value == None):
  68. print(f'{self.name} exiting !! \n')
  69. outputQueue.put(None)
  70. return
  71. (frame,frameId) = value
  72. print(f"{self.name} Got frame with ID {frameId}\n")
  73. #do some processing here.
  74. time.sleep(.25)
  75. outputQueue.put((frame,frameId))
  76. class OutputFrame(th.Thread):
  77. global IMAGE_HEIGHT,IMAGE_WIDTH
  78. global outputQueue
  79. def __init__(self,name='output thread',custom_id=1,outputfilename="output.avi"):
  80. super().__init__()
  81. self.name = f'{name} {custom_id}'
  82. self.outputfilename = outputfilename
  83. print(f'frame size {IMAGE_HEIGHT.value} {IMAGE_WIDTH.value}')
  84. self.videoWriterObject = cv2.VideoWriter(outputfilename,cv2.VideoWriter_fourcc(*'MJPG'),30,(IMAGE_WIDTH.value,IMAGE_HEIGHT.value))
  85. self.winName = "DISPLAY"
  86. def run(self):
  87. cv2.namedWindow(self.winName,cv2.WINDOW_NORMAL)
  88. while True:
  89. try:
  90. value = outputQueue.get()
  91. if(value == None):
  92. return
  93. (frame,frameId) = value
  94. print(f'{self.name} got frame with ID {frameId} shape = {frame.shape}')
  95. cv2.imshow(self.winName,frame)
  96. self.videoWriterObject.write(frame)
  97. except(AttributeError):
  98. continue
  99. if __name__ == '__main__':
  100. import cProfile
  101. app_profiler = cProfile.Profile()
  102. parser = argparse.ArgumentParser(description='BitSilica Traffic Analysis Solution')
  103. parser.add_argument('--image', help=' Full Path to image file.')
  104. parser.add_argument('--video', help='Full Path to video file.')
  105. parser.add_argument('--realtime',help='Camera Connected Input')
  106. args = parser.parse_args()
  107. #Name of the video file.
  108. outputvideo = f'output {os.path.basename(args.video)[:-4]} {datetime.now()}.avi'
  109. print(f'-----> Writing to file {outputvideo} <-------\n')
  110. #enable profiler here.
  111. app_profiler.enable()
  112. readFramesThread = ReadFrame(args.video)
  113. vehicleDetectionProcess = VehicleDetection()
  114. numberPlateOcrProcess = NumberPlateOcr()
  115. outputframeThread = OutputFrame(outputfilename = outputvideo)
  116. readFramesThread.start()
  117. time.sleep(.25)
  118. vehicleDetectionProcess.start()
  119. numberPlateOcrProcess.start()
  120. outputframeThread.start()
  121. print(f'{vehicleDetectionProcess.name} {vehicleDetectionProcess.pid} \n')
  122. print(f'{numberPlateOcrProcess.name} {numberPlateOcrProcess.pid} \n')
  123. readFramesThread.join()
  124. print(f'readframesthread {readFramesThread.is_alive()}\n')
  125. vehicleDetectionProcess.join()
  126. print(f'vehicleDetectionProcess {vehicleDetectionProcess.is_alive()}\n')
  127. numberPlateOcrProcess.join()
  128. print(f'numberPlateOcrProcess {numberPlateOcrProcess.is_alive()}\n')
  129. outputframeThread.join()
  130. print(f'{outputframeThread.name} {outputframeThread.is_alive()}')
  131. #disable profiler here.
  132. app_profiler.disable()
  133. profile_name = str('{}.prof'.format(os.path.basename(args.video)[0:-4]))
  134. print("------------------------\nEnd of execution, dumping profile stats\n-------------------------")
  135. app_profiler.dump_stats(profile_name)