Ejemplo n.º 1
0
    def __setup_subscriber(self):
        self.rc_data.delete(self.opt.sub_channel)

        # Dummy set value
        # expired_at = 2 # in seconds
        # redis_set(self.rc_data, self.opt.sub_channel, True, expired_at)
        redis_set(self.rc_data, self.opt.sub_channel, 1)
Ejemplo n.º 2
0
    def run(self):
        print("\nReading video:")
        # while True:
        while self.is_running:
            try:
                # t0_stream_setup = time.time()
                self.cap = cv.VideoCapture(self.opt.source)
                # t_stream_setup = time.time() - t0_stream_setup
                # t_stream_setup_key = "stream-setup-" + str(self.opt.drone_id)
                t_stream_setup_key = "stream-start-" + str(self.opt.drone_id)
                redis_set(self.rc_latency, t_stream_setup_key, time.time())

                # Latency:
                # t_stream_setup_key = "stream-setup-" + str(self.opt.drone_id)
                # redis_set(self.rc_latency, t_stream_setup_key, t_stream_setup)
                # print('\nLatency [Stream Setup Time]: (%.5fs)' % (t_stream_setup))

                if self.opt.enable_cv_out:
                    cv.namedWindow("Image", cv.WND_PROP_FULLSCREEN)
                    cv.resizeWindow("Image", 1366, 768)  # Enter your size

                self.__start_streaming()
            except:
                print(
                    "\nUnable to communicate with the Streaming. Restarting . . ."
                )
                # time.sleep(1) # Delay 1 second before trying again
                # The following frees up resources and closes all windows
                self.cap.release()
                if self.opt.enable_cv_out:
                    cv.destroyAllWindows()
Ejemplo n.º 3
0
    def __load_balancing(self, frame_id, ret, frame, save_path):
        # Initially, send process into first worker
        self.worker_id += 1
        # self.worker_id = 1
        stream_channel = common_settings["redis_config"][
            "channel_prefix"] + str(self.worker_id)

        # Check worker status first, please wait while still working
        # print(">>>>>> __worker_status = ", self.__worker_status())
        w = 0
        wait_time = self.wait_time
        if redis_get(self.rc_data, self.worker_id) is None:
            print("This worker is OFF. Nothing to do")
            print(
                "TBD next time: Should skip this worker and move to the next worker instead"
            )
            self.__find_optimal_worker()
        else:
            # None = DISABLED; 1=Ready; 0=Busy
            while self.__worker_status() == 0:
                # print("\nWorker-%d is still processing other image, waiting (%ds) ..." % (self.worker_id, w))
                # print("\nWorker-%d is still processing other image, waiting ... " % self.worker_id)
                # time.sleep(0.005)
                if not self.opt.disable_delay:
                    time.sleep(self.wait_time)
                w += self.wait_time

            # Send multi-process and set the worker as busy (value=False)
            print("### Sending the work into [worker-#%d] @ `%s`" %
                  ((self.worker_id), stream_channel))
            Process(target=frame_producer,
                    args=(
                        self.rc,
                        frame_id,
                        ret,
                        frame,
                        save_path,
                        stream_channel,
                        self.rc_latency,
                        self.opt.drone_id,
                    )).start()
            redis_set(self.rc_data, self.worker_id, 0)

        self.__reset_worker()
