Пример #1
0
class ConfluentKafkaProducer(KafkaProducerInterface):
    def __init__(self, config, logger):
        super(ConfluentKafkaProducer, self).__init__()

        self.logger = logger

        conf = {
            'bootstrap.servers': ','.join(config['kafka_bootstrap_servers']),
            'broker.version.fallback': config['kafka_broker_version_fallback'],
            'api.version.request': config['kafka_api_version_request'],
            'queue.buffering.max.ms': config['kafka_producer_batch_linger_ms'],
            'queue.buffering.max.kbytes':
            config['kafka_producer_buffer_kbytes'],
            'message.send.max.retries': 3,
            'default.topic.config': {
                'request.required.acks': 1
            }
        }

        self.logger.info("Creating a Confluent Kafka Producer",
                         {"config": json.dumps(conf, indent=4)})
        self.producer = Producer(dict(conf,
                                      **{'error_cb': self.error_callback}),
                                 logger=logger.logger)

        # Service any logging
        self.producer.poll(0.25)

    def error_callback(self, error):
        """
        :param error:
        :type error: KafkaError
        :param message:
        :param datum:
        :return:
        """
        if error:
            datum = {}
            datum['success'] = False
            datum['exception'] = error.name()
            datum['description'] = error.str()
            self.logger.error("Kafka error", datum if datum else {})

    def send(self, topic, message, callback=None):

        self.producer.produce(topic,
                              json.dumps(message).encode('utf-8'),
                              callback=callback)

        # Service the delivery callback queue.
        self.producer.poll(0)

    def poll(self):
        self.producer.poll(0)

    def close(self):
        self.producer.flush()
        self.producer.poll(0)
Пример #2
0
def produce(queue, key, val, headers=None):
    logging.info("Producing into %s: %s %s", queue, key, val)
    producer = Producer({
        'bootstrap.servers': KAFK,
        "message.send.max.retries": 2
    })
    producer.poll(0)
    producer.produce(queue, key=key, value=val, headers=headers)
    producer.flush()
Пример #3
0
def produce_test_messages(producer: ConfluenceProducer,
                          topic: Tuple[str, int]) -> Iterable[KafkaMessage]:
    topic_name, num_partitions = topic
    messages = []
    for i in range(10):
        partition = random.randrange(0, num_partitions)
        random_value = "".join(random.choices(ascii_letters, k=5))
        message = KafkaMessage(str(i), random_value, partition)
        messages.append(message)
        producer.produce(topic=topic_name,
                         key=message.key,
                         value=message.value,
                         partition=message.partition)
        producer.flush()
    return messages
Пример #4
0
    def check_connection(self):
        def check_callback(error, event):
            if error:
                if error.code() == KafkaError._MSG_TIMED_OUT:
                    log.error(
                        "This Timout might indicate the broker is down or connection is misconfigured"
                    )
                log.error(f"Error while producing initial msg: {error}")
                raise KafkaSetupError()

        config = ConfigFactory(kafka_client="producer").config
        config["delivery.timeout.ms"] = "3000"  # 3 seconds
        prod = Producer(config)
        prod.produce("pyrandall", "starting simulate", callback=check_callback)
        prod.flush()  # block until callback is called
class StopEventsDataPublisher:
    _logger = logging.getLogger('StopEventsDataPublisher')

    def __init__(self):
        kafka_configs = KafkaHelper.get_kafka_configs()
        self._producer = Producer(kafka_configs)

    def publish_stop_event_records(self,
                                   stop_event_records,
                                   topic=STOP_EVENT_TOPIC):
        self._logger.info(
            "Publishing {} stop event records to {} topic ...".format(
                len(stop_event_records), topic))
        delivered_records = 0

        def callback(err, msg):
            nonlocal delivered_records
            if err is not None:
                self._logger.error("Failed to deliver message: %s: %s" %
                                   (str(msg), str(err)))
            else:
                delivered_records += 1
                self._logger.debug(
                    "Published record to topic {} partition [{}] @ offset {}".
                    format(msg.topic(), msg.partition(), msg.offset()))
                self._logger.debug(
                    'Published records count: {}'.format(delivered_records))

        for trip_id, stop_events in stop_event_records.items():
            stop_data_record = dict()
            stop_data_record[trip_id] = stop_events

            self._producer.produce(topic,
                                   value=json.dumps(stop_data_record),
                                   on_delivery=callback)
            self._producer.poll(0)

        self._producer.flush()

        self._logger.info(
            'Done delivering records to {} topic! A total of {} records were published'
            .format(topic, delivered_records))
Пример #6
0
def main():
    parser = argparse.ArgumentParser(
        epilog="""Description:
           Plays a video from a jpeg topic,
           visualizes the head detection with a bounding box around a head.
           The boundig box is grey when mask detection did not run;
           it is green when a mask is detected;
           it is orange and 'NO MASK' is written above the head when no mask is detected.
           Displays ('-d') or stores ('-o') the result of this demo in the kafka topic.

           Required topics:
           - <prefix>.cam.0.original.Image.jpg
           - <prefix>.cam.0.dets.ObjectDetectionRecord.json
           - <prefix>.cam.0.masks.FaceMaskRecord.json
           """,
        formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument("broker",
                        help="The name of the kafka broker.",
                        type=str)
    parser.add_argument("prefix",
                        help="Prefix of topics (base|skeleton).",
                        type=str)
    parser.add_argument('-f', "--full_screen", action='store_true')
    parser.add_argument('-d', "--display", action='store_true')
    parser.add_argument('-v', "--video_file", action='store_true')
    parser.add_argument('-o',
                        '--output',
                        help='write output image into kafka topic',
                        action='store_true')
    args = parser.parse_args()

    if not args.display and not args.output:
        parser.error(
            "Missing argument: -d (display output) or -o (write output to kafka) is needed"
        )

    if args.output:
        producer = Producer({'bootstrap.servers': args.broker})

    begin_flag = None
    end_flag = EndFlag.NEVER
    if args.video_file:
        begin_flag = BeginFlag.BEGINNING
        end_flag = EndFlag.END_OF_PARTITION
    heartbeat_interval_ms = 1000

    overlay = cv2.imread('resources/powered_by_white.png',
                         cv2.IMREAD_UNCHANGED)

    image_topic = f"{args.prefix}.cam.0.original.Image.jpg"
    detection_topic = f"{args.prefix}.cam.0.dets.ObjectDetectionRecord.json"
    mask_topic = f"{args.prefix}.cam.0.masks.FaceMaskRecord.json"
    output_topic_name = f"{args.prefix}.cam.0.face_mask.Image.jpg"
    frameinfo_topic = f"{args.prefix}.cam.0.frameinfo.FrameInfoRecord.json"

    # Write notification if no message is received for this long
    notification_delay_sec = 10

    # handle full screen
    window_name = "DEMO: Face Mask"
    if args.full_screen:
        cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
        cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN,
                              cv2.WINDOW_FULLSCREEN)

    # read message, draw and display them
    consumer = TimeOrderedGeneratorWithTimeout(
        args.broker,
        "detection", [
            TopicInfo(image_topic),
            TopicInfo(detection_topic),
            TopicInfo(mask_topic),
            TopicInfo(frameinfo_topic)
        ],
        100,
        None,
        True,
        begin_flag=begin_flag,
        end_flag=end_flag,
        heartbeat_interval_ms=heartbeat_interval_ms)

    i = 0
    scaling = 1.0
    img_dimensions = (768, 1024)
    last_image_ts = None
    for msgs in consumer.getMessages():
        if not isinstance(msgs, HeartBeat):
            for ts, v in message_list_to_frame_structure(msgs).items():
                img = v[args.prefix]["0"]["image"]
                if type(img) != np.ndarray:
                    continue
                last_image_ts = int(time.time())

                # Set the image scale
                img_dimensions = (img.shape[0], img.shape[1])
                shape_orig = v[args.prefix]["0"]["head_detection"].pop(
                    "image", {})
                if shape_orig:
                    scaling = img.shape[1] / shape_orig["frame_info"]["columns"]

                for head_detection in v[args.prefix]["0"]["head_detection"]:
                    object_detection_record = v[args.prefix]["0"][
                        "head_detection"][head_detection]["bounding_box"]
                    if object_detection_record["type"] != "PERSON_HEAD":
                        continue
                    mask_record = v[args.prefix]["0"]["head_detection"][
                        head_detection]["face_mask"]

                    mask_text = ""

                    if not mask_record:
                        color = COLOR_DARK_GREY
                    elif mask_record["has_mask"]:
                        color = COLOR_GREEN
                    else:
                        mask_text = "NO MASK"
                        color = COLOR_ORANGE

                    # draw bounding_box
                    img = draw_nice_bounding_box(
                        canvas=img,
                        bounding_box=object_detection_record["bounding_box"],
                        color=color,
                        scaling=scaling)
                    # write age and gender
                    img = draw_nice_text(
                        img,
                        mask_text,
                        object_detection_record["bounding_box"],
                        color,
                        scale=scaling)
                # draw ultinous logo
                img = draw_overlay(canvas=img,
                                   overlay=overlay,
                                   position=Position.BOTTOM_RIGHT,
                                   scale=scaling)

                # produce output topic
                if args.output:
                    producer.produce(output_topic_name,
                                     value=encode_image_to_message(img),
                                     timestamp=ts)
                    producer.poll(0)
                    if i % 100 == 0:
                        producer.flush()
                    i += 1

                # display
                if args.display:
                    cv2.imshow(window_name, img)

        # Write notification until the first message is received
        # (output topic is not updated to ensure kafka timestamp consistency)
        elif args.display and (
                last_image_ts is None
                or last_image_ts + notification_delay_sec < int(time.time())):
            img = np.zeros((*img_dimensions, 3), np.uint8)
            text = "Waiting for input Kafka topics to be populated. \n" \
                "Please make sure that MGR and other necessary services are running."
            img = draw_simple_text(canvas=img, text=text, color=(10, 95, 255))
            cv2.imshow(window_name, img)

        k = cv2.waitKey(33)
        if k == 113:  # The 'q' key to stop
            if args.video_file:
                exit(130)
            break
        elif k == -1:  # normally -1 returned,so don't print it
            continue
        else:
            print(f"Press 'q' key for EXIT!")
Пример #7
0
def main():
    parser = init_parser()
    args = parser.parse_args()
    config_data = parse_config_data(args=args, parser=parser)
    positive_areas = parse_areas(config_data, "positive_areas")
    negative_areas = parse_areas(config_data, "negative_areas")
    detection_types = parse_detection_types(config_data)

    if not args.display and not args.output:
        parser.error(
            "Missing argument: -d (display output) or -o (write output to kafka) is needed"
        )

    if args.output:
        producer = Producer({'bootstrap.servers': args.broker})

    begin_flag = None
    end_flag = None
    if args.video_file:
        begin_flag = BeginFlag.BEGINNING
        end_flag = EndFlag.END_OF_PARTITION

    output_topic_name = f"{args.prefix}.cam.0.filtered_dets.Image.jpg"

    # handle full screen
    window_name = "DEMO: Filtered detection"
    if args.full_screen:
        cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
        cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN,
                              cv2.WINDOW_FULLSCREEN)

    # read message, draw and display them
    consumer = TimeOrderedGeneratorWithTimeout(
        broker=args.broker,
        groupid="detection",
        topics_infos=[
            TopicInfo(
                f"{args.prefix}.cam.0.original.Image.jpg"),  # image_topic
            TopicInfo(
                f"{args.prefix}.cam.0.filtered_dets.ObjectDetectionRecord.json"
            ),  # filtered_detection_topic
            TopicInfo(f"{args.prefix}.cam.0.dets.ObjectDetectionRecord.json"
                      )  # detection_topic
        ],
        latency_ms=100,
        group_by_time=True,
        begin_flag=begin_flag,
        end_flag=end_flag)
    i = 0
    scaling = 1.0
    for msgs in consumer.getMessages():
        for time, v in message_list_to_frame_structure(msgs).items():
            frame_info = v[args.prefix]["0"]
            img = frame_info["image"]
            if type(img) == np.ndarray:
                # Set the image scale
                shape_orig = frame_info["head_detection"].pop("image", {})
                if shape_orig:
                    scaling = img.shape[1] / shape_orig["frame_info"]["columns"]

                # draw bounding_box
                for head_detection in frame_info["head_detection"]:
                    img = draw_bounding_box(
                        object_detection_record=frame_info["head_detection"]
                        [head_detection]["bounding_box"],
                        detection_types=detection_types,
                        img=img,
                        scaling=scaling,
                        color=COLOR_GREY)

                for head_detection in frame_info["filtered_head_detection"]:
                    img = draw_bounding_box(object_detection_record=frame_info[
                        "filtered_head_detection"][head_detection]
                                            ["filtered_bounding_box"],
                                            detection_types=detection_types,
                                            img=img,
                                            scaling=scaling,
                                            color=COLOR_ORANGE)

                draw_areas(areas=positive_areas, img=img, color=COLOR_GREEN)
                draw_areas(areas=negative_areas, img=img, color=COLOR_RED)

                draw_ultinous_logo(canvas=img, scale=scaling)

                # produce output topic
                if args.output:
                    producer.produce(output_topic_name,
                                     value=encode_image_to_message(img),
                                     timestamp=time)
                    producer.poll(0)
                    if i % 100 == 0:
                        producer.flush()
                        i = 0
                    i += 1

                # display
                if args.display:
                    cv2.imshow(window_name, img)
        k = cv2.waitKey(33)
        if k == 113:  # The 'q' key to stop
            if args.video_file:
                exit(130)
            else:
                break
        elif k == -1:  # normally -1 returned,so don't print it
            continue
        else:
            print(f"Press 'q' key for EXIT!")
