Beispiel #1
0
 def preRun__(self):
     super().preRun__()
     # Shmem servers could also be created on-demand for various master processes
     self.server = ShmemRGBServer(
         name = self.server_name,
         n_ringbuffer = self.server_n_ringbuffer,
         width = self.server_width,
         height = self.server_height
     )
     self.server.useEventFd(self.event_fd)
     print("rgbClientSideProcess : using event_fd for serving frames fd=", self.event_fd.getFd())
 def c__setMasterProcess(self, ipc_index=None):
     # get shmem parameters from master process frontend
     self.ipc_index = ipc_index
     self.eventfd, self.master_pipe = singleton.ipc.get1(self.ipc_index)
     # self.n_buffer etc. have been set by a call to c__activate
     self.server = ShmemRGBServer(
         name=self.shmem_name_server,
         n_ringbuffer=self.n_buffer,  # size of ring buffer
         width=self.image_dimensions[0],
         height=self.image_dimensions[1],
         verbose=self.shmem_verbose)
     self.server.useEventFd(self.eventfd)  # activate eventfd API
     singleton.ipc.set(ipc_index)
def test2():
    import numpy

    shmem_name = "kokkelis"
    n_buffer = 10
    image_dimensions = (400, 300)
    server = ShmemRGBServer(
        name=shmem_name,
        n_ringbuffer=n_buffer,  # size of ring buffer
        width=image_dimensions[0],
        height=image_dimensions[1],
        verbose=True)

    p = QShmemProcess("test",
                      n_buffer=n_buffer,
                      image_dimensions=image_dimensions,
                      shmem_verbose=True,
                      shmem_name=shmem_name)

    p.setDebug()
    p.start()
    p.activate()

    img = numpy.zeros((300, 400, 3), dtype=numpy.uint8)

    for i in range(5):
        img[:, :, :] = i
        server.pushFrame(img, 1, 123)
        time.sleep(0.2)

    p.deactivate()

    for i in range(50):
        img[:, :, :] = i
        server.pushFrame(img, 1, 123)
        # time.sleep(0.2)

    p.activate()

    for i in range(15):
        img[:, :, :] = i
        server.pushFrame(img, 1, 123)
        time.sleep(0.1)

    p.stop()
def test3():
    """One client, one master process
    """
    import numpy

    shmem_name = "kokkelis"
    n_buffer = 10
    image_dimensions = (400, 300)
    server = ShmemRGBServer(
        name=shmem_name,
        n_ringbuffer=n_buffer,  # size of ring buffer
        width=image_dimensions[0],
        height=image_dimensions[1],
        verbose=True)

    p = QShmemClientProcess("test",
                            n_buffer=n_buffer,
                            image_dimensions=image_dimensions,
                            shmem_verbose=True,
                            shmem_name=shmem_name)

    p.setDebug()
    p.start()

    pm = QShmemMasterProcess("master_test")
    pm.setDebug()
    pm.start()
    """
    p.activate(n_buffer=n_buffer, 
        image_dimensions=image_dimensions, 
        shmem_name=shmem_name)
    """
    p.activate()

    img = numpy.zeros((300, 400, 3), dtype=numpy.uint8)
    for i in range(10):
        img[:, :, :] = i
        server.pushFrame(img, 1, 123)
        time.sleep(0.1)

    print("\nConnecting master process\n")

    p.setMasterProcess(pm)

    for i in range(10):
        img[:, :, :] = i
        server.pushFrame(img, 1, 123)
        time.sleep(0.1)

    p.unsetMasterProcess(pm)

    p.stop()
    pm.stop()
 def c__requestQtShmemServer(self, **kwargs):
     self.logger.debug("shmem server requested")
     # should be called only after the shmem client has been instantiated
     self.shmem_name_qt_server = self.shmem_name + "_qt_server"
     self.qt_server = ShmemRGBServer(
         name=self.shmem_name_qt_server,
         n_ringbuffer=self.n_buffer,  # size of ring buffer
         width=self.image_dimensions[0],
         height=self.image_dimensions[1],
         verbose=self.shmem_verbose)
     # inform frontend & widgets that the shmem server is available:
     self.send_out__(
         MessageObject(
             "shmem_server",  # this is routed to the qt signal with the same name
             shmem_name=self.shmem_name_qt_server,
             shmem_n_buffer=self.n_buffer,
             width=self.image_dimensions[0],
             height=self.image_dimensions[1],
             verbose=self.shmem_verbose))