Ejemplo n.º 4
0
    def __iterate_frames(self, this_frame_id=None):
        # Run inference
        self.t0 = time.time()
        # frame_id = 0
        for path, img, im0s, vid_cap in self.dataset:
            self.frame_id += 1
            t = time.time()

            # Get detections
            ts_det = time.time()
            img = torch.from_numpy(img).to(self.device)
            if img.ndimension() == 3:
                img = img.unsqueeze(0)
            self.pred = self.model(img)[0]
            # print('\n # Total Inference time: (%.3fs)' % (time.time() - ts_det))
            t_inference = time.time() - ts_det
            self.time_inference += t_inference
            self.time_inference_list.append(t_inference)

            # Latency: Inference
            print('\nLatency [Inference] of frame-%s: (%.5fs)' %
                  (str(this_frame_id), t_inference))
            t_inference_key = "inference-" + str(
                self.opt.drone_id) + "-" + str(this_frame_id)
            redis_set(self.rc_latency, t_inference_key, t_inference)

            # Default: Disabled
            if self.opt.half:
                self.pred = self.pred.float()

            # Apply NMS: Non-Maximum Suppression
            ts_nms = time.time()
            # to Removes detections with lower object confidence score than 'conf_thres'
            self.pred = non_max_suppression(self.pred,
                                            self.opt.conf_thres,
                                            self.opt.iou_thres,
                                            classes=self.opt.classes,
                                            agnostic=self.opt.agnostic_nms)
            # print('\n # Total Non-Maximum Suppression (NMS) time: (%.3fs)' % (time.time() - ts_nms))
            t_nms = time.time() - ts_nms
            self.time_nms += t_nms
            self.time_nms_list.append(t_nms)

            # Latency: NMS
            print('\nLatency [NMS] of frame-%s: (%.5fs)' %
                  (str(this_frame_id), t_nms))
            t_nms_key = "nms-" + str(
                self.opt.drone_id) + "-" + str(this_frame_id)
            redis_set(self.rc_latency, t_nms_key, t_nms)

            # Apply Classifier: Default DISABLED
            if self.classify:
                self.pred = apply_classifier(self.pred, self.modelc, img, im0s)

            # Process detections
            '''
            p = path
            s = string for printing
            im0 = image (matrix)
            '''

            for i, det in enumerate(self.pred):  # detections per image
                if self.webcam:  # batch_size >= 1
                    p, self.str_output, im0 = path[i], '%g: ' % i, im0s[i]
                else:
                    p, self.str_output, im0 = path, '', im0s

                self.save_path = str(Path(self.out) / Path(p).name)
                self.str_output += '%gx%g ' % img.shape[2:]  # print string
                if det is not None and len(det):
                    # Rescale boxes from img_size to im0 size
                    det[:, :4] = scale_coords(img.shape[2:], det[:, :4],
                                              im0.shape).round()

                    ts_mbbox = time.time()
                    if self.mbbox_algorithm:
                        self.__mbbox_detection(det, im0)  # modifying Mb-box
                    t_mbbox = time.time() - ts_mbbox
                    self.time_mbbox += t_mbbox
                    self.time_mbbox_list.append(t_mbbox)

                    # Latency: MB-Box
                    print('\nLatency [MB-Box Algorithm] of frame-%s: (%.5fs)' %
                          (str(this_frame_id), t_mbbox))
                    t_mbbox_key = "mbbox-" + str(
                        self.opt.drone_id) + "-" + str(this_frame_id)
                    redis_set(self.rc_latency, t_mbbox_key, t_mbbox)

                    ts_default = time.time()
                    if not self.opt.maximize_latency:
                        if self.default_algorithm:
                            self.__default_detection(det, im0)
                    t_default = time.time() - ts_default
                    self.time_default += t_default
                    self.time_default_list.append(t_default)

                    # Latency: Default Detection
                    print(
                        '\nLatency [Default Detection] of frame-%s: (%.5fs)' %
                        (str(this_frame_id), t_default))
                    t_default_key = "draw2bbox-" + str(
                        self.opt.drone_id) + "-" + str(this_frame_id)
                    redis_set(self.rc_latency, t_default_key, t_default)

                    # Print time (inference + NMS)
                    # print('%sDone. (%.3fs)' % (self.str_output, time.time() - t))

                    print(
                        'Done. (%.3fs) --> '
                        'Inference(%.3fs); NMS(%.3fs); MB-Box(%.3fs); Default-Bbox(%.3fs)'
                        % ((time.time() - t), t_inference, t_nms, t_mbbox,
                           t_default))

                    # Save end latency calculation
                    t_end_key = "end-" + str(self.opt.drone_id)
                    redis_set(self.rc_latency, t_end_key, time.time())

                    # Mark last processed frame
                    t_last_frame_key = "last-" + str(self.opt.drone_id)
                    redis_set(self.rc_latency, t_last_frame_key,
                              int(this_frame_id))

                    # latency: End-to-end Latency, each frame
                    t_sframe_key = "start-fi-" + str(
                        self.opt.drone_id
                    )  # to calculate end2end latency each frame.
                    t_end2end_frame = redis_get(
                        self.rc_latency, t_end_key) - redis_get(
                            self.rc_latency, t_sframe_key)
                    t_e2e_frame_key = "end2end-frame-" + str(
                        self.opt.drone_id) + "-" + str(this_frame_id)
                    redis_set(self.rc_latency, t_e2e_frame_key,
                              t_end2end_frame)
                    print(
                        '\nLatency [End2end this frame] of frame-%s: (%.5fs)' %
                        (str(this_frame_id), t_end2end_frame))

                    # latency: End-to-end Latency TOTAL
                    t_start_key = "start-" + str(self.opt.drone_id)
                    t_end2end = redis_get(self.rc_latency,
                                          t_end_key) - redis_get(
                                              self.rc_latency, t_start_key)
                    t_e2e_key = "end2end-" + str(self.opt.drone_id)
                    redis_set(self.rc_latency, t_e2e_key, t_end2end)
                    print('\nLatency [This End2end] of frame-%s: (%.5fs)' %
                          (str(this_frame_id), t_end2end))

                    # Stream results
                    # if self.view_img:
                    #     cv2.imshow(p, im0)
                    #     if cv2.waitKey(1) == ord('q'):  # q to quit
                    #         raise StopIteration

                    self.__save_results(im0, vid_cap, self.frame_id)