Пример #8
0
class ModelInference(object):
    def __init__(self,
                 my_id=1,
                 bootstrap_servers='',
                 list_of_partitions=[],
                 request_topic='',
                 inference_topic='',
                 group_id='my_grp'):
        """ Constructor
        :type interval: int
        :param interval: Check interval, in seconds
        """
        self.model = None
        #Create the model instance here
        self.my_id = my_id
        self.t = request_topic
        self.result_t = inference_topic
        self.my_grp_id = group_id
        self.result_t_p = 8
        self.bootstrap_servers = bootstrap_servers

        self.tls = []
        x = 0
        for i in list_of_partitions:
            self.tls.insert(x, TopicPartition(self.t, i))
            x = x + 1
        #self.tls=list_of_partitions
        print(self.tls)
        conf = {
            'bootstrap.servers': bootstrap_servers,
            'sasl.mechanism': 'PLAIN',
            'security.protocol': 'SASL_SSL',
            'ssl.ca.location': '/tmp/cacert.pem',
            'sasl.username': '******',
            'sasl.password': '******',
            # 'key.serializer': StringSerializer('utf_8'),
            # 'value.serializer': StringSerializer('utf_8'),
            'client.id': 'test-sw-1'
        }

        self.producer = Producer(conf)
        conf = {
            'bootstrap.servers': bootstrap_servers,
            #'sasl.mechanism': 'PLAIN',
            'sasl.username': '******',
            'sasl.password': '******',
            'ssl.ca.location': '/tmp/cacert.pem',
            'group.id': group_id,
            'auto.offset.reset': 'smallest'
        }
        self.consumer = consumer = Consumer(conf)
        self.consumer.assign(self.tls)

    def __del__(self):
        print('closing')

        self.producer.flush()
        self.consumer.close()

    def run(self):
        try:
            self.consumer.assign(self.tls)
            i = 0
            while (True):
                msg = self.consumer.poll(timeout=1.0)
                if msg is None: continue

                if msg.error():
                    if msg.error().code() == KafkaError._PARTITION_EOF:
                        # End of partition event
                        sys.stderr.write(
                            '%% %s [%d] reached end at offset %d\n' %
                            (msg.topic(), msg.partition(), msg.offset()))
                    elif msg.error():
                        raise KafkaException(msg.error())
                else:

                    message = loads(msg.value().decode("utf-8"))
                    ingest_ts = message['ingestTs']
                    message_id = message['message_id']
                    truth = message['Class']
                    y_hat = truth  ## Replace with model.predict & model.learn_one(
                    inference_ts = time.time()
                    out = {}
                    out['ingest_ts'] = ingest_ts
                    out['message_id'] = message_id
                    out['truth'] = truth  ## model.learn_one(Y,Y_HAT)
                    out['y_hat'] = y_hat
                    out['inference_ts'] = inference_ts
                    out['dur_evt_inf'] = inference_ts - ingest_ts
                    i = i + 1
                    # sprint(self.result_t)
                    k = str(i)
                    v = json.dumps(out).encode('utf-8')
                    #self.producer.produce(self.result_t, value=v, key=k)
                    # self.producer.flush()

                    if (i % 2 == 0):
                        print('sending to ' + self.result_t + ' ' +
                              str(self.result_t_p) + ' ' + str(out))
                        self.producer.flush()
                #self.producer.close()

        finally:
            # Close down consumer to commit final offsets.
            self.consumer.close()

    def runOld(self):
        print(bootstrap_servers)
        conf = {
            'bootstrap.servers': bootstrap_servers,
            'sasl.mechanism': 'PLAIN',
            'security.protocol': 'SASL_SSL',
            'ssl.ca.location': '/tmp/cacert.pem',
            'sasl.username': '******',
            'sasl.password':
            '******',
            # 'key.serializer': StringSerializer('utf_8'),
            # 'value.serializer': StringSerializer('utf_8'),
            'client.id': 'test-sw-1'
        }

        self.producer = Producer(conf)
        conf = {
            'bootstrap.servers': bootstrap_servers,
            'sasl.mechanism': 'PLAIN',
            'security.protocol': 'SASL_SSL',
            'sasl.username': '******',
            'sasl.password':
            '******',
            'ssl.ca.location': '/tmp/cacert.pem',
            'group.id': 'g-1',
            'auto.offset.reset': 'smallest'
        }
        self.consumer = consumer = Consumer(conf)
        self.consumer.assign(self.tls)
        print('starting ' + str(self.my_id))
        now = datetime.now()
        i = 0
        while True:

            for message in self.consumer:

                message = loads(msg.value().decode("utf-8"))

                ingest_ts = message['ingestTs']
                message_id = message['message_id']
                truth = message['Class']
                y_hat = truth  ## Replace with model.predict & model.learn_one(
                inference_ts = time.time()
                out = {}
                out['ingest_ts'] = ingest_ts
                out['message_id'] = message_id
                out['truth'] = truth  ## model.learn_one(Y,Y_HAT)
                out['y_hat'] = y_hat
                out['inference_ts'] = inference_ts
                out['dur_evt_inf'] = inference_ts - ingest_ts
                i = i + 1
                #sprint(self.result_t)
                self.producer.send(self.result_t,
                                   value=out,
                                   key=str(message_id))
                #self.producer.flush()

                if (i % 1000 == 0):
                    print('sending to ' + self.result_t + ' ' +
                          str(self.result_t_p) + ' ' + str(out))
        self.producer.flush()
        self.producer.close()
Пример #9
0
def main():
    parser = argparse.ArgumentParser(
        epilog="""Description:
           Plays a video from a jpeg topic,
           visualizes head detection with an orage bounding box around a head 
           and writes the IDs given by reid MS above the heads.
           Displays ('-d') or stores ('-o') the result of this demo in the kafka topic.

           Required topics:
           - <prefix>.cam.0.original.Image.jpg
           - <prefix>.cam.0.dets.ObjectDetectionRecord.json
           - <prefix>.cam.99.reids.ReidRecord.json
           """,
        formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument("broker",
                        help="The name of the kafka broker.",
                        type=str)
    parser.add_argument("prefix",
                        help="Prefix of topics (base|skeleton).",
                        type=str)
    parser.add_argument('-f', "--full_screen", action='store_true')
    parser.add_argument('-d', "--display", action='store_true')
    parser.add_argument('-o',
                        '--output',
                        help='write output image into kafka topic',
                        action='store_true')
    args = parser.parse_args()

    if not args.display and not args.output:
        parser.error(
            "Missing argument: -d (display output) or -o (write output to kafka) is needed"
        )

    if args.output:
        producer = Producer({'bootstrap.servers': args.broker})

    overlay = cv2.imread('resources/powered_by_white.png',
                         cv2.IMREAD_UNCHANGED)

    image_topic = f"{args.prefix}.cam.0.original.Image.jpg"
    detection_topic = f"{args.prefix}.cam.0.dets.ObjectDetectionRecord.json"
    reid_topic = f"{args.prefix}.cam.{REID_TOPIC_ID}.reids.ReidRecord.json"
    output_topic_name = f"{args.prefix}.cam.0.reids.Image.jpg"

    # handle full screen
    window_name = TITLE
    if args.full_screen:
        cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
        cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN,
                              cv2.WINDOW_FULLSCREEN)

    # read message, draw and display them
    consumer = TimeOrderedGeneratorWithTimeout(args.broker, "detection", [
        TopicInfo(image_topic),
        TopicInfo(detection_topic),
        TopicInfo(reid_topic, drop=False),
    ], 500, None, True)

    i = 0
    stored_ids = {}
    for msgs in consumer.getMessages():
        for time, v in message_list_to_frame_structure(msgs).items():

            reid_records = v[args.prefix][REID_TOPIC_ID].get("reid", {})
            img = v[args.prefix]["0"]["image"]
            if type(img) == np.ndarray:

                for key in v[args.prefix]["0"]["head_detection"]:
                    object_detection_record = v[args.prefix]["0"][
                        "head_detection"][key]["bounding_box"]

                    color = COLOR_GREY
                    reid_record = reid_records.get(key)
                    if reid_record:
                        color = COLOR_ORANGE
                        reid_key = reid_record["reg_refs"][0]["subject"]["key"]

                        key_to_display = stored_ids.get(reid_key, None)
                        if key_to_display is None:
                            key_to_display = len(stored_ids) + 1
                            stored_ids[reid_key] = key_to_display

                        # user id
                        img = draw_nice_text(
                            canvas=img,
                            text=str(key_to_display),
                            bounding_box=object_detection_record[
                                "bounding_box"],
                            color=color)

                    # draw bounding_box
                    img = draw_nice_bounding_box(
                        canvas=img,
                        bounding_box=object_detection_record["bounding_box"],
                        color=color)

                # draw ultinous logo
                img = draw_overlay(canvas=img,
                                   overlay=overlay,
                                   position=Position.BOTTOM_RIGHT)

                # produce output topic
                if args.output:
                    producer.produce(output_topic_name,
                                     value=encode_image_to_message(img),
                                     timestamp=time)
                    producer.poll(0)
                    if i % 100 == 0:
                        producer.flush()
                    i += 1

                # display
                if args.display:
                    cv2.imshow(window_name, img)
        k = cv2.waitKey(33)
        if k == 113:  # The 'q' key to stop
            break
        elif k == -1:  # normally -1 returned,so don't print it
            continue
        else:
            print(f"Press 'q' key for EXIT!")
