计算每秒 opencv 发送的帧数的问题

Issue in calculating frames sent per second opencv

我有以下代码,我正在计算每秒从客户端向服务器发送帧所花费的时间,基本上是计算帧丢失率的百分比和响应所花费的时间,并且通信模式是异步的。 现在我在计算这两个指标时遇到了一些问题,为了响应所花费的时间,我将延迟设置为超过 5 秒,因为由于网络和服务器的处理速度,将结果发送回客户端需要时间,因此,延迟更长, 但对于每秒帧数,我需要计算每秒从客户端发送到服务器的帧数,我将如何在 data_rate 方法中计算它。两个指标都需要不同的时间延迟,我不能对两个指标使用相同的时间延迟。非常感谢有关如何在代码中定义它的帮助。

IMAGE_FOLDER = "videoframe"
FPS = 5
SERVER_A_ADDRESS = "tcp://localhost:5555"
ENDPOINT_HANDLER_ADDRESS = "tcp://*:5553"
SERVER_A_TITLE = "SERVER A"
SERVER_B_TITLE = "SERVER B"
context = zmq.Context()
socket_server_a = context.socket(zmq.PUSH)
socket_server_endpoint = context.socket(zmq.PULL)

socket_server_a.connect(SERVER_A_ADDRESS)
socket_server_endpoint.bind(ENDPOINT_HANDLER_ADDRESS)

destination = {
 "currentSocket": socket_server_a,
 "currentServersTitle": SERVER_A_TITLE,
 "currentEndpoint": SERVER_B_TITLE,}

running = True
endpoint_responses = 0
frame_requests = 0
filenames = [f"{IMAGE_FOLDER}/frame{i}.jpg" for i in range(1, 2522)]

def handle_endpoint_responses():
  global destination, running, endpoint_responses
  while running:
    endpoint_response = socket_server_endpoint.recv().decode()
    endpoint_responses += 1
def data_rate():
  global destination, running, endpoint_responses, frame_requests
  while running:
    before_received = endpoint_responses ###
    time.sleep(5)
    after_received = endpoint_responses
    before_sent = frame_requests
    time.sleep(1)
    after_sent = frame_requests ###
    print(25 * "#")
    print(f"{time.strftime('%H:%M:%S')} ( i ) : receiving model results: {round((after_received - before_received) / 5, 2)} per second.")
    print(f"{time.strftime('%H:%M:%S')} ( i ) : sending frames: {round((after_sent - before_sent) / 1, 2)} per second.")
    print(25 * "#")
def send_frame(frame, frame_requests):
  global destination, running
  try:
    frame = cv2.resize(frame, (224, 224))
    encoded, buffer = cv2.imencode('.jpg', frame)
    jpg_as_text = base64.b64encode(buffer)
    destination["currentSocket"].send(jpg_as_text)
  except Exception as Error:
    running = False
def main():
 global destination, running, frame_requests
 interval = 1 / FPS
 while running:
    for img in filenames:
        frame = cv2.imread(img)
        frame_requests += 1
        threading.Thread(target=send_frame, args=(frame, frame_requests)).start()
        time.sleep(interval)
 destination["currentSocket"].close()
if __name__ == "__main__":
  threading.Thread(target=handle_endpoint_responses).start()
  threading.Thread(target=data_rate).start()
  main()

不仅是服务器时间,打开图片也需要时间,使用sleep interval = 1/FPS也可能导致掉帧,即产生的帧数比可能的少(离线播放也是如此)。对于播放,如果完成睡眠,间隔可以更短,并且可以在循环中检查当前时间,如果时间合适 - 发送下一帧,如果不合适 - 等待。延迟也可以是自适应的,并且该时间可能提前于线性周期,以补偿传输延迟,如果目标是服务器端在实际帧时间显示或对图像进行某些操作。

我认为你必须每次 synchronize/measure 客户端和服务器的时钟差异与初始握手或作为交易的一部分,并包括和记录时间sending/receiving 在 transactions/log.

这样你就可以测量传输的一些平均延迟。

另一件可能给出提示的事情是最初播放图像而不发送它们。这将显示 cv2.imread(...) 和预处理需要多少时间。

即commenting/adding 另一个没有目标的函数["currentSocket"].send(jpg_as_text)