Ejemplo n.º 5
0
    def waiting_frames(self):
        print("Starting YOLOv3 image detector")
        t0 = time.time()
        self.__load_weight()
        t_load_weight = time.time() - t0
        # print(".. Load `weight` in (%.3fs)" % t_load_weight)

        # Latency: Load YOLOv3 Weight
        t_weight_key = "weight-" + str(self.opt.drone_id)
        redis_set(self.rc_latency, t_weight_key, t_load_weight)
        print('\nLatency [Load `weight`]: (%.5fs)' % (t_load_weight))

        t0 = time.time()
        self.__eval_model()
        t_load_eval_model = time.time() - t0
        # print(".. Load function `eval_model` in (%.3fs)" % t_load_eval_model)

        # Latency: Execute Evaluation Model
        t_eval_model_key = "evalModel-" + str(self.opt.drone_id)
        redis_set(self.rc_latency, t_eval_model_key, t_load_eval_model)
        print('\nLatency [Load `Eval Model`]: (%.5fs)' % (t_load_eval_model))

        self.__get_names_colors()

        # Setup redis subscriber availability
        self.__setup_subscriber()

        # Waiting for get the image information
        stream_ch = "stream_" + self.opt.sub_channel
        print("\n### Waiting for get the image information @ Channel `%s`" %
              stream_ch)
        pubsub = self.rc.pubsub()
        pubsub.subscribe([stream_ch])
        for item in pubsub.listen():
            # noinspection PyPackageRequirements
            try:
                t0_sub2frame = time.time()
                # Start fetching information
                fetch_data = json.loads(item['data'])
                frame_id = fetch_data['frame_id']
                # print('Streamer collects : ', fetch_data)

                # Latency: subscribing frame
                t_sub2frame = time.time() - t0_sub2frame
                t_sub2frame_key = "sub2frame-" + str(
                    self.opt.drone_id) + "-" + str(frame_id)
                redis_set(self.rc_latency, t_sub2frame_key, t_sub2frame)
                print(
                    '\nLatency [Subscriber extracting information] of frame-%s: (%.5fs)'
                    % (str(frame_id), t_sub2frame))

                self.source = fetch_data["img_path"]
                # print('img_path : ', self.source)
                # Load image from pub: get `img_path`
                t0_load_img = time.time()
                self.__set_data_loader()
                t_load_img = time.time() - t0_load_img
                # print(".. load image into variable in (%.3fs)" % (time.time() - t0))
                t_load_img_key = "loadIMG-" + str(
                    self.opt.drone_id) + "-" + str(frame_id)
                redis_set(self.rc_latency, t_load_img_key, t_load_img)
                print(
                    '\nLatency [Loads image into YOLOv3 Worker] of frame-%s: (%.5fs)'
                    % (str(frame_id), t_load_img))

                # # Check worker status first, please wait while still working
                # is_worker_ready = redis_get(self.rc_data, self.opt.sub_channel)
                # print(">>>>>> is_worker_ready = ", is_worker_ready)
                # if is_worker_ready:
                #     print("\nWorker-%d is still running, waiting to finish ..." % self.opt.sub_channel)
                #     time.sleep(0.1)

                # Start processing image
                print("\nStart processing to get MB-Box.")
                redis_set(self.rc_data, self.opt.sub_channel,
                          0)  # set as `Busy`
                # print("Set as busy Done.")
                self.__iterate_frames(
                    frame_id)  # Perform detection in each frame here
                # print(" >>> Hasil MB-Box Img = ", self.mbbox_img)
                # print("Process finished.")

                frame_id = str(fetch_data["frame_id"])
                prev_fid = str(self.opt.drone_id) + "-" + str(
                    (int(frame_id) - 1))

                # # TBD: Start behavior detection in background process, in every 30 frames (FPS=30)
                # behave_det = BehaviorDetection(self.opt, int(frame_id), self.detected_mbbox)
                # if int(frame_id) % self.fps and self.detected_mbbox > 0:
                #     behave_det.run()

                # Preparing to send the frames.
                if self.mbbox_img is not None:
                    # output_path = self.opt.mbbox_output + "frame-%s.jpg" % frame_id
                    output_path = self.opt.mbbox_output + str(
                        self.opt.drone_id) + "/frame-%s.jpg" % frame_id

                    # Try writing synchronously: store ONLY when (frame-1) has been stored
                    # print(" ######## PREV_ID = ", redis_get(self.rc, prev_fid))
                    while redis_get(self.rc,
                                    prev_fid) is None and int(frame_id) > 1:
                        # print(" ######## Waiting previous frame to be stored. PREV_ID = ", redis_get(self.rc, prev_fid))
                        # time.sleep(1)
                        pass

                    t0_save_mbbox_img = time.time()
                    cv2.imwrite(output_path, self.mbbox_img)
                    # print("Saving image in: ", output_path)
                    # print(".. MB-Box image is saved in (%.3fs)" % (time.time() - t0))
                    t_save_mbbox_img = time.time() - t0_save_mbbox_img
                    t_save_mbbox_img_key = "save2mmboxIMG-" + str(
                        self.opt.drone_id) + "-" + str(frame_id)
                    redis_set(self.rc_latency, t_save_mbbox_img_key,
                              t_save_mbbox_img)
                    print(
                        '\nLatency [Save MB-Box Image] of frame-%s: (%.5fs)' %
                        (str(frame_id), t_save_mbbox_img))

                    # Set that this frame has been successfully added
                    expired_at = 20  # in seconds
                    key = str(self.opt.drone_id) + "-" + frame_id
                    redis_set(self.rc, key, True, expired_at)
                else:
                    print("This MB-Box is NONE. nothing to be saved yet.")

                # self.__save_latency_to_csv()

                # Restore availibility
                redis_set(self.rc_data, self.opt.sub_channel,
                          1)  # set as `Ready`
                print("\n### This Worker-%s is ready to serve again. \n\n" %
                      self.opt.sub_channel)

                # Set prev_fid as DONE
                redis_set(self.rc_data, prev_fid, None)  # set as `Ready`

                # if this is latest frame: Set this frame as latest
                # key = "drone_id-latest", value: "drone_id-frame_id"
                # redis_set(self.rc_data, prev_fid, None) # set as `Ready`
            except:
                pass