Beispiel #6
0
class RGBClientProcess(RGB24Process):
    """
    Gets RGB24 frames from valkka side, inspects them and then pass them to master processes (i,e different Machine Vision processes)

    !! Needs to establish an RGB24 shmem server

    Receives a message from Machine vision process
    """

    def __init__(self, mstimeout = 1000, server_img_width = 100, server_img_height = 100):
        super().__init__(mstimeout= mstimeout)
        self.event_fd = reserveEventFd() # event fd for the rgb24 shmem server

        self.server_name = str(id(self))
        self.server_n_ringbuffer = 10
        self.server_width = server_img_width
        self.server_height = server_img_height

        self.intercom_ipc_index = None # event fd index for sending messages to master process (i,e machine vision process)
        self.intercom_client = None
        self.intercom_fd = None

    def __del__(self):
        releaseEventFd(self.event_fd)


    """ BACKEND METHODS 
    
    Never call these methods from the main python process: they are internal for the multiprocess backend
    """

    def preRun__(self):
        super().preRun__()
        # Shmem servers could also be created on-demand for various master processes
        self.server = ShmemRGBServer(
            name = self.server_name,
            n_ringbuffer = self.server_n_ringbuffer,
            width = self.server_width,
            height = self.server_height
        )
        self.server.useEventFd(self.event_fd)
        print("rgbClientSideProcess : using event_fd for serving frames fd=", self.event_fd.getFd())

    def postRun__(self):
        super(RGBClientProcess, self).postRun__()

    def readPipes__(self, timeout):
        """
        Multiplex all intercom pipes / events

        This is used by your multiprocess run() method // no need to modify run() method

        """
        rlis = [self.back_pipe]
        # self.back_pipe is the intercom pipe with the main python process

        # listen to all rgb frame sources
        frame_fds = list(self.client_by_fd.keys())

        rlis += frame_fds

        if self.intercom_fd is not None:
            rlis.append(self.intercom_fd)

        rs, ws, es = safe_select(rlis, [],  [], timeout= timeout)

        # rs is a list of event file descriptors that have been triggered
        for fd in rs:
            # 1. handle the main intercom pipe
            if fd == self.back_pipe:
                self.handleBackPipe__(self.back_pipe)
            # 2. handle frame coming from valkka c++ side
            if fd in frame_fds:
                client = self.client_by_fd[fd]
                index, meta = client.pullFrame()
                if (index == None):
                    print("weird.. rgb client got none ")
                else:
                    data = client.shmem_list[index][0:meta.size]
                    data = data.reshape((meta.height, meta.width, 3))
                    self.handleFrame__(data, meta)
            # 3. handle message from the master process (i,e machine vision process )
            if fd == self.intercom_fd:
                obj = self.intercom_client.pullObject()
                self.handleMessage__(obj)

    def handleFrame__(self, frame, meta):
        print("ClientProcess: handleFrame__ : got frame", frame.shape, "from slot", meta.slot)
        """
        metadata has the following members :
        size 
        width
        height 
        slot 
        mstimeout
        """
        imgblurred = cv2.GaussianBlur(frame, (15, 15), 0)
        # Lets convert the image to HSV
        imgHSV = cv2.cvtColor(imgblurred, cv2.COLOR_BGR2HSV)

        # Define the mask
        lower_mask_value = [18, 50, 50]
        upper_mask_value = [36, 255, 255]

        lower_mask_value = np.array(lower_mask_value, dtype='uint8')
        upper_mask_value = np.array(upper_mask_value, dtype='uint8')

        mask = cv2.inRange(imgHSV, lower_mask_value, upper_mask_value)

        # Count the total number of red pixels ; total number of non zero pixels
        total_number = cv2.countNonZero(mask)
        print('total number : ', int(total_number))
        if total_number > 500:
            print("fire detected")

        # do something with the frame then forward it to the master process (i,e machine vision process )
        ## TODO: if the frame is too big, the client will hang -- To deal with later
        self.server.pushFrame(frame[0:10, 0:10, :], meta.slot, meta.mstimeout)
        # send message to main process like this
        # self.send_out__({})

    def handleMessage__(self, obj):
        print("rgbClientSide process : handleMessage__ : got a message from master ",obj)

    def c__listenIntercom(self,
                          name = None,
                          n_ringbuffer = None,
                          n_bytes = None,
                          ipc_index = None,
                          ):
        client = ShmemClient(
            name = name,
            n_ringbuffer = n_ringbuffer,
            n_bytes = n_bytes,
            mstimeout = self.mstimeout
        )
        eventfd = getEventFd(ipc_index)
        client.useEventFd(eventfd)
        fd = eventfd.getFd()
        # self.intercom_client_by_fd[fd] = client #if you would be listening many clients at a time
        self.intercom_client = client
        self.intercom_fd = fd

    def c__dropIntercom(self
                        # ipc_index = None,
                        ):
        # fd = getFdFromIndex(ipc_index)
        # self.intercom_client_by_fd.pop(fd) # if you would be listening many clients at a time
        self.intercom_client = None
        self.intercom_fd = None

    """FRONTEND

    These methods are called by your main python process
    """

    def getRGB24ServerPars(self):
        pars = {
            "name": self.server_name,
            "n_ringbuffer": self.server_n_ringbuffer,
            "width": self.server_width,
            "height": self.server_height,
            "ipc_index": eventFdToIndex(self.event_fd)
        }
        print("getRGB24ServerPars:", pars)
        return pars

    def listenIntercom(self,
                       name=None,
                       n_ringbuffer=None,
                       n_bytes=None,
                       ipc_index=None
                       ):
        if self.intercom_ipc_index is not None:
            print("listenIntercom: already listening to master")
            return

        self.sendMessageToBack(MessageObject(
            "listenIntercom",
            name=name,
            n_ringbuffer=n_ringbuffer,
            n_bytes=n_bytes,
            ipc_index=ipc_index  # event fd index for the intecom channel
        ))
        self.intercom_ipc_index = ipc_index

    def dropIntercom(self):
        if self.intercom_ipc_index is None:
            print("dropIntercom: no intercom")
            return
        self.sendMessageToBack(MessageObject(
            "dropIntercom"
            # ipc_index = ipc_index # event fd index for the intecom channel
        ))
        self.intercom_ipc_index = None
