Recently, when doing real-time video prediction of flames, I always encounter delay problems, ranging from a few seconds to ten seconds or tens of seconds, which is difficult to accept.
The following scheme can control the delay within 1 second.
The overall idea: adopt kafka
kafka installation reference Installation kafka
producers to obtain video streams get each frame, call processing algorithm model, the processed frame into kafka,
consumers subscribe kafka news video.
The producer code is as followskafka_producer.py
# -*- coding: utf-8 -*-
from kafka import KafkaProducer
from imutils.video import VideoStream
import requests
import imutils
import numpy as np
import time
import cv2
from PIL import Image
from io import BytesIO
import base64
import json
def publish_video(server, topic, rtsp, api_url):
producer = KafkaProducer(bootstrap_servers=server)
vs = VideoStream(src=rtsp).start()
time.sleep(2.0)
print("publishing video...")
while True:
frame = vs.read()
frame = process(frame, api_url)
frame = imutils.resize(frame, width=400)
# send to kafka topic
producer.send(topic, frame.tobytes())
vs.stop()
def process(frame, api_url):
img = Image.fromarray(frame)
output_buffer = BytesIO() # 创建一个BytesIO
img.save(output_buffer, format='JPEG') # 写入output_buffer
byte_data = output_buffer.getvalue() # 在内存中读取
image_base64 = base64.b64encode(byte_data).decode() # 转为BASE64
data = json.dumps(
{"image": image_base64, "visual_result": "True", "username": "xsrt", "password": "dGVzdC1wd2QxMjM="})
headers = {"Content-Type": "application/json"}
response = requests.post(api_url, data=data, headers=headers)
result = response.text
result = json.loads(result)
try:
base64_img = result["base64"]
process_img = base64.b64decode(base64_img)
img = cv2.imdecode(np.frombuffer(process_img, np.uint8), cv2.IMREAD_COLOR)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
except:
img = frame
return img
def process_list(result):
for i in result:
result_i = i
result_i_bbox = result_i["bbox"]
for i in range(len(result_i_bbox)):
result_i_bbox[i] = result_i_bbox[i] * 2
return result
if __name__ == '__main__':
server = '192.168.20.99:9092'
topic = 'run'
# rtsp = 'rtsp://admin:[email protected]:554/h264/ch1/main/av_stream'
rtsp = 0
api_url = 'http://192.168.20.99:8191/fire/json'
publish_video(server, topic, rtsp, api_url)
The consumer code is as follows kafka_consumer.py
from imutils.video import VideoStream
from imutils.video import FPS
import numpy as np
import time
import cv2
from kafka import KafkaConsumer
import sys
def showCam(server, topic, window_name):
consumer = KafkaConsumer(
topic,
bootstrap_servers=[server])
fps = FPS().start()
for msg in consumer:
# print(msg)
decoded = np.frombuffer(msg.value, np.uint8)
# print(decoded.size)
# decoded = decoded.reshape(225, 400, 3)
decoded = decoded.reshape((int)(decoded.size / (400 * 3)), 400, 3)
cv2.namedWindow(window_name, flags=cv2.WINDOW_FREERATIO)
cv2.imshow(window_name, decoded)
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
break
fps.update()
fps.stop()
cv2.destroyAllWindows()
if __name__ == '__main__':
server = '192.168.20.99:9092'
topic = 'run'
window_name = 'fire'
showCam(server, topic, window_name)
further optimization
kafka_producer.py
# -*- coding: utf-8 -*-
from kafka import KafkaProducer
from imutils.video import VideoStream
import requests
import imutils
import numpy as np
import time
import cv2
from PIL import Image
from io import BytesIO
import base64
import json
def publish_video(server, topic, rtsp, api_url):
producer = KafkaProducer(bootstrap_servers=server)
vs = VideoStream(src=rtsp).start()
time.sleep(2.0)
print("publishing video...")
i = 0
a = 5
while True:
i = i +1
if i % a == 0:
frame = vs.read()
if q.qsize() > 1:
q.get()
else:
q.put(frame)
# frame = process(frame)
# frame = imutils.resize(frame, width=400)
frame = q.get()
if frame is not None:
frame = imutils.resize(frame, width=400)
# frame = detection(frame, 'pretrained.prototxt.txt', 'pretrained.caffemodel')
frame = process(frame)
# send to kafka topic
producer.send(topic, frame.tobytes())
vs.stop()
def process(frame, api_url):
img = Image.fromarray(frame)
output_buffer = BytesIO() # 创建一个BytesIO
img.save(output_buffer, format='JPEG') # 写入output_buffer
byte_data = output_buffer.getvalue() # 在内存中读取
image_base64 = base64.b64encode(byte_data).decode() # 转为BASE64
data = json.dumps(
{"image": image_base64, "visual_result": "True", "username": "xsrt", "password": "dGVzdC1wd2QxMjM="})
headers = {"Content-Type": "application/json"}
response = requests.post(api_url, data=data, headers=headers)
result = response.text
result = json.loads(result)
try:
base64_img = result["base64"]
process_img = base64.b64decode(base64_img)
img = cv2.imdecode(np.frombuffer(process_img, np.uint8), cv2.IMREAD_COLOR)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
except:
img = frame
return img
def process_list(result):
for i in result:
result_i = i
result_i_bbox = result_i["bbox"]
for i in range(len(result_i_bbox)):
result_i_bbox[i] = result_i_bbox[i] * 2
return result
if __name__ == '__main__':
server = '192.168.20.99:9092'
topic = 'run'
# rtsp = 'rtsp://admin:[email protected]:554/h264/ch1/main/av_stream'
rtsp = 0
api_url = 'http://192.168.20.99:8191/fire/json'
publish_video(server, topic, rtsp, api_url)
You can also optimize, refer to the following scheme to
read the video stream of multiple (Haikang\Dahua) webcams (using opencv-python) to solve the problem of real-time reading delay