Пример #10
0
class AioProducer:

    def __init__(self, config, kafka_redis, message_queue_key, name=None, loop=None):
        self.loop = loop or asyncio.get_event_loop()
        assert config is not None, 'init kafka product error, config is None'
        self.kafka_redis = kafka_redis
        self.message_queue_key = message_queue_key
        self._producer = Producer(**config)
        # 'INIT' -> 'RUNNING' -> 'STOP'
        self.status = 'INIT'
        self.name = name
        self.__heath_check = Thread(target=self.__producer_health_loop)
        self.__heath_check.setDaemon(True)
        self.__heath_check.start()

    def __producer_health_loop(self):
        while self.status != 'STOP':
            self._producer.poll(1)

    def stop(self):
        self.status = 'STOP'

    def close(self):
        """
        kafka生产者的poll()方法使用异步方式进行数据推送,当程序结束的时候,不能保证数据已经完成推送。
        因此需要在结束生产者之前,使用flush()方法将未推送的数据已同步方式推送完成,等待推送完成后再结束进程。
        :return:
        """
        try:
            self.__heath_check.join()
            self._producer.flush()
        except Exception as e:
            logger.error(f'{self.name} close error: {e.args}, traceback: {traceback.format_exc()}')

    async def publish(self, topic: str, message: str):
        """
        kafka生产者主函数,将传入的数据data推送到指定topic中, 并在推送完成后调用callback回调函数

        :param topic:     推送数据的kafka主题
        :param message:   推送数据 str
        :return: 是否推送成功 True/False
        """
        result = self.loop.create_future()

        def ack(err, msg):
            """  成功/失败的处理函数 """
            if err is not None:
                logger.error(f'{message} delivery failed: {err}')
                self.loop.call_soon_threadsafe(result.set_result, False)
            else:
                logger.info(f'{message} delivered to {msg.topic()} partition:[{msg.partition()}]')
                self.loop.call_soon_threadsafe(result.set_result, True)

        try:
            self._producer.produce(topic, message, on_delivery=ack)
            return await result
        except BufferError as e:
            logger.error('Local producer queue is full ({} messages awaiting delivery): try again\n'.format(
                len(self._producer)))
            await asyncio.sleep(1)
        except KafkaException as e:
            logger.error(f'producer publish {message} error, '
                         f'topic:{topic}.error_info: {e.args[0]}')
        except Exception as e:
            logger.error(f'producer publish {message} error'
                         f'topic:{topic}.error_info: {traceback.format_exc()}', exc_info=e)
        return False

    async def __get_message(self) -> str:
        try:
            with await self.kafka_redis.pool as p:
                return await p.lpop(self.message_queue_key)
        except TimeoutError:
            logger.info(f'redis_key:{self.message_queue_key} timeout')
        return ''

    async def __retry_message(self, message):
        try:
            with await self.kafka_redis.pool as p:
                return await p.rpush(self.message_queue_key, message)
        except TimeoutError:
            logger.info(f'redis_key:{self.message_queue_key} timeout')
        return 0

    async def run(self):
        while self.status == 'RUNNING':
            message = Message.loads(await self.__get_message())
            if not message:
                await asyncio.sleep(1)
                continue
            flag = await self.publish(topic=message.topic, message=message.dumps())
            push_2_redis_flag = False
            while not flag and not push_2_redis_flag:
                message.delivery_retry()
                push_2_redis_flag = await self.__retry_message(message.dumps())
                if not push_2_redis_flag:
                    await asyncio.sleep(5)
        await self.loop.run_in_executor(None, self.close)
Пример #11
0
def main():
    parser = argparse.ArgumentParser(
        epilog="""Description:
           Plays a video from a jpeg topic,
           visualizes the head detection with an orage bounding box around a head
           and writes demography data (gender & age) data above the heads.
           Displays ('-d') or stores ('-o') the result of this demo in the kafka topic.
           
           Required topics:
           - <prefix>.cam.0.original.Image.jpg
           - <prefix>.cam.0.dets.ObjectDetectionRecord.json
           - <prefix>.cam.0.genders.GenderRecord.json
           - <prefix>.cam.0.ages.AgeRecord.json
           """,
        formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument("broker",
                        help="The name of the kafka broker.",
                        type=str)
    parser.add_argument("prefix",
                        help="Prefix of topics (base|skeleton).",
                        type=str)
    parser.add_argument('-f', "--full_screen", action='store_true')
    parser.add_argument('-d', "--display", action='store_true')
    parser.add_argument('-o',
                        '--output',
                        help='write output image into kafka topic',
                        action='store_true')
    args = parser.parse_args()

    if not args.display and not args.output:
        parser.error(
            "Missing argument: -d (display output) or -o (write output to kafka) is needed"
        )

    if args.output:
        producer = Producer({'bootstrap.servers': args.broker})

    overlay = cv2.imread('resources/powered_by_white.png',
                         cv2.IMREAD_UNCHANGED)

    image_topic = f"{args.prefix}.cam.0.original.Image.jpg"
    detection_topic = f"{args.prefix}.cam.0.dets.ObjectDetectionRecord.json"
    gender_topic = f"{args.prefix}.cam.0.genders.GenderRecord.json"
    age_topic = f"{args.prefix}.cam.0.ages.AgeRecord.json"
    output_topic_name = f"{args.prefix}.cam.0.demography.Image.jpg"

    # handle full screen
    window_name = "DEMO: Demography (gender & age)"
    if args.full_screen:
        cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
        cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN,
                              cv2.WINDOW_FULLSCREEN)

    # read message, draw and display them
    consumer = TimeOrderedGeneratorWithTimeout(args.broker, "detection", [
        TopicInfo(image_topic),
        TopicInfo(detection_topic),
        TopicInfo(gender_topic),
        TopicInfo(age_topic),
    ], 100, None, True)

    i = 0
    for msgs in consumer.getMessages():
        for time, v in message_list_to_frame_structure(msgs).items():
            img = v[args.prefix]["0"]["image"]
            if type(img) == np.ndarray:
                for head_detection in v[args.prefix]["0"]["head_detection"]:
                    object_detection_record = v[args.prefix]["0"][
                        "head_detection"][head_detection]["bounding_box"]
                    age_record = v[args.prefix]["0"]["head_detection"][
                        head_detection]["age"]
                    gender_record = v[args.prefix]["0"]["head_detection"][
                        head_detection]["gender"]
                    age = "" if age_record['age'] == {} else age_record['age']
                    gender = "" if gender_record[
                        'gender'] == {} else gender_record['gender']
                    # draw bounding_box
                    img = draw_nice_bounding_box(
                        img, object_detection_record["bounding_box"],
                        (10, 95, 255))
                    # write age and gender
                    img = draw_nice_text(
                        img,
                        str(gender) + " " + str(age),
                        object_detection_record["bounding_box"], (10, 95, 255))
                # draw ultinous logo
                img = draw_overlay(img, overlay, Position.BOTTOM_RIGHT)

                # produce output topic
                if args.output:
                    producer.produce(output_topic_name,
                                     value=encode_image_to_message(img),
                                     timestamp=time)
                    producer.poll(0)
                    if i % 100 == 0:
                        producer.flush()
                    i += 1

                # display
                if args.display:
                    cv2.imshow(window_name, img)
        k = cv2.waitKey(33)
        if k == 113:  # The 'q' key to stop
            break
        elif k == -1:  # normally -1 returned,so don't print it
            continue
        else:
            print(f"Press 'q' key for EXIT!")
Пример #12
0
def main():
    parser = init_parser()
    args = parser.parse_args()
    config_data = parse_config_data(args=args, parser=parser)
    positive_areas = parse_areas(config_data, "positive_areas")
    negative_areas = parse_areas(config_data, "negative_areas")
    detection_types = parse_detection_types(config_data)

    if not args.display and not args.output:
        parser.error(
            "Missing argument: -d (display output) or -o (write output to kafka) is needed"
        )

    if args.output:
        producer = Producer({'bootstrap.servers': args.broker})

    begin_flag = None
    end_flag = EndFlag.NEVER
    if args.video_file:
        begin_flag = BeginFlag.BEGINNING
        end_flag = EndFlag.END_OF_PARTITION
    heartbeat_interval_ms = 1000

    output_topic_name = f"{args.prefix}.cam.0.filtered_dets.Image.jpg"

    # Write notification if no message is received for this long
    notification_delay_sec = 10

    # handle full screen
    window_name = "DEMO: Filtered detection"
    if args.full_screen:
        cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
        cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN,
                              cv2.WINDOW_FULLSCREEN)

    # read message, draw and display them
    consumer = TimeOrderedGeneratorWithTimeout(
        broker=args.broker,
        groupid="detection",
        topics_infos=[
            TopicInfo(
                f"{args.prefix}.cam.0.original.Image.jpg"),  # image_topic
            TopicInfo(
                f"{args.prefix}.cam.0.filtered_dets.ObjectDetectionRecord.json"
            ),  # filtered_detection_topic
            TopicInfo(f"{args.prefix}.cam.0.dets.ObjectDetectionRecord.json"
                      )  # detection_topic
        ],
        latency_ms=100,
        group_by_time=True,
        begin_flag=begin_flag,
        end_flag=end_flag,
        heartbeat_interval_ms=heartbeat_interval_ms)
    i = 0
    scaling = 1.0
    img_dimensions = (768, 1024)
    last_image_ts = None
    for msgs in consumer.getMessages():
        if not isinstance(msgs, HeartBeat):
            for ts, v in message_list_to_frame_structure(msgs).items():
                frame_info = v[args.prefix]["0"]
                img = frame_info["image"]
                if type(img) != np.ndarray:
                    continue
                last_image_ts = int(time.time())

                # Set the image scale
                img_dimensions = (img.shape[0], img.shape[1])
                shape_orig = frame_info["head_detection"].pop("image", {})
                if shape_orig:
                    scaling = img.shape[1] / shape_orig["frame_info"]["columns"]

                # draw bounding_box
                for head_detection in frame_info["head_detection"]:
                    img = draw_bounding_box(
                        object_detection_record=frame_info["head_detection"]
                        [head_detection]["bounding_box"],
                        detection_types=detection_types,
                        img=img,
                        scaling=scaling,
                        color=COLOR_GREY)

                for head_detection in frame_info["filtered_head_detection"]:
                    img = draw_bounding_box(object_detection_record=frame_info[
                        "filtered_head_detection"][head_detection]
                                            ["filtered_bounding_box"],
                                            detection_types=detection_types,
                                            img=img,
                                            scaling=scaling,
                                            color=COLOR_ORANGE)

                draw_areas(areas=positive_areas, img=img, color=COLOR_GREEN)
                draw_areas(areas=negative_areas, img=img, color=COLOR_RED)

                draw_ultinous_logo(canvas=img, scale=scaling)

                # produce output topic
                if args.output:
                    producer.produce(output_topic_name,
                                     value=encode_image_to_message(img),
                                     timestamp=ts)
                    producer.poll(0)
                    if i % 100 == 0:
                        producer.flush()
                        i = 0
                    i += 1

                # display
                if args.display:
                    cv2.imshow(window_name, img)

        # Write notification until the first message is received
        # (output topic is not updated to ensure kafka timestamp consistency)
        elif args.display and (
                last_image_ts is None
                or last_image_ts + notification_delay_sec < int(time.time())):
            img = np.zeros((*img_dimensions, 3), np.uint8)
            text = "Waiting for input Kafka topics to be populated. \n" \
                "Please make sure that MGR and other necessary services are running."
            img = draw_simple_text(canvas=img, text=text, color=(10, 95, 255))
            cv2.imshow(window_name, img)

        k = cv2.waitKey(33)
        if k == 113:  # The 'q' key to stop
            if args.video_file:
                exit(130)
            else:
                break
        elif k == -1:  # normally -1 returned,so don't print it
            continue
        else:
            print(f"Press 'q' key for EXIT!")