def test4():
    """Two clients, one master process
    """
    import numpy

    shmem_name1 = "kokkelis1"
    n_buffer1 = 10
    image_dimensions1 = (400, 300)
    server1 = ShmemRGBServer(
        name=shmem_name1,
        n_ringbuffer=n_buffer1,  # size of ring buffer
        width=image_dimensions1[0],
        height=image_dimensions1[1],
        verbose=True)
    p1 = QShmemClientProcess("test1",
                             n_buffer=n_buffer1,
                             image_dimensions=image_dimensions1,
                             shmem_verbose=True,
                             shmem_name=shmem_name1)

    shmem_name2 = "kokkelis2"
    n_buffer2 = 10
    image_dimensions2 = (400, 300)
    server2 = ShmemRGBServer(
        name=shmem_name2,
        n_ringbuffer=n_buffer2,  # size of ring buffer
        width=image_dimensions2[0],
        height=image_dimensions2[1],
        verbose=True)
    p2 = QShmemClientProcess("test2",
                             n_buffer=n_buffer2,
                             image_dimensions=image_dimensions2,
                             shmem_verbose=True,
                             shmem_name=shmem_name2)

    p1.setDebug()
    p1.start()
    p2.setDebug()
    p2.start()

    pm = QShmemMasterProcess("master_test")
    pm.setDebug()
    pm.start()
    """
    p.activate(n_buffer=n_buffer, 
        image_dimensions=image_dimensions, 
        shmem_name=shmem_name)
    """
    p1.activate()
    p2.activate()

    img = numpy.zeros((300, 400, 3), dtype=numpy.uint8)
    for i in range(10):
        img[:, :, :] = i
        server1.pushFrame(img, 1, 123)
        server2.pushFrame(img, 2, 123)
        time.sleep(0.1)

    print("\nConnecting master process\n")
    p1.setMasterProcess(pm)
    p2.setMasterProcess(pm)

    for i in range(10):
        img[:, :, :] = i
        server1.pushFrame(img, 1, 123)
        server2.pushFrame(img, 2, 123)
        time.sleep(0.1)

    p1.unsetMasterProcess(pm)
    p2.unsetMasterProcess(pm)

    p1.stop()
    p2.stop()

    pm.stop()
