Merge branch 'multiProcessing' into dev

This commit is contained in:
ori
2019-06-09 11:00:50 -07:00
3 changed files with 105 additions and 73 deletions

View File

@@ -1,22 +1,28 @@
from multiprocessing import Queue
from multiprocessing.managers import BaseManager
import tornado.ioloop
import multiprocessing
import logging
from cscore import CameraServer
from app.ChameleonVisionApp import ChameleonApplication
from app.classes.SettingsManager import SettingsManager
from tornado.options import options
from app.handlers.VisionHandler import VisionHandler
if __name__ == "__main__":
SettingsManager()
VisionHandler().run()
# SettingsManager().save_settings()
def run_server():
tornado.options.parse_command_line()
app = ChameleonApplication()
print(f"Serving on port {options.port}")
app.listen(options.port)
tornado.ioloop.IOLoop.current().start()
#TODO: create process for each camera
# create proccess loop and camera publisher
# bridge network tables for each camera
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG)
SettingsManager()
VisionHandler().run()

View File

@@ -25,7 +25,8 @@ class SettingsManager(metaclass=Singleton):
"dilate": False,
"area": [0, 100],
"ratio": [0, 20],
"extent": [0, 100]
"extent": [0, 100],
"is_binary": "Normal"
}
default_general_settings = {
"team_number": 1577,
@@ -68,42 +69,38 @@ class SettingsManager(metaclass=Singleton):
if os.path.exists(os.path.join(self.cams_path, cam.name + '.json')):
with open(os.path.join(self.cams_path, cam.name + '.json'), 'r') as camera:
self.cams[cam.name] = json.load(camera)
self.cams[cam_name] = json.load(camera)
if len(self.cams[cam.name]["pipelines"]) == 0:
self.create_new_pipeline(cam_name=cam.name)
self.create_new_pipeline(cam_name=cam_name)
else:
self.create_new_cam(cam.name)
self.create_new_cam(cam_name)
# Initiate true usb cameras(filters microphones and double cameras)
def _init_cameras_info(self):
true_cameras = []
usb_devices = cscore.UsbCamera.enumerateUsbCameras()
for index in range(len(usb_devices)):
cap = cv2.VideoCapture(index)
for index, device in enumerate(usb_devices):
cap = cv2.VideoCapture(device.dev)
if cap.isOpened():
true_cameras.append(index)
cap.release()
index += 1
for i in true_cameras:
self.usb_cameras_info[usb_devices[i].name] = usb_devices[i]
device_name = usb_devices[i].name
suffix = 0
while device_name in self.usb_cameras_info:
suffix += 1
device_name = f"{device.name}({str(suffix)})"
self.usb_cameras_info[device_name] = usb_devices[i]
# Initiate cscore usb devices
def _init_usb_cameras(self):
for i in self.usb_cameras_info:
device = self.usb_cameras_info[i]
device_name = device.name
if device_name in self.usb_cameras:
suffix = 1
device_name = device.name + f"({str(suffix)})"
while device_name in self.usb_cameras:
suffix += 1
device_name = "pipeline" + f"({str(suffix)})"
for device_name in self.usb_cameras_info:
device = self.usb_cameras_info[device_name]
camera = cscore.UsbCamera(name=device_name, dev=device.dev)

View File

@@ -5,11 +5,15 @@ import cv2
import numpy
from cscore import CameraServer
from app.classes.SettingsManager import SettingsManager
from ..classes.Singleton import Singleton
import time
import json
from multiprocessing import Process
import multiprocessing
import threading
import zmq
class VisionHandler:
class VisionHandler(metaclass=Singleton):
def __init__(self):
self.kernel = numpy.ones((5, 5), numpy.uint8)
@@ -69,56 +73,81 @@ class VisionHandler:
return input_image
def run(self):
camera_server = cscore.CameraServer.getInstance()
# NetworkTables.startClientTeam(team=SettingsManager.general_settings.get("team_number", 1577))
NetworkTables.initialize("localhost")
# NetworkTables.initialize()
for cam in SettingsManager().usb_cameras:
self.camera_process(SettingsManager().usb_cameras[cam],cam)
def camera_process(self, camera,cam_name):
curr_pipline = list(SettingsManager.cams[cam_name]["pipelines"].values())[0]
def change_camera_values():
camera.setBrightness(0)
camera.setExposureManual(0)
def pipeline_listener(table, key, value, is_new):
if(is_new):
curr_pipline = SettingsManager.cams[cam_name]["pipelines"][value]
change_camera_values()
def mode_listener(table, key, value, is_new):
pass
image = numpy.zeros(shape=(SettingsManager().cams[cam_name]["video_mode"]["width"], SettingsManager().cams[cam_name]["video_mode"]["height"], 3), dtype=numpy.uint8)
table = NetworkTables.getTable("/Chameleon-Vision/" + camera.getInfo().name)
table.addEntryListenerEx(pipeline_listener, key="Pipeline",
flags=networktables.NetworkTablesInstance.NotifyFlags.UPDATE)
table.addEntryListenerEx(mode_listener, key="Driver_Mode",
flags=networktables.NetworkTablesInstance.NotifyFlags.UPDATE)
change_camera_values()
cs = CameraServer.getInstance()
cv_sink = cs.getVideo(camera=camera)
cv_publish = cs.putVideo(name=cam_name, width=SettingsManager().cams[cam_name]["video_mode"]["width"],
height=SettingsManager().cams[cam_name]["video_mode"]["height"])
cam_area = SettingsManager().cams[cam_name]["video_mode"]["width"] * SettingsManager().cams[cam_name]["video_mode"]["height"]
port = 5550
for cam_name in SettingsManager().usb_cameras:
threading.Thread(target=self.thread_proc, args=(cs, cam_name, str(port))).start()
port += 1
def thread_proc(self, cs, cam_name, port="5557"):
cv_sink = cs.getVideo(camera=SettingsManager.usb_cameras[cam_name])
width = SettingsManager().cams[cam_name]["video_mode"]["width"]
height = SettingsManager().cams[cam_name]["video_mode"]["height"]
image = numpy.zeros(shape=(width, height, 3), dtype=numpy.uint8)
cv_publish = cs.putVideo(name=cam_name, width=width, height=height)
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.bind("tcp://*:%s" % port)
p = Process(target=self.camera_process, args=(SettingsManager.usb_cameras[cam_name], cam_name, port))
p.start()
while True:
start = time.time()
_, image = cv_sink.grabFrame(image)
hsv_image = self._hsv_threshold(curr_pipline["hue"],
curr_pipline["saturation"], curr_pipline["value"],
image, curr_pipline["erode"], curr_pipline["dilate"])
# if table.getBoolean("Driver_Mode", False):
contours = self.find_contours(hsv_image)
filtered_contours = self.filter_contours(contours, cam_area, curr_pipline["area"], curr_pipline["ratio"], curr_pipline["extent"])
image = self.draw_image(input_image=image, is_binary=False, rectangles=filtered_contours)
socket.send_pyobj(image)
image = socket.recv_pyobj()
cv_publish.putFrame(image)
end = time.time()
print(1/(end-start))
print(cam_name + " " + str(1 / (end - start)))
def camera_process(self, camera, cam_name, port):
curr_pipeline = list(SettingsManager.cams[cam_name]["pipelines"].values())[0]
# def change_camera_values():
# camera.setBrightness(0)
# camera.setExposureManual(0)
#
# def pipeline_listener(table, key, value, is_new):
# if (is_new):
# curr_pipline = SettingsManager.cams[cam_name]["pipelines"][value]
# change_camera_values()
#
# def mode_listener(table, key, value, is_new):
# pass
#
# table = NetworkTables.getTable("/Chameleon-Vision/" + camera.getInfo().name)
#
# table.addEntryListenerEx(pipeline_listener, key="Pipeline",
# flags=networktables.NetworkTablesInstance.NotifyFlags.UPDATE)
# table.addEntryListenerEx(mode_listener, key="Driver_Mode",
# flags=networktables.NetworkTablesInstance.NotifyFlags.UPDATE)
# change_camera_values()
width = SettingsManager().cams[cam_name]["video_mode"]["width"]
height = SettingsManager().cams[cam_name]["video_mode"]["height"]
cam_area = width * height
context = zmq.Context()
socket = context.socket(zmq.REP)
socket.connect("tcp://localhost:%s" % port)
while True:
image = socket.recv_pyobj()
hsv_image = self._hsv_threshold(curr_pipeline["hue"],
curr_pipeline["saturation"], curr_pipeline["value"],
image, curr_pipeline["erode"], curr_pipeline["dilate"])
# if table.getBoolean("Driver_Mode", False):
contours = self.find_contours(hsv_image)
filtered_contours = self.filter_contours(contours, cam_area, curr_pipeline["area"], curr_pipeline["ratio"],
curr_pipeline["extent"])
res = self.draw_image(input_image=image, is_binary=False, rectangles=filtered_contours)
socket.send_pyobj(res)