Пример #13
0
def main():
    parser = argparse.ArgumentParser(
        epilog="""Description:
           Basic Reidentification demo using two cameras: 
           Camera0 for object registration and Camera1 for reidentification.
           
           Plays a video from a jpeg topic,
           visualizes head detection with an orange bounding box around a head
           and writes the dwell time and ID (derived from the reid MS ID) above the heads.
           
           Displays ('-d') or stores ('-o') the result of this demo in kafka topics.

           Required topics:
           - <prefix>.cam.0.original.Image.jpg
           - <prefix>.cam.0.dets.ObjectDetectionRecord.json
           - <prefix>.cam.1.original.Image.jpg
           - <prefix>.cam.1.dets.ObjectDetectionRecord.json
           - <prefix>.cam.1.reids.ReidRecord.json
           """,
        formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument("broker",
                        help="The name of the kafka broker.",
                        type=str)
    parser.add_argument("prefix",
                        help="Prefix of topics (base|skeleton).",
                        type=str)
    parser.add_argument('-f', "--full_screen", action='store_true')
    parser.add_argument('-d', "--display", action='store_true')
    parser.add_argument('-o',
                        '--output',
                        help='write output image into kafka topic',
                        action='store_true')
    args = parser.parse_args()

    if not args.display and not args.output:
        parser.error(
            "Missing argument: -d (display output) or -o (write output to kafka) is needed"
        )

    if args.output:
        producer = Producer({'bootstrap.servers': args.broker})

    overlay = cv2.imread('resources/powered_by_white.png',
                         cv2.IMREAD_UNCHANGED)

    image_reg_topic = f"{args.prefix}.cam.{REG_CAMERA_ID}.original.Image.jpg"
    image_reid_topic = f"{args.prefix}.cam.{REID_CAMERA_ID}.original.Image.jpg"
    detection_reg_topic = f"{args.prefix}.cam.{REG_CAMERA_ID}.dets.ObjectDetectionRecord.json"
    detection_reid_topic = f"{args.prefix}.cam.{REID_CAMERA_ID}.dets.ObjectDetectionRecord.json"
    reid_topic = f"{args.prefix}.cam.{REID_TOPIC_ID}.reids.ReidRecord.json"
    output_reg_topic_name = f"{args.prefix}.cam.{REG_CAMERA_ID}.reids.Image.jpg"
    output_reid_topic_name = f"{args.prefix}.cam.{REID_CAMERA_ID}.reids.Image.jpg"

    # handle full screen
    window_name = TITLE
    if args.full_screen:
        cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
        cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN,
                              cv2.WINDOW_FULLSCREEN)

    # read message, draw and display them
    consumer = TimeOrderedGeneratorWithTimeout(
        broker=args.broker,
        groupid="detection",
        topics_infos=[
            TopicInfo(image_reg_topic),
            TopicInfo(image_reid_topic),
            TopicInfo(detection_reg_topic),
            TopicInfo(detection_reid_topic),
            TopicInfo(reid_topic, drop=False),
        ],
        latency_ms=500,
        commit_interval_sec=None,
        group_by_time=True)

    registrations: Dict[str, int] = {}
    i = 0
    inner_id = 0
    for msgs in consumer.getMessages():
        for time, v in message_list_to_frame_structure(msgs).items():
            message = v.get(args.prefix, {})

            # Register the recognized faces
            reid_records = message[REID_TOPIC_ID].get("reid", {})
            for reid_key, reid_record in reid_records.items():
                record_type = reid_record["type"]
                # Get the stored registration key
                registration_key = reid_record["reg_refs"][0]["subject"]["key"]
                if record_type == "REG" and registration_key not in registrations:
                    inner_id += 1
                    registrations[registration_key] = inner_id

            for topic_key, topic_message in message.items():
                img = topic_message.get("image", {})
                if not isinstance(img, np.ndarray):
                    continue

                # Process detections
                head_detections = topic_message.get("head_detection", {})
                for detection_key, detection_record in head_detections.items():
                    object_detection_record = detection_record["bounding_box"]
                    color = COLOR_GREY
                    key_to_display = ""
                    # Reidentification received
                    reid_record = reid_records.get(detection_key)
                    if reid_record and reid_record["type"] == "REID":
                        reid_key = reid_record["reg_refs"][0]["subject"][
                            "key"]  # We only use the first identified face now
                        registered_id = registrations.get(reid_key)
                        if registered_id:
                            color = COLOR_ORANGE
                            dwell_time = time - int(reid_key.split('_')[0])
                            key_to_display = f"id: {registered_id}; dwell time: {dwell_time}ms"

                    # draw text above bounding box
                    img = draw_nice_text(
                        canvas=img,
                        text=key_to_display,
                        bounding_box=object_detection_record["bounding_box"],
                        color=color)

                    # draw bounding_box
                    img = draw_nice_bounding_box(
                        canvas=img,
                        bounding_box=object_detection_record["bounding_box"],
                        color=color)

                # draw ultinous logo
                img = draw_overlay(canvas=img,
                                   overlay=overlay,
                                   position=Position.BOTTOM_RIGHT)

                # produce output topic
                if args.output:
                    out_topic = output_reg_topic_name if topic_key is REG_CAMERA_ID else output_reid_topic_name
                    producer.produce(out_topic,
                                     value=encode_image_to_message(img),
                                     timestamp=time)
                    producer.poll(0)
                    if i % 100 == 0:
                        producer.flush()
                    i += 1

                # display #
                if args.display:
                    cv2.imshow(window_name, img)

        k = cv2.waitKey(33)
        if k == 113:  # The 'q' key to stop
            break
        elif k == -1:  # normally -1 returned,so don't print it
            continue
        else:
            print(f"Press 'q' key for EXIT!")
Пример #14
0
class KafkaWriterConfiguration:
    def __init__(self, configuration):
        self.broker = configuration['broker']
        self.topics = []
        for topic_name, topic_configuration in configuration['topics'].items():
            self.topics.append(
                KafkaConfigurationTopic(topic_name,
                                        topic_configuration['replication'],
                                        topic_configuration['partitions'],
                                        topic_configuration['recreate']))
        self.producer = None
        self.producer_configuration = configuration['producer'][
            'configuration']

    def create_or_recreate_topics(self, admin=None):
        topics_to_recreate = list(
            filter(lambda topic_spec: topic_spec.recreate, self.topics))
        if topics_to_recreate:
            logger.info('Got %s topics to recreate', topics_to_recreate)
            if not admin:
                admin = AdminClient({'bootstrap.servers': self.broker})
            topics_to_delete = list(
                map(lambda topic_spec: topic_spec.name, topics_to_recreate))

            deleted_topics_result = admin.delete_topics(topics_to_delete,
                                                        operation_timeout=15,
                                                        request_timeout=45)
            for deleted_topic, future in deleted_topics_result.items():
                try:
                    future.result()
                except Exception as e:
                    # TODO: transform to WARN
                    print('An error occurred on deleting {}: {}'.format(
                        deleted_topic, e))

            # Apparently there is a concurrent issue with topics create or recreate operations
            # https://github.com/confluentinc/confluent-kafka-python/issues/524
            # That's why I will try to create the topic 5 times with a kind of exponential backoff
            topics_to_create = {
                topic_spec.name: topic_spec.to_new_topic()
                for topic_spec in topics_to_recreate
            }
            creation_errors = []
            for retry in range(0, 5):
                if topics_to_create:
                    futures = admin.create_topics(list(
                        topics_to_create.values()),
                                                  operation_timeout=15,
                                                  request_timeout=45)
                    for topic, f in futures.items():
                        try:
                            f.result()
                            print("Topic {} created".format(topic))
                            del topics_to_create[topic]
                        except Exception as e:
                            logger.warning(
                                "Topic %s was not created - retrying. Got exception %s",
                                topic,
                                e,
                                exc_info=1)
                            if retry == 4:
                                creation_errors.append((topic, e))
                    time.sleep(retry * 5)

            assert not creation_errors, "Some topics were not correctly created {}".format(
                list(
                    map(
                        lambda topic_and_error: "{}: {}".format(
                            topic_and_error[0], topic_and_error[1]),
                        creation_errors)))

    def send_message(self, topic_name, key, message):
        if not self.producer:
            # check https://github.com/edenhill/librdkafka/blob/master/CONFIGURATION.md for more information
            producer_config = {'bootstrap.servers': self.broker}
            producer_config.update(self.producer_configuration)
            self.producer = Producer(producer_config)
        """
        Traceback (most recent call last):
        File "/home/bartosz/workspace/data-generator/examples/kafka/generate_dataset_to_kafka.py", line 51, in <module>
            configuration.send_message(output_topic_name, action)
        File "/home/bartosz/workspace/data-generator/data_generator/sink/kafka_writer.py", line 60, in send_message
            self.producer.produce(topic_name, value=bytes(message, encoding='utf-8'))
        BufferError: Local: Queue full
        The below code is the workaround for the above problem, found here:
        `Confluent Kafka-Python issue 104 <https://github.com/confluentinc/confluent-kafka-python/issues/104>`
        """
        def delivery_callback(error, result):
            if error:
                logger.error("Record was not correctly delivered: %s", error)

        # if the key is missing, it will fail with "TypeError: encoding without a string argument" error
        # replace the missing key by some dummy value
        message_key = key if key else 'empty'
        try:
            self.producer.produce(topic=topic_name,
                                  key=bytes(message_key, encoding='utf-8'),
                                  value=bytes(message, encoding='utf-8'),
                                  on_delivery=delivery_callback)
        except BufferError:
            self.producer.flush()
            self.producer.produce(topic=topic_name,
                                  key=bytes(message_key, encoding='utf-8'),
                                  value=bytes(message, encoding='utf-8'),
                                  on_delivery=delivery_callback)

    def __repr__(self):
        return 'KafkaWriterConfiguration (broker={}) (topics={})'.format(
            self.broker, self.topics)
Пример #15
0
def main():
    parser = argparse.ArgumentParser(
        epilog="""Description:
           Plays video from a jpeg topic, visualizes main points of a human skeleton linked with colorful lines. 
           Displays the result on screen ('-d') or stores in a kafka topic with '-o' parameter.
                      
           Required topics:
           - <prefix>.cam.0.original.Image.jpg
           - <prefix>.cam.0.skeletons.SkeletonRecord.json
           """,
        formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument("broker",
                        help="The name of the kafka broker.",
                        type=str)
    parser.add_argument("prefix",
                        help="Prefix of topics (base|skeleton).",
                        type=str)
    parser.add_argument('-f', "--full_screen", action='store_true')
    parser.add_argument('-d', "--display", action='store_true')
    parser.add_argument('-v', "--video_file", action='store_true')
    parser.add_argument('-o',
                        '--output',
                        help='write output image into kafka topic',
                        action='store_true')
    args = parser.parse_args()

    if not args.display and not args.output:
        parser.error(
            "Missing argument: -d (display output) or -o (write output to kafka) is needed"
        )

    if args.output:
        producer = Producer({'bootstrap.servers': args.broker})

    begin_flag = None
    end_flag = None
    if args.video_file:
        begin_flag = BeginFlag.BEGINNING
        end_flag = EndFlag.END_OF_PARTITION

    overlay = cv2.imread('resources/powered_by_white.png',
                         cv2.IMREAD_UNCHANGED)

    img_topic = f"{args.prefix}.cam.0.original.Image.jpg"
    skeleton_topic = f"{args.prefix}.cam.0.skeletons.SkeletonRecord.json"
    output_topic_name = f"{args.prefix}.cam.0.skeleton.Image.jpg"

    # handle full screen
    window_name = "DEMO: Human skeleton"
    if args.full_screen:
        cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
        cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN,
                              cv2.WINDOW_FULLSCREEN)

    # read message, draw and display them
    consumer = TimeOrderedGeneratorWithTimeout(
        args.broker,
        "skeleton",
        [TopicInfo(img_topic), TopicInfo(skeleton_topic)],
        100,
        None,
        True,
        begin_flag=begin_flag,
        end_flag=end_flag)
    i = 0
    for msgs in consumer.getMessages():
        for time, v in message_list_to_frame_structure(msgs).items():
            img = v[args.prefix]["0"]["image"]
            if type(img) == np.ndarray:
                # draw skeletons
                for skeleton_id, skeleton in v[
                        args.prefix]["0"]["skeleton"].items():
                    img = draw_skeleton_with_background(
                        img, skeleton["points"])

                # draw ultinous logo
                img = draw_overlay(img, overlay, Position.BOTTOM_RIGHT)

                # produce output topic
                if args.output:
                    producer.produce(output_topic_name,
                                     value=encode_image_to_message(img),
                                     timestamp=time)
                    producer.poll(0)
                    if i % 100 == 0:
                        producer.flush()
                    i += 1

                # display
                if args.display:
                    cv2.imshow(window_name, img)
        k = cv2.waitKey(33)
        if k == 113:  # The 'q' key to stop
            if args.video_file:
                exit(130)
            break
        elif k == -1:  # normally -1 returned,so don't print it
            continue
        else:
            print(f"Press 'q' key for EXIT!")