class QShmemClientProcess(QShmemProcess):
    """Like QShmemProcess, but uses a common master process
    """
    """
    def c__setMasterProcess(self, 
            ipc_index = None,
            n_buffer = None,
            image_dimensions = None,
            shmem_name = None):
    """
    def c__setMasterProcess(self, ipc_index=None):
        # get shmem parameters from master process frontend
        self.ipc_index = ipc_index
        self.eventfd, self.master_pipe = singleton.ipc.get1(self.ipc_index)
        # self.n_buffer etc. have been set by a call to c__activate
        self.server = ShmemRGBServer(
            name=self.shmem_name_server,
            n_ringbuffer=self.n_buffer,  # size of ring buffer
            width=self.image_dimensions[0],
            height=self.image_dimensions[1],
            verbose=self.shmem_verbose)
        self.server.useEventFd(self.eventfd)  # activate eventfd API
        singleton.ipc.set(ipc_index)

    def c__unsetMasterProcess(self):
        # singleton.ipc.release(self.ipc_index) # not here
        self.server = None
        self.master_pipe = None
        self.eventfd = None

    # ****

    def __init__(self, name="QShmemClientProcess", **kwargs):
        super().__init__(name=name, **kwargs)
        self.shmem_name_server = "valkkashmemserver" + str(id(self))
        # parameterInitCheck(QShmemClientProcess.parameter_defs, kwargs, self)
        self.ipc_index = None  # used at the frontend
        self.master_process = None

    def preRun_(self):
        self.logger.debug("preRun_")
        self.c__deactivate()  # init variables
        self.c__unsetMasterProcess()

    def postRun_(self):
        """Clear shmem variables
        """
        self.c__deactivate()
        self.c__unsetMasterProcess()

    def run(self):
        self.preRun_()
        while self.loop:
            if self.listening:
                self.cycle_()
                self.readPipes__(timeout=0)  # timeout = 0 == just poll
            else:
                self.readPipes__(timeout=self.timeout)  # timeout of 1 sec

        self.postRun_()
        # indicate front end qt thread to exit
        self.back_pipe.send(None)
        self.logger.debug("bye!")

    def cycle_(self):
        """Receives frame from the shmem client and sends them for further
        processing to a master process
        """
        # get rgb frame from the filterchain
        index, meta = self.client.pullFrame()
        if (index is None):
            self.logger.debug("Client timed out..")
            return

        self.logger.debug("Client index, size = %s", index)
        data = self.client.shmem_list[index][0:meta.size]
        img = data.reshape((meta.height, meta.width, 3))
        # forward rgb frame to master process (yolo etc.)
        self.logger.debug("cycle_: got frame %s", img.shape)

        if self.server is not None:
            self.logger.debug("cycle_ : pushing to server")
            self.server.pushFrame(img, meta.slot, meta.mstimestamp)
            # receive results from master process
            message = self.master_pipe.recv()
            print("reply from master process:", message)

    # *** frontend ***

    def setMasterProcess(self, master_process=None):
        # ipc_index, n_buffer, image_dimensions, shmem_name # TODO
        self.master_process = master_process
        self.ipc_index = singleton.ipc.reserve()

        # first, create the server
        self.sendMessageToBack(
            MessageObject("setMasterProcess", ipc_index=self.ipc_index))

        # this will create the client:
        # self.n_buffer etc. have been set by call to self.activate
        master_process.registerClient(ipc_index=self.ipc_index,
                                      n_buffer=self.n_buffer,
                                      image_dimensions=self.image_dimensions,
                                      shmem_name=self.shmem_name_server)

    def unsetMasterProcess(self):  # , master_process):
        if self.master_process is None:
            self.logger.warning("unsetMasterProcess: none set")
            return

        self.sendMessageToBack(MessageObject("unsetMasterProcess"))
        self.master_process.unregisterClient(ipc_index=self.ipc_index)
        singleton.ipc.release(self.ipc_index)
        self.ipc_index = None
        self.master_process = None

    def requestStop(self):
        self.unsetMasterProcess()
        super().requestStop()

    """