Ejemplo n.º 6
0
    def __start_streaming(self):
        n = 0
        frame_id = 0
        received_frame_id = 0
        # t_start = time.time()
        # redis_set(self.rc_latency, "start", t_start)

        # Save timestamp to start extracting video streaming.
        t_start_key = "start-" + str(self.opt.drone_id)
        redis_set(self.rc_latency, t_start_key, time.time())

        # while (self.cap.isOpened()):
        while (self.cap.isOpened()) and self.is_running:
            received_frame_id += 1

            t_sframe_key = "start-fi-" + str(
                self.opt.drone_id)  # to calculate end2end latency each frame.
            redis_set(self.rc_latency, t_sframe_key, time.time())

            n += 1

            t0_frame = time.time()
            # ret = a boolean return value from getting the frame, frame = the current frame being projected in the video
            try:
                ret, frame = self.cap.read()

                # Latency: capture each frame
                t_frame = time.time() - t0_frame
                print('\nLatency [Reading stream frame] of frame-%d: (%.5fs)' %
                      (received_frame_id, t_frame))
                t_frame_key = "frame-" + str(
                    self.opt.drone_id) + "-" + str(frame_id)
                redis_set(self.rc_latency, t_frame_key, t_frame)

                if n == self.opt.delay:  # read every n-th frame

                    if ret:
                        # Start capturing here
                        if received_frame_id >= self.start_frame_id:
                            frame_id += 1
                            # Force stop after n frames
                            # if frame_id > int(self.max_frames):
                            if frame_id == (int(self.max_frames) + 1):
                                self.is_running = False
                                break

                            save_path = self.opt.output_folder + str(
                                self.opt.drone_id) + "/frame-%d.jpg" % frame_id
                            self.__load_balancing(frame_id, ret, frame,
                                                  save_path)

                            if self.opt.enable_cv_out:
                                cv.imshow("Image", frame)

                    else:
                        print("IMAGE is INVALID.")
                        print("I guess there is no more frame to show.")
                        break

                    n = 0
                # time.sleep(0.01)  # wait time

            except:
                print("No more frame to show.")
                break

            if cv.waitKey(10) & 0xFF == ord('q'):
                break