Пример #16
0
def main():
    parser = argparse.ArgumentParser(
        epilog="""Description:
           Plays a video from a jpeg topic, visualizes the head detections and tracks, and pass detections.
           Displays the result on screen ('-d') or stores result in kafka ('-o').
           
           Required topics:
           - <prefix>.cam.0.original.Image.jpg
           - <prefix>.cam.0.dets.ObjectDetectionRecord.json
           - <prefix>.cam.0.tracks.TrackChangeRecord.json
           - <prefix>.cam.0.passdet.PassDetectionRecord.json
           """,
        formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument("broker",
                        help="The name of the kafka broker.",
                        type=str)
    parser.add_argument("prefix",
                        help="Prefix of topics (base|skeleton).",
                        type=str)
    parser.add_argument("config", help="Path to service config.", type=str)
    parser.add_argument('-f', "--full_screen", action='store_true')
    parser.add_argument('-d', "--display", action='store_true')
    parser.add_argument('-o',
                        '--output',
                        help='write output image into kafka topic',
                        action='store_true')
    args = parser.parse_args()

    config_file = Path(args.config)

    if not config_file.is_file():
        parser.error(f"{args.config} does not exist.")

    if not args.display and not args.output:
        parser.error(
            "Missing argument: -d (display output) or -o (write output to kafka) is needed"
        )

    if args.output:
        producer = Producer({'bootstrap.servers': args.broker})

    with config_file.open() as f:
        try:
            passdet_config_json = json.loads(
                javaproperties.load(f)
                ["ultinous.service.kafka.passdet.config"])
        except KeyError:
            parser.error(
                "Missing property: ultinous.service.kafka.passdet.config")
        except JSONDecodeError as e:
            parser.error(f"Error parsing {e}")

    overlay = cv2.imread('resources/powered_by_white.png',
                         cv2.IMREAD_UNCHANGED)

    passlines: Dict[str, PassLine] = {
        pl["id"]: PassLine(next(pass_colors),
                           [(int(p["x"]), int(p["y"])) for p in pl["poly"]])
        for pl in passdet_config_json["passLines"]
    }

    image_topic = f"{args.prefix}.cam.0.original.Image.jpg"
    detection_topic = f"{args.prefix}.cam.0.dets.ObjectDetectionRecord.json"
    track_topic = f"{args.prefix}.cam.0.tracks.TrackChangeRecord.json"
    passdet_topic = f"{args.prefix}.cam.0.passdet.PassDetectionRecord.json"
    output_topic_name = f"{args.prefix}.cam.0.passdet.Image.jpg"

    # handle full screen
    window_name = "DEMO: Pass detection"
    if args.full_screen:
        cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
        cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN,
                              cv2.WINDOW_FULLSCREEN)

    # read message, draw and display them
    consumer = TimeOrderedGeneratorWithTimeout(args.broker, "detection", [
        TopicInfo(image_topic),
        TopicInfo(track_topic, drop=False),
        TopicInfo(passdet_topic, drop=False),
        TopicInfo(detection_topic)
    ], 100, None, True)
    i = 0

    tracks: DefaultDict[Any, ColoredPolyLine] = defaultdict(
        lambda: ColoredPolyLine(next(track_colors)))

    for msgs in consumer.getMessages():
        for time, v in message_list_to_frame_structure(msgs).items():
            for track_key, track_val in v[args.prefix]["0"]["track"].items():
                if track_val["end_of_track"]:
                    if track_key in tracks:
                        del tracks[track_key]
                    continue
                point = track_val["point"]["x"], track_val["point"]["y"]
                tracks[track_key].add_point(point)
            for pass_det in v[args.prefix]["0"]["passdet"].values():
                if pass_det["type"] == "HEARTBEAT":
                    continue
                elif pass_det["type"] == "END_OF_TRACK":
                    continue
                elif pass_det["type"] == "PASS_CANDIDATE":
                    pass_id = pass_det["pass_candidate"]["pass"][
                        "pass_line_id"]
                    cross_dir = pass_det["pass_candidate"]["pass"]["cross_dir"]
                    if pass_id in passlines:
                        passlines[pass_id].add_event(cross_dir)
                elif pass_det["type"] == "PASS_REALIZED":
                    continue

            img = v[args.prefix]["0"]["image"]
            if type(img) == np.ndarray:
                # draw bounding_box
                for head_detection in v[args.prefix]["0"]["head_detection"]:
                    object_detection_record = v[args.prefix]["0"][
                        "head_detection"][head_detection]["bounding_box"]
                    if object_detection_record["type"] == "PERSON_HEAD":
                        img = draw_nice_bounding_box(
                            img, object_detection_record["bounding_box"],
                            (10, 95, 255))

                for t in tracks.values():
                    t.draw(img)

                for idx, l in enumerate(passlines.values()):
                    l.draw(img)
                    cv2.putText(img,
                                "".join(l.events), (40, (idx + 1) * 50),
                                cv2.FONT_HERSHEY_COMPLEX,
                                2,
                                l.color,
                                5,
                                bottomLeftOrigin=True)
                img = draw_overlay(img, overlay, Position.BOTTOM_RIGHT)

                # produce output topic
                if args.output:
                    producer.produce(output_topic_name,
                                     value=encode_image_to_message(img),
                                     timestamp=time)
                    producer.poll(0)
                    if i % 100 == 0:
                        producer.flush()
                        i = 0
                    i += 1

                # display
                if args.display:
                    cv2.imshow(window_name, img)
        k = cv2.waitKey(33)
        if k == 113:  # The 'q' key to stop
            break
        elif k == -1:  # normally -1 returned,so don't print it
            continue
        else:
            print(f"Press 'q' key for EXIT!")
Пример #17
0
def main():
    parser = argparse.ArgumentParser(
        epilog="""Description:
           Plays a video from a jpeg topic and visualizes the head detection with an orange bounding box around a head.
           Displays ('-d') or stores ('-o') the result of this demo in the kafka topic.
           
           Required topics:
           - <prefix>.cam.0.original.Image.jpg
           - <prefix>.cam.0.dets.ObjectDetectionRecord.json
           """,
        formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument("broker",
                        help="The name of the kafka broker.",
                        type=str)
    parser.add_argument("prefix",
                        help="Prefix of topics (base|skeleton).",
                        type=str)
    parser.add_argument('-f', "--full_screen", action='store_true')
    parser.add_argument('-d', "--display", action='store_true')
    parser.add_argument('-v', "--video_file", action='store_true')
    parser.add_argument('-o',
                        '--output',
                        help='write output image into kafka topic',
                        action='store_true')
    args = parser.parse_args()

    if not args.display and not args.output:
        parser.error(
            "Missing argument: -d (display output) or -o (write output to kafka) is needed"
        )

    if args.output:
        producer = Producer({'bootstrap.servers': args.broker})

    begin_flag = None
    end_flag = None
    if args.video_file:
        begin_flag = BeginFlag.BEGINNING
        end_flag = EndFlag.END_OF_PARTITION

    overlay = cv2.imread('resources/powered_by_white.png',
                         cv2.IMREAD_UNCHANGED)

    image_topic = f"{args.prefix}.cam.0.original.Image.jpg"
    detection_topic = f"{args.prefix}.cam.0.dets.ObjectDetectionRecord.json"
    frameinfo_topic = f"{args.prefix}.cam.0.frameinfo.FrameInfoRecord.json"
    output_topic_name = f"{args.prefix}.cam.0.head_detection.Image.jpg"

    # handle full screen
    window_name = "DEMO: Head detection"
    if args.full_screen:
        cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
        cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN,
                              cv2.WINDOW_FULLSCREEN)

    # read message, draw and display them
    consumer = TimeOrderedGeneratorWithTimeout(args.broker,
                                               "detection", [
                                                   TopicInfo(image_topic),
                                                   TopicInfo(detection_topic),
                                                   TopicInfo(frameinfo_topic)
                                               ],
                                               100,
                                               None,
                                               True,
                                               begin_flag=begin_flag,
                                               end_flag=end_flag)
    i = 0
    scaling = 1.0
    for msgs in consumer.getMessages():
        for time, v in message_list_to_frame_structure(msgs).items():
            img = v[args.prefix]["0"]["image"]
            if type(img) == np.ndarray:

                # Set the image scale
                shape_orig = v[args.prefix]["0"]["head_detection"].pop(
                    "image", {})
                if shape_orig:
                    scaling = img.shape[1] / shape_orig["frame_info"]["columns"]

                # draw bounding_box
                for head_detection in v[args.prefix]["0"]["head_detection"]:
                    object_detection_record = v[args.prefix]["0"][
                        "head_detection"][head_detection]["bounding_box"]
                    if object_detection_record["type"] == "PERSON_HEAD":
                        img = draw_nice_bounding_box(
                            canvas=img,
                            bounding_box=object_detection_record[
                                "bounding_box"],
                            color=(10, 95, 255),
                            scaling=scaling)

                # draw ultinous logo
                img = draw_overlay(canvas=img,
                                   overlay=overlay,
                                   position=Position.BOTTOM_RIGHT,
                                   scale=scaling)

                # produce output topic
                if args.output:
                    producer.produce(output_topic_name,
                                     value=encode_image_to_message(img),
                                     timestamp=time)
                    producer.poll(0)
                    if i % 100 == 0:
                        producer.flush()
                        i = 0
                    i += 1

                # display
                if args.display:
                    cv2.imshow(window_name, img)
        k = cv2.waitKey(33)
        if k == 113:  # The 'q' key to stop
            if args.video_file:
                exit(130)
            else:
                break
        elif k == -1:  # normally -1 returned,so don't print it
            continue
        else:
            print(f"Press 'q' key for EXIT!")
Пример #18
0
class KafmanProducer(metaclass=Singleton):
    """TODO"""

    def __init__(self):
        super().__init__()
        self.topic = None
        self.producer = None
        self.started = False
        self.bus = EventBus.get(PRODUCER_BUS)
        self.console_bus = EventBus.get(HConsole.CONSOLE_BUS)

    def flush(self, timeout: int = 0) -> None:
        """TODO"""
        if self.producer:
            self.producer.flush(timeout=timeout)

    def purge(self) -> None:
        """TODO"""
        if self.producer:
            self.producer.purge()

    def start(self, settings: dict) -> None:
        """TODO"""
        if self.producer is None:
            self.producer = Producer(settings)
            self.started = True

    def stop(self) -> None:
        """TODO"""
        if self.producer is not None:
            self.purge()
            self.flush()
            del self.producer
            self.producer = None
            self.started = False

    def produce(self, topics: List[str], messages: List[str]) -> None:
        """TODO"""
        if self.started:
            tr = threading.Thread(target=self._produce, args=(topics,messages,))
            tr.setDaemon(True)
            tr.start()

    def _produce(self, topics: List[str], messages: List[str]):
        """TODO"""
        try:
            for topic in topics:
                for msg in messages:
                    if msg:
                        self.producer.produce(topic, msg, callback=self._message_produced)
                self.producer.poll(POLLING_INTERVAL)
        except KeyboardInterrupt:
            print("Keyboard interrupted")
        finally:
            self.producer.flush(30)

    def _message_produced(self, error: KafkaError, message: Message) -> None:
        """TODO"""
        topic = message.topic()
        msg = message.value().decode(Charset.UTF_8.value)
        if error is not None:
            print(f"Failed to deliver message: {msg}: {error.str()}")
        else:
            self.bus.emit(MSG_PROD_EVT, message=msg, topic=topic)
Пример #19
0
def main(args):
    serial = args.serial
    num_messages = args.num_messages
    brokers = args.brokers
    group_id = args.group_id
    input_topic = args.input_topic
    input_partition = args.input_partition
    output_topic = args.output_topic

    if serial:
        print("Running in SERIAL mode")
        print(
            "The input producer will wait for the reply of the transactor before producing the next message."
        )
    else:
        print("Running in PARALLEL mode")
        print(
            "The input producer will produce all messages in parallel (at once) after the first message."
        )

    tr_args = [
        sys.executable,
        os.path.join(HERE, "eos-transactions.py"),
        "-b",
        brokers,
        "-g",
        group_id + "-tr",
        "-t",
        input_topic,
        "-p",
        str(input_partition),
        "-o",
        output_topic,
    ]

    output_consumer = Consumer({
        "bootstrap.servers": brokers,
        "group.id": group_id + "-pr",
        "auto.offset.reset": "earliest",
        "enable.auto.commit": True,
        "enable.partition.eof": False,
    })
    output_consumer.subscribe([output_topic])

    input_producer = Producer({
        'bootstrap.servers': brokers,
    })

    try:
        with tempfile.NamedTemporaryFile(mode='w+') as f:
            tr_proc = subprocess.Popen(tr_args,
                                       stderr=subprocess.STDOUT,
                                       stdout=f,
                                       cwd=HERE,
                                       close_fds=True)
            try:
                time.sleep(1)
                assert tr_proc.poll() is None
                tx = 0
                for i in range(num_messages):
                    input_producer.produce(input_topic,
                                           key=b"xy",
                                           value=str(tx).encode("ascii"))
                    tx += 1
                    assert input_producer.flush(10) == 0
                    while serial or tx <= 1:
                        msg = output_consumer.poll(1.0)
                        if msg is None:
                            continue
                        assert msg.error() is None
                        if tx == 1:
                            t_start = time.time()
                        break
                if not serial:
                    for _ in range(num_messages - 1):
                        msg = output_consumer.poll(1.0)
                        if msg is None:
                            continue
                        assert msg.error() is None

                print("Processing took {}".format(time.time() - t_start))
            finally:
                if tr_proc.poll() is None:
                    tr_proc.terminate()
                    tr_proc.wait()
            f.seek(0)
            eos_out = f.read()
    finally:
        output_consumer.close()  # commit offsets

    i = 0
    c = False
    send_offset_logs = defaultdict(list)
    send_offset_times = []
    for line in eos_out.split("\n"):
        if line.startswith(":DEMO:START "):
            c = True
        if c:
            send_offset_logs[i].append(line)
        if line.startswith(":DEMO:END "):
            send_offset_times.append(float(line.rpartition(" ")[-1]))
            c = False
            i += 1

    print("\nSend offset times:", send_offset_times)
    print("Send offset times average:",
          sum(send_offset_times) / len(send_offset_times))

    print("\nRelevant log snippet from the middle:")
    print("\n".join(send_offset_logs[int(i / 2)]))

    print("\nFull output of the transactor:")
    print(eos_out)
Пример #20
0
def main():
    parser = argparse.ArgumentParser(
        epilog="""Description:
           Plays a video from a jpeg topic,
           visualizes head detection with an orage bounding box around a head 
           and writes the IDs given by reid MS above the heads.
           Displays ('-d') or stores ('-o') the result of this demo in the kafka topic.
           Required topics:
           - <prefix>.cam.0.original.Image.jpg
           - <prefix>.cam.0.dets.ObjectDetectionRecord.json
           - <prefix>.cam.99.reids.ReidRecord.json
           """,
        formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument("broker",
                        help="The name of the kafka broker.",
                        type=str)
    parser.add_argument("prefix",
                        help="Prefix of topics (base|skeleton).",
                        type=str)
    parser.add_argument('-f', "--full_screen", action='store_true')
    parser.add_argument('-d', "--display", action='store_true')
    parser.add_argument('-v', "--video_file", action='store_true')
    parser.add_argument('-o',
                        '--output',
                        help='write output image into kafka topic',
                        action='store_true')
    args = parser.parse_args()

    if not args.display and not args.output:
        parser.error(
            "Missing argument: -d (display output) or -o (write output to kafka) is needed"
        )

    if args.output:
        producer = Producer({'bootstrap.servers': args.broker})

    begin_flag = None
    end_flag = None
    if args.video_file:
        begin_flag = BeginFlag.BEGINNING
        end_flag = EndFlag.END_OF_PARTITION

    overlay = cv2.imread('resources/powered_by_white.png',
                         cv2.IMREAD_UNCHANGED)

    image_topic = f"{args.prefix}.cam.0.original.Image.jpg"
    detection_topic = f"{args.prefix}.cam.0.dets.ObjectDetectionRecord.json"
    reid_topic = f"{args.prefix}.cam.{REID_TOPIC_ID}.reids.ReidRecord.json"
    output_topic_name = f"{args.prefix}.cam.0.reidentification.Image.jpg"
    frameinfo_topic = f"{args.prefix}.cam.0.frameinfo.FrameInfoRecord.json"

    # handle full screen
    window_name = TITLE
    if args.full_screen:
        cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
        cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN,
                              cv2.WINDOW_FULLSCREEN)

    # read message, draw and display them
    consumer = TimeOrderedGeneratorWithTimeout(
        args.broker,
        "detection",
        [
            TopicInfo(image_topic),
            TopicInfo(detection_topic),
            TopicInfo(reid_topic),
            TopicInfo(frameinfo_topic)
        ],
        500,
        None,
        True,
        begin_flag=begin_flag,
        end_flag=end_flag,
    )

    i = 0
    stored_ids = {}
    scaling = 1.0
    for msgs in consumer.getMessages():
        for time, v in message_list_to_frame_structure(msgs).items():
            message = v.get(args.prefix, {})
            reid_records = message[REID_TOPIC_ID].get("reid", {})
            img = message["0"].get("image", {})
            if type(img) == np.ndarray:
                head_detections = message["0"].get("head_detection", {})
                # Set the image scale
                shape_orig = head_detections.pop("image", {})
                if shape_orig:
                    scaling = img.shape[1] / shape_orig["frame_info"]["columns"]

                # Processing detections
                for detection_key, detection_record in head_detections.items():
                    object_detection_record = detection_record["bounding_box"]

                    color = COLOR_GREY
                    reid_records_for_det = reid_records.get(detection_key, ())
                    for reid_record in filter(lambda r: "reid_event" in r,
                                              reid_records_for_det):
                        color = COLOR_ORANGE
                        reid_key = reid_record["reid_event"]["match_list"][0][
                            "id"]["first_detection_key"]
                        key_to_display = stored_ids.get(reid_key, None)
                        if key_to_display is None:
                            key_to_display = len(stored_ids) + 1
                            stored_ids[reid_key] = key_to_display

                        # user id
                        img = draw_nice_text(
                            canvas=img,
                            text=str(key_to_display),
                            bounding_box=object_detection_record[
                                "bounding_box"],
                            color=color,
                            scale=scaling)

                    # draw bounding_box
                    img = draw_nice_bounding_box(
                        canvas=img,
                        bounding_box=object_detection_record["bounding_box"],
                        color=color,
                        scaling=scaling)

                # draw ultinous logo
                img = draw_overlay(canvas=img,
                                   overlay=overlay,
                                   position=Position.BOTTOM_RIGHT,
                                   scale=scaling)

                # produce output topic
                if args.output:
                    producer.produce(output_topic_name,
                                     value=encode_image_to_message(img),
                                     timestamp=time)
                    producer.poll(0)
                    if i % 100 == 0:
                        producer.flush()
                    i += 1

                # display
                if args.display:
                    cv2.imshow(window_name, img)
        k = cv2.waitKey(33)
        if k == 113:  # The 'q' key to stop
            if args.video_file:
                exit(130)
            break
        elif k == -1:  # normally -1 returned,so don't print it
            continue
        else:
            print(f"Press 'q' key for EXIT!")
Пример #21
0
def main():
    parser = argparse.ArgumentParser(
        epilog="""Description:
           Plays a video from a jpeg topic, visualizes the head detections and tracks, and pass detections.
           Displays the result on screen ('-d') or stores result in kafka ('-o').
           
           Required topics:
           - <prefix>.cam.0.original.Image.jpg
           - <prefix>.cam.0.dets.ObjectDetectionRecord.json
           - <prefix>.cam.0.tracks.TrackChangeRecord.json
           - <prefix>.cam.0.passdet.PassDetectionRecord.json
           """,
        formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument("broker",
                        help="The name of the kafka broker.",
                        type=str)
    parser.add_argument("prefix",
                        help="Prefix of topics (base|skeleton).",
                        type=str)
    parser.add_argument("config", help="Path to service config.", type=str)
    parser.add_argument('-f', "--full_screen", action='store_true')
    parser.add_argument('-d', "--display", action='store_true')
    parser.add_argument('-v', "--video_file", action='store_true')
    parser.add_argument('-o',
                        '--output',
                        help='write output image into kafka topic',
                        action='store_true')
    args = parser.parse_args()

    passdet_config_json = parse_config_data(args=args, parser=parser)

    if not args.display and not args.output:
        parser.error(
            "Missing argument: -d (display output) or -o (write output to kafka) is needed"
        )

    if args.output:
        producer = Producer({'bootstrap.servers': args.broker})

    begin_flag = None
    end_flag = EndFlag.NEVER
    if args.video_file:
        begin_flag = BeginFlag.BEGINNING
        end_flag = EndFlag.END_OF_PARTITION
    heartbeat_interval_ms = 1000

    overlay = cv2.imread('resources/powered_by_white.png',
                         cv2.IMREAD_UNCHANGED)

    passlines: Dict[str, PassLine] = {
        pl["id"]: PassLine(next(pass_colors),
                           [(int(p["x"]), int(p["y"])) for p in pl["poly"]])
        for pl in passdet_config_json["passLines"]
    }

    image_topic = f"{args.prefix}.cam.0.original.Image.jpg"
    detection_topic = f"{args.prefix}.cam.0.dets.ObjectDetectionRecord.json"
    track_topic = f"{args.prefix}.cam.0.tracks.TrackChangeRecord.json"
    frameinfo_topic = f"{args.prefix}.cam.0.frameinfo.FrameInfoRecord.json"
    passdet_topic = f"{args.prefix}.cam.0.passdet.PassDetectionRecord.json"
    output_topic_name = f"{args.prefix}.cam.0.passdet.Image.jpg"

    # Write notification if no message is received for this long
    notification_delay_sec = 10

    # handle full screen
    window_name = "DEMO: Pass detection"
    if args.full_screen:
        cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
        cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN,
                              cv2.WINDOW_FULLSCREEN)

    # read message, draw and display them
    consumer = TimeOrderedGeneratorWithTimeout(
        args.broker,
        "detection", [
            TopicInfo(image_topic),
            TopicInfo(track_topic, drop=False),
            TopicInfo(passdet_topic, drop=False),
            TopicInfo(detection_topic),
            TopicInfo(frameinfo_topic)
        ],
        100,
        None,
        True,
        begin_flag=begin_flag,
        end_flag=end_flag,
        heartbeat_interval_ms=heartbeat_interval_ms)
    i = 0
    scaling = 1.0
    img_dimensions = (768, 1024)
    last_image_ts = None
    tracks: DefaultDict[Any, ColoredPolyLine] = defaultdict(
        lambda: ColoredPolyLine(next(track_colors)))

    for msgs in consumer.getMessages():
        if not isinstance(msgs, HeartBeat):
            for ts, v in message_list_to_frame_structure(msgs).items():
                for track_key, track_val in v[
                        args.prefix]["0"]["track"].items():
                    if track_val["end_of_track"]:
                        if track_key in tracks:
                            del tracks[track_key]
                        continue
                    point = track_val["point"]["x"], track_val["point"]["y"]
                    tracks[track_key].add_point(point)

                for pass_det in v[args.prefix]["0"]["passdet"].values():
                    if pass_det["type"] == "HEARTBEAT":
                        continue
                    elif pass_det["type"] == "END_OF_TRACK":
                        continue
                    elif pass_det["type"] == "PASS_CANDIDATE":
                        pass_id = pass_det["pass_candidate"]["pass"][
                            "pass_line_id"]
                        cross_dir = pass_det["pass_candidate"]["pass"][
                            "cross_dir"]
                        if pass_id in passlines:
                            passlines[pass_id].add_event(cross_dir)
                    elif pass_det["type"] == "PASS_REALIZED":
                        continue

                img = v[args.prefix]["0"]["image"]
                if type(img) != np.ndarray:
                    continue
                last_image_ts = int(time.time())

                # Set the image scale
                img_dimensions = (img.shape[0], img.shape[1])
                shape_orig = v[args.prefix]["0"]["head_detection"].pop(
                    "image", {})
                if shape_orig:
                    scaling = img.shape[1] / shape_orig["frame_info"]["columns"]

                # draw bounding_box
                for head_detection in v[args.prefix]["0"]["head_detection"]:
                    object_detection_record = v[args.prefix]["0"][
                        "head_detection"][head_detection]["bounding_box"]
                    if object_detection_record["type"] == "PERSON_HEAD":
                        img = draw_nice_bounding_box(
                            canvas=img,
                            bounding_box=object_detection_record[
                                "bounding_box"],
                            color=(10, 95, 255),
                            scaling=scaling)
                for t in tracks.values():
                    t.draw(img, scaling)
                for idx, l in enumerate(passlines.values()):
                    l.draw(img, scaling)
                    cv2.putText(img,
                                "".join(l.events), (40, (idx + 1) * 50),
                                cv2.FONT_HERSHEY_COMPLEX,
                                2,
                                l.color,
                                5,
                                bottomLeftOrigin=True)
                img = draw_overlay(canvas=img,
                                   overlay=overlay,
                                   position=Position.BOTTOM_RIGHT,
                                   scale=scaling)

                # produce output topic
                if args.output:
                    producer.produce(output_topic_name,
                                     value=encode_image_to_message(img),
                                     timestamp=ts)
                    producer.poll(0)
                    if i % 100 == 0:
                        producer.flush()
                        i = 0
                    i += 1

                # display
                if args.display:
                    cv2.imshow(window_name, img)

        # Write notification until the first message is received
        # (output topic is not updated to ensure kafka timestamp consistency)
        elif args.display and (
                last_image_ts is None
                or last_image_ts + notification_delay_sec < int(time.time())):
            img = np.zeros((*img_dimensions, 3), np.uint8)
            text = "Waiting for input Kafka topics to be populated. \n" \
                "Please make sure that MGR and other necessary services are running."
            img = draw_simple_text(canvas=img, text=text, color=(10, 95, 255))
            cv2.imshow(window_name, img)

        k = cv2.waitKey(33)
        if k == 113:  # The 'q' key to stop
            if args.video_file:
                exit(130)
            break
        elif k == -1:  # normally -1 returned,so don't print it
            continue
        else:
            print(f"Press 'q' key for EXIT!")
Пример #22
0
def main():
    parser = argparse.ArgumentParser(
        epilog="""Description:
           Plays a video from a jpeg topic, visualizes the head detections and tracks.
           Displays the result on screen ('-d') or stores result in kafka ('-o').
           
           Required topics:
           - <prefix>.cam.0.original.Image.jpg
           - <prefix>.cam.0.dets.ObjectDetectionRecord.json
           - <prefix>.cam.0.tracks.TrackChangeRecord.json
           """,
        formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument("broker",
                        help="The name of the kafka broker.",
                        type=str)
    parser.add_argument("prefix",
                        help="Prefix of topics (base|skeleton).",
                        type=str)
    parser.add_argument('-f', "--full_screen", action='store_true')
    parser.add_argument('-d', "--display", action='store_true')
    parser.add_argument('-o',
                        '--output',
                        help='write output image into kafka topic',
                        action='store_true')
    args = parser.parse_args()

    if not args.display and not args.output:
        parser.error(
            "Missing argument: -d (display output) or -o (write output to kafka) is needed"
        )

    if args.output:
        producer = Producer({'bootstrap.servers': args.broker})

    overlay = cv2.imread('resources/powered_by_white.png',
                         cv2.IMREAD_UNCHANGED)

    image_topic = f"{args.prefix}.cam.0.original.Image.jpg"
    detection_topic = f"{args.prefix}.cam.0.dets.ObjectDetectionRecord.json"
    track_topic = f"{args.prefix}.cam.0.tracks.TrackChangeRecord.json"
    output_topic_name = f"{args.prefix}.cam.0.tracks.Image.jpg"

    # handle full screen
    window_name = "DEMO: Head detection"
    if args.full_screen:
        cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
        cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN,
                              cv2.WINDOW_FULLSCREEN)

    # read message, draw and display them
    consumer = TimeOrderedGeneratorWithTimeout(args.broker, "detection", [
        TopicInfo(image_topic),
        TopicInfo(track_topic, drop=False),
        TopicInfo(detection_topic)
    ], 100, None, True)
    i = 0

    tracks: DefaultDict[Any, Track] = defaultdict(lambda: Track(next(colors)))

    for msgs in consumer.getMessages():
        for time, v in message_list_to_frame_structure(msgs).items():
            for track_key, track_val in v[args.prefix]["0"]["track"].items():
                if track_val["end_of_track"]:
                    if track_key in tracks:
                        del tracks[track_key]
                    continue
                point = track_val["point"]["x"], track_val["point"]["y"]
                tracks[track_key].add_point(point)
            img = v[args.prefix]["0"]["image"]
            if type(img) == np.ndarray:
                # draw bounding_box
                for head_detection in v[args.prefix]["0"]["head_detection"]:
                    object_detection_record = v[args.prefix]["0"][
                        "head_detection"][head_detection]["bounding_box"]
                    if object_detection_record["type"] == "PERSON_HEAD":
                        img = draw_nice_bounding_box(
                            img, object_detection_record["bounding_box"],
                            (10, 95, 255))

                for t_key, t in tracks.items():
                    cv2.polylines(img=img,
                                  pts=[np.array(t.points, np.int32)],
                                  isClosed=False,
                                  color=t.color,
                                  thickness=3)

                # draw ultinous logo
                img = draw_overlay(img, overlay, Position.BOTTOM_RIGHT)

                # produce output topic
                if args.output:
                    producer.produce(output_topic_name,
                                     value=encode_image_to_message(img),
                                     timestamp=time)
                    producer.poll(0)
                    if i % 100 == 0:
                        producer.flush()
                        i = 0
                    i += 1

                # display
                if args.display:
                    cv2.imshow(window_name, img)
        k = cv2.waitKey(33)
        if k == 113:  # The 'q' key to stop
            break
        elif k == -1:  # normally -1 returned,so don't print it
            continue
        else:
            print(f"Press 'q' key for EXIT!")
Пример #23
0
    class Kafka(object):
        def __init__(self, target_key) -> None:
            super().__init__()
            self.address = _address_for_key(target_key)
            kafka_config = {
                'bootstrap.servers': self.address,
                'group.id': "up9-test-group",
                'enable.auto.commit':
                'false'  # important for passive observing
            }
            if "ssl://" in self.address.lower():
                kafka_config['security.protocol'] = 'SSL'

            self.consumer = Consumer(kafka_config)
            self.producer = Producer(kafka_config)
            self.watching_topics = []

            self.consumer.list_topics(timeout=5)  # to check for connectivity

        def watch_topics(self, topics: list):
            def my_on_assign(consumer, partitions):
                logging.debug("On assign: %r", partitions)
                consumer.assign(partitions)
                for partition in partitions:
                    low, high = consumer.get_watermark_offsets(partition)
                    partition.offset = high
                    logging.debug("Setting offset: %r", partition)
                    consumer.seek(partition)

            self.watching_topics.extend(topics)
            self.consumer.subscribe(topics, on_assign=my_on_assign)
            self.consumer.poll(0.01)  # to trigger partition assignments

        def get_watched_messages(self, interval=0.0, predicate=lambda x: True):
            logging.debug(
                "Checking messages that appeared on kafka topics: %r",
                self.watching_topics)
            res = []

            start = time.time()
            while True:
                msg = self.consumer.poll(interval)
                if msg is None or time.time() - start > interval:
                    break  # done reading

                if msg.error():
                    raise KafkaException("kafka consumer error: {}".format(
                        msg.error()))

                logging.debug(
                    "Potential message: %r",
                    (msg.partition(), msg.key(), msg.headers(), msg.value()))
                if predicate(msg):
                    res.append(msg)

            # TODO: consumer.close()
            return res

        def assert_seen_message(self, resp, delay=0, predicate=lambda x: True):
            @recorder.assertion_decorator
            def assert_seen_kafka_message(resp, topics, delay):
                messages = self.get_watched_messages(delay, predicate)
                messages = [(m.topic(), m.key(), m.value(), m.headers())
                            for m in messages]
                if not messages:
                    raise AssertionError("No messages on Kafka topic %r" %
                                         topics)
                else:
                    logging.info("Validated the messages have appeared: %s",
                                 messages)

                return messages

            return assert_seen_kafka_message(resp, self.watching_topics, delay)

        def put(self, topic, data=None, json=None, headers=None):
            # TODO: parse key out of URL
            if topic.startswith('/'):
                topic = topic[1:]

            if data is None and json is not None:
                data = json_lib.dumps(json)

            with apiritif.transaction('kafka://[' + self.address + ']/' +
                                      topic):
                logging.info("Sending message to Kafka topic %r: %r", topic,
                             data)
                self.producer.produce(
                    topic, data, headers=[] if headers is None else headers)
                self.producer.poll(0)
                self.producer.flush()

                wrapped_req = self._make_request(
                    'PUT',
                    'kafka://' + self.address.split(',')[0] + '/' + topic,
                    data)
                wrapped_response = self._make_response(wrapped_req)
                recorder.record_http_request('PUT', self.address, wrapped_req,
                                             wrapped_response,
                                             _context.session)

            return wrapped_response

        def _make_request(self, method, url, request):
            req = requests.Request(method, url=url, data=request)
            prepared = req.prepare()
            _context.grpc_mapping[id(request)] = prepared
            return prepared

        def _make_response(self, wrapped_req):
            resp = requests.Response()
            resp.status_code = 202
            resp.request = wrapped_req
            resp._request = wrapped_req
            resp.msg = 'Accepted'
            resp.raw = io.BytesIO()
            return resp
class ModelInference(object):
    def __init__(self,
                 my_id=1,
                 bootstrap_servers='',
                 list_of_partitions=[],
                 request_topic='',
                 inference_topic='',
                 group_id='my_grp'):
        """ Constructor
        :type interval: int
        :param interval: Check interval, in seconds
        """
        self.model = compose.Pipeline(
            preprocessing.MinMaxScaler(), anomaly.HalfSpaceTrees(
                seed=42))  # tree.HoeffdingTreeClassifier(max_depth=10)
        self.metric = metrics.ROCAUC()  # metrics.Accuracy() #
        self.my_id = my_id
        self.t = request_topic
        self.result_t = inference_topic
        self.my_grp_id = group_id
        self.result_t_p = 8
        self.bootstrap_servers = bootstrap_servers
        #         self.list_of_partitions = list_of_partitions

        self.tls = []
        x = 0
        for i in list_of_partitions:
            self.tls.insert(x, TopicPartition(self.t, i))
            x = x + 1
        #self.tls=list_of_partitions
        print(self.tls)

        conf = {
            'bootstrap.servers': bootstrap_servers,
            'sasl.mechanism': 'PLAIN',
            'security.protocol': 'SASL_SSL',
            'ssl.ca.location': '/tmp/cacert.pem',
            'sasl.username': '******',
            'sasl.password':
            '******',
            #                 'sasl.username': '******',
            #                 'sasl.password': '******',
            # 'key.serializer': StringSerializer('utf_8'),
            # 'value.serializer': StringSerializer('utf_8'),
            'client.id': 'test-sw-1'
        }

        self.producer = Producer(conf)
        conf = {
            'bootstrap.servers': bootstrap_servers,
            'sasl.mechanism': 'PLAIN',
            'security.protocol': 'SASL_SSL',
            'sasl.username': '******',
            'sasl.password':
            '******',
            'ssl.ca.location': '/tmp/cacert.pem',
            'group.id': group_id,
            'auto.offset.reset': 'latest'
        }
        self.consumer = consumer = Consumer(conf)
        self.consumer.assign(self.tls)

    def __del__(self):
        print('closing')
        #self.consumer.close()
        self.producer.flush()
        self.producer.close()

    def run(self):
        ### Set up model, metric, and starting timestamp for this model instance ###
        model = self.model
        metric = self.metric
        print('MODEL and METRIC before any messages consumed:', model, metric)
        start_consume_ts = time.time()
        print('Start Consume Time ' + str(start_consume_ts))
        ######
        try:
            self.consumer.assign(self.tls)
            i = 0
            while (True):
                msg = self.consumer.poll(timeout=1.0)
                if msg is None: continue

                if msg.error():
                    if msg.error().code() == KafkaError._PARTITION_EOF:
                        # End of partition event
                        sys.stderr.write(
                            '%% %s [%d] reached end at offset %d\n' %
                            (msg.topic(), msg.partition(), msg.offset()))
                    elif msg.error():
                        raise KafkaException(msg.error())
                else:
                    message = loads(msg.value().decode("utf-8"))
                    ingest_ts = message[
                        'ingestTs']  # Ingestion time from Kafka
                    message.pop('ingestTs')
                    message_id = message['message_id']  # Message ID from Kafka
                    message.pop('message_id')
                    truth = float(
                        message['Class'])  # True label supplied by Kafka
                    message.pop(
                        'Class'
                    )  # Remove label remove passing the data for prediction (could combine with above)
                    message.pop('ignore')
                    x = message
                    for k, v in x.items():
                        x[k] = float(v)
                    y_hat = model.score_one(
                        x)  #model.predict_one(x) # make a prediction
                    if (i % 1000 == 0):
                        print('x: ', x)
                        for k, v in x.items():
                            print(type(x[k]))
                        print('model: ', model)
                        print('y_hat: ', y_hat)
                    inference_ts = time.time()
                    metric = metric.update(truth, y_hat)  # update the metric
                    model = model.learn_one(
                        x)  # model.learn_one(x,y) # make the model learn
                    learn_ts = time.time()
                    out = {}
                    out['ingest_ts'] = ingest_ts
                    out['learn_ts'] = learn_ts
                    out['message_id'] = message_id
                    out['truth'] = truth
                    out['y_hat'] = y_hat
                    out['inference_ts'] = inference_ts
                    out['dur_evt_inf'] = inference_ts - ingest_ts
                    out['dur_start_inf'] = inference_ts - start_consume_ts
                    out['dur_inf_learn'] = learn_ts - inference_ts
                    out['model_metric'] = metric.get()
                    out['ignore'] = False
                    i = i + 1
                    # sprint(self.result_t)
                    k = str(i)
                    v = json.dumps(out).encode('utf-8')
                    self.producer.produce(self.result_t, value=v, key=k)
                    # self.producer.flush()

                    if (i % 1000 == 0):
                        print('sending to ' + self.result_t + ' ' +
                              str(self.result_t_p) + ' ' + str(out))
                        self.producer.flush()
                    if (i % 100000 == 0):
                        try:
                            pickle.dump(model, open("model.pkl", "wb"))
                        except:
                            os.remove("model.pkl")
                            pickle.dump(model, open("model.pkl", "wb"))
                #self.producer.close()

        finally:
            # Close down consumer to commit final offsets.
            self.consumer.close()
Пример #25
0
def main():
    parser = argparse.ArgumentParser(
        epilog="""Description:
           Reidentification demo using any number of cameras: 
           Either camera can be used for registration or reidentification only, or for both.
           
           Plays a video from a jpeg topic,
           visualizes head detection with a gray bounding box around a head.
           When a detection is identified, changes the bounding box color to orange
           and writes the dwell time, age and ID (derived from the reid MS ID) above the heads.
           
           Displays ('-d') or stores ('-o') the result of this demo in kafka topics.

           Required topics (example):
           - <prefix>.cam.0.original.Image.jpg
           - <prefix>.cam.0.dets.ObjectDetectionRecord.json
           - <prefix>.cam.0.frameinfo.FrameInfoRecord.json
           - <prefix>.cam.0.ages.AgeRecord.json
           - <prefix>.cam.1.original.Image.jpg
           - <prefix>.cam.1.dets.ObjectDetectionRecord.json
           - <prefix>.cam.1.frameinfo.FrameInfoRecord.json
           - <prefix>.cam.1.ages.AgeRecord.json
           ...
           - <prefix>.cam.1.reids.ReidRecord.json
           """,
        formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument("broker",
                        help="The name of the kafka broker.",
                        type=str)
    parser.add_argument("prefix",
                        help="Prefix of topics (base|skeleton).",
                        type=str)
    parser.add_argument('-d', "--display", action='store_true')
    parser.add_argument('-o',
                        '--output',
                        help='write output image into kafka topic',
                        action='store_true')
    parser.add_argument('text',
                        help='Text to display (age|dwell_time|both).',
                        type=str)
    args = parser.parse_args()

    if not args.display and not args.output:
        parser.error(
            "Missing argument: -d (display output) or -o (write output to kafka) is needed"
        )

    if args.output:
        producer = Producer({'bootstrap.servers': args.broker})

    overlay = cv2.imread('resources/powered_by_white.png',
                         cv2.IMREAD_UNCHANGED)

    # Prepare the topics to read
    input_topics = [
        f"{args.prefix}.cam.{id}.{topic_postfix}" for id in CAMERA_TOPIC_IDS
        for topic_postfix in TOPIC_POSTFIXES
    ]
    reid_topics = [
        f"{args.prefix}.cam.{id}.{topic_postfix}" for id in REID_TOPIC_IDS
        for topic_postfix in REID_TOPIC_POSTFIXES
    ]
    consumable_topics = list(map(TopicInfo, input_topics)) \
                        + (list(map(lambda t: TopicInfo(t, drop=False), reid_topics)))

    # TODO (when names via person stream): Remove this consumer
    reg_consumer = Consumer({
        'bootstrap.servers': args.broker,
        'group.id': 'multicamreid_reg',
        'auto.offset.reset': 'earliest'
    })
    reg_consumer.assign(
        [TopicPartition(topic="named.records.json", partition=0, offset=0)])

    output_topics = dict((id, f"{args.prefix}.cam.{id}.{OUTPUT_TOPIC_POSTFIX}")
                         for id in CAMERA_TOPIC_IDS)

    # read message, draw and display them
    consumer = TimeOrderedGeneratorWithTimeout(broker=args.broker,
                                               groupid="detection",
                                               topics_infos=consumable_topics,
                                               latency_ms=200,
                                               commit_interval_sec=None,
                                               group_by_time=True)

    registrations: Dict[str, Registration] = {}
    i = 0
    inner_id = 0
    scaling = 1.0
    for msgs in consumer.getMessages():
        k = -1
        for time, v in message_list_to_frame_structure(msgs).items():
            message = v.get(args.prefix, {})

            # Collect Reid records
            reid_records = {}
            for reid_id in REID_TOPIC_IDS:
                reid_message = message.get(reid_id, {})
                reid_records.update(reid_message.get("reid", {}))

            # Process the image
            for topic_key, topic_message in filter(
                    lambda t: t[0] not in REID_TOPIC_IDS, message.items()):
                img = topic_message.get("image", {})
                if not isinstance(img, np.ndarray):
                    continue
                head_detections = topic_message.get("head_detection", {})
                # Set the image scale
                shape_orig = head_detections.pop("image", {})
                if shape_orig:
                    scaling = img.shape[1] / shape_orig["frame_info"]["columns"]

                # Processing the detections of the image
                for detection_key, detection_record in head_detections.items():
                    object_detection_record = detection_record.get(
                        "bounding_box", {})
                    if not object_detection_record:
                        continue
                    key_to_display = ""
                    color = COLOR_DARK_GREY

                    face_detection = detection_record.get("unknown", {})
                    if face_detection:
                        color = COLOR_LIGHT_GREY

                    age = None
                    age_detection_record = detection_record.get("age", {})
                    if age_detection_record:
                        age = age_detection_record["age"]
                    if args.text == "age" or args.text == "both":
                        key_to_display = f"Age: {age}" if age else ""

                    # Reidentification received for the detection
                    reid_records_for_det = reid_records.get(detection_key, {})
                    if reid_records_for_det:
                        for reid_record in filter(lambda r: "reid_event" in r,
                                                  reid_records_for_det):
                            # We only use the first [0] identified face now
                            reid_key = reid_record["reid_event"]["match_list"][
                                0]["id"]["first_detection_key"]
                            registered = registrations.get(reid_key, None)
                            if registered:
                                age_to_display = ""
                                if age:
                                    registered.addAge(age)
                                if args.text == "age" or args.text == "both":
                                    age_to_display = f"; Age: {registered.age:d}" if age else ""
                                # Calculate the dwell time if required
                                dwell_time_display = ""
                                if args.text == "dwell_time" or args.text == "both":
                                    detection_time = reid_record["reid_event"][
                                        "match_list"][0]["id"][
                                            "first_detection_time"]
                                    dwell_time = time - int(detection_time)
                                    dwell_time_display = f"; Dwell time: {dwell_time}ms"
                                color = COLOR_ORANGE
                                name_to_display = registered.name if registered.name else f"ID: {registered.id}"
                                key_to_display = f"{name_to_display}{age_to_display}{dwell_time_display}"

                            else:
                                inner_id += 1
                                registrations[reid_key] = Registration(
                                    id=inner_id)
                                if age:
                                    registrations[reid_key].addAge(age)

                                # Update the technical naming topic
                                #  TODO (when names via person stream): remove
                                producer.produce(
                                    "detected.records.json",
                                    key=str(reid_key).encode("utf-8"),
                                    value=(str(inner_id) +
                                           ";").encode("utf-8"),
                                    timestamp=time)

                    # Read the technical naming topic
                    #  TODO (when names via person stream): remove
                    reg_msg = reg_consumer.poll(0.01)
                    if reg_msg is not None:
                        try:
                            key = reg_msg.key().decode("utf-8")
                            name = reg_msg.value().decode("utf-8")
                            # Update the person name
                            reg_to_update = registrations.get(key)
                            if reg_to_update:
                                reg_to_update.addName(name)
                            else:
                                registrations[key] = Registration(name=name)
                        except:
                            print(
                                "Decoding entry of the named.records topic failed.",
                                flush=True)

                    # draw text above bounding box
                    img = draw_nice_text(
                        canvas=img,
                        text=key_to_display,
                        bounding_box=object_detection_record["bounding_box"],
                        color=color,
                        scale=scaling)

                    # draw bounding_box
                    img = draw_nice_bounding_box(
                        canvas=img,
                        bounding_box=object_detection_record["bounding_box"],
                        color=color,
                        scaling=scaling)

                # draw ultinous logo
                img = draw_overlay(canvas=img,
                                   overlay=overlay,
                                   position=Position.BOTTOM_RIGHT,
                                   scale=scaling)

                # produce output topic
                if args.output:
                    out_topic = output_topics.get(topic_key)
                    producer.produce(out_topic,
                                     value=encode_image_to_message(img),
                                     timestamp=time)
                    producer.poll(0)
                    if i % 1000 == 0:
                        producer.flush()
                    i += 1

                # display #
                if args.display:
                    cv2.imshow(f"DEMO Camera {topic_key}", img)
                    k = cv2.waitKey(33)

        if k == 113:  # The 'q' key to stop
            break
        elif k == -1:  # normally -1 returned,so don't print it
            continue
        else:
            print(f"Press 'q' key for EXIT!")
Пример #26
0
def main():
    parser = argparse.ArgumentParser(
        epilog="""Description:
           Plays video from a jpeg topic, and visualize the head pose records with 3 diff color lines.
           [see: The yaw, pitch, and roll angles in the human head motion]
           Displays ('-d') or stores ('-o') the result of this demo in the kafka topic.
           
           Required topics:
           - <prefix>.cam.0.original.Image.jpg
           - <prefix>.cam.0.dets.ObjectDetectionRecord.json
           - <prefix>.cam.0.poses.HeadPose3DRecord.json
           """,
        formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument("broker",
                        help="The name of the kafka broker.",
                        type=str)
    parser.add_argument("prefix",
                        help="Prefix of topics (base|skeleton).",
                        type=str)
    parser.add_argument('-f', "--full_screen", action='store_true')
    parser.add_argument('-d', "--display", action='store_true')
    parser.add_argument('-o',
                        '--output',
                        help='write output image into kafka topic',
                        action='store_true')
    args = parser.parse_args()

    if not args.display and not args.output:
        parser.error(
            "Missing argument: -d (display output) or -o (write output to kafka) is needed"
        )

    if args.output:
        producer = Producer({'bootstrap.servers': args.broker})

    overlay = cv2.imread('resources/powered_by_white.png',
                         cv2.IMREAD_UNCHANGED)

    image_topic = f"{args.prefix}.cam.0.original.Image.jpg"
    detection_topic = f"{args.prefix}.cam.0.dets.ObjectDetectionRecord.json"
    pose_topic = f"{args.prefix}.cam.0.poses.HeadPose3DRecord.json"
    output_topic_name = f"{args.prefix}.cam.0.head_pose.Image.jpg"

    # handle full screen
    window_name = "DEMO: Head pose"
    if args.full_screen:
        cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
        cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN,
                              cv2.WINDOW_FULLSCREEN)

    # read message, draw and display them
    consumer = TimeOrderedGeneratorWithTimeout(args.broker, "detection", [
        TopicInfo(image_topic),
        TopicInfo(detection_topic),
        TopicInfo(pose_topic),
    ], 100, None, True)
    i = 0
    for msgs in consumer.getMessages():
        for time, v in message_list_to_frame_structure(msgs).items():
            img = v[args.prefix]["0"]["image"]
            if type(img) == np.ndarray:
                # draw bounding_box
                for head_detection in v[args.prefix]["0"]["head_detection"]:
                    object_detection_record = v[args.prefix]["0"][
                        "head_detection"][head_detection]["bounding_box"]
                    if object_detection_record["type"] == "PERSON_HEAD":
                        pose_record = v[args.prefix]["0"]["head_detection"][
                            head_detection]["head_pose"]
                        if "pose" in pose_record:
                            img = draw_head_pose(
                                img,
                                pose_record["pose"],
                                object_detection_record["bounding_box"],
                            )

                # draw ultinous logo
                img = draw_overlay(img, overlay, Position.BOTTOM_RIGHT)

                # produce output topic
                if args.output:
                    producer.produce(output_topic_name,
                                     value=encode_image_to_message(img),
                                     timestamp=time)
                    producer.poll(0)
                    if i % 100 == 0:
                        producer.flush()
                    i += 1

                # display
                if args.display:
                    cv2.imshow(window_name, img)
        k = cv2.waitKey(33)
        if k == 113:  # The 'q' key to stop
            break
        elif k == -1:  # normally -1 returned,so don't print it
            continue
        else:
            print(f"Press 'q' key for EXIT!")