bump
This commit is contained in:
BIN
__pycache__/utils.cpython-311.pyc
Normal file
BIN
__pycache__/utils.cpython-311.pyc
Normal file
Binary file not shown.
337
analyze_dump.py
Normal file
337
analyze_dump.py
Normal file
@@ -0,0 +1,337 @@
|
||||
import pickle
|
||||
with open('/home/thebears/source/infer/dump','rb') as ff:
|
||||
dump = pickle.load(ff)
|
||||
|
||||
|
||||
|
||||
# %%
|
||||
|
||||
import av
|
||||
import numpy as np
|
||||
|
||||
#def rtp_to_matrix(rtp_packets):
|
||||
if True:
|
||||
"""Convert list of RTP packets to image matrix"""
|
||||
|
||||
# Create codec context (adjust codec based on your stream)
|
||||
codec = av.CodecContext.create('h264', 'r') # or 'h265', 'mjpeg', etc.
|
||||
|
||||
frames = []
|
||||
for _,rtp_packet in ts_data.items():
|
||||
# Extract payload (skip RTP header - usually 12 bytes)
|
||||
payload = rtp_packet
|
||||
# Create packet
|
||||
print(len(payload))
|
||||
packet = av.Packet(payload)
|
||||
|
||||
try:
|
||||
# Decode
|
||||
for frame in codec.decode(packet):
|
||||
# Convert to numpy array
|
||||
img = frame.to_ndarray(format='bgr24')
|
||||
frames.append(img)
|
||||
except Exception as e:
|
||||
print(f"Decode error: {e}")
|
||||
continue
|
||||
|
||||
# Flush decoder
|
||||
for frame in codec.decode(None):
|
||||
img = frame.to_ndarray(format='bgr24')
|
||||
frames.append(img)
|
||||
|
||||
|
||||
|
||||
# Usage
|
||||
# rtp_packets = [packet1, packet2, ...] # Your raw RTP packets
|
||||
# matrices = rtp_to_matrix(rtp_packets)
|
||||
|
||||
|
||||
# %%
|
||||
|
||||
import subprocess
|
||||
import numpy as np
|
||||
import cv2
|
||||
from io import BytesIO
|
||||
|
||||
class RTPDepayloader:
|
||||
def __init__(self, payload_type):
|
||||
"""
|
||||
payload_type: 96=H264, 26=JPEG, etc.
|
||||
"""
|
||||
self.payload_type = payload_type
|
||||
self.buffer = bytearray()
|
||||
|
||||
def parse_rtp_header(self, packet):
|
||||
"""Parse RTP header and return payload"""
|
||||
if len(packet) < 12:
|
||||
return None
|
||||
|
||||
# RTP Header structure (12 bytes minimum)
|
||||
# Byte 0: V(2), P(1), X(1), CC(4)
|
||||
# Byte 1: M(1), PT(7)
|
||||
# Bytes 2-3: Sequence number
|
||||
# Bytes 4-7: Timestamp
|
||||
# Bytes 8-11: SSRC
|
||||
|
||||
version = (packet[0] >> 6) & 0x03
|
||||
padding = (packet[0] >> 5) & 0x01
|
||||
extension = (packet[0] >> 4) & 0x01
|
||||
csrc_count = packet[0] & 0x0F
|
||||
|
||||
marker = (packet[1] >> 7) & 0x01
|
||||
payload_type = packet[1] & 0x7F
|
||||
|
||||
sequence = int.from_bytes(packet[2:4], 'big')
|
||||
timestamp = int.from_bytes(packet[4:8], 'big')
|
||||
|
||||
# Calculate header size
|
||||
header_size = 12 + (csrc_count * 4)
|
||||
|
||||
if extension:
|
||||
if len(packet) < header_size + 4:
|
||||
return None
|
||||
ext_len = int.from_bytes(packet[header_size+2:header_size+4], 'big') * 4
|
||||
header_size += 4 + ext_len
|
||||
|
||||
# Return payload
|
||||
payload = packet[header_size:]
|
||||
|
||||
return {
|
||||
'payload': payload,
|
||||
'marker': marker,
|
||||
'sequence': sequence,
|
||||
'timestamp': timestamp,
|
||||
'payload_type': payload_type
|
||||
}
|
||||
|
||||
def depayload_h264(self, rtp_packets):
|
||||
"""Depayload H.264 RTP packets to NAL units"""
|
||||
nal_units = bytearray()
|
||||
|
||||
for packet in rtp_packets:
|
||||
parsed = self.parse_rtp_header(packet)
|
||||
if not parsed:
|
||||
continue
|
||||
|
||||
payload = parsed['payload']
|
||||
if len(payload) == 0:
|
||||
continue
|
||||
|
||||
# H.264 RTP payload format (RFC 6184)
|
||||
nal_unit_type = payload[0] & 0x1F
|
||||
|
||||
if nal_unit_type >= 1 and nal_unit_type <= 23:
|
||||
# Single NAL unit
|
||||
nal_units.extend(b'\x00\x00\x00\x01') # Start code
|
||||
nal_units.extend(payload)
|
||||
elif nal_unit_type == 28:
|
||||
# FU-A (Fragmentation Unit)
|
||||
fu_header = payload[1]
|
||||
start = (fu_header >> 7) & 0x01
|
||||
end = (fu_header >> 6) & 0x01
|
||||
nal_type = fu_header & 0x1F
|
||||
|
||||
if start:
|
||||
# Reconstruct NAL header
|
||||
nal_header = (payload[0] & 0xE0) | nal_type
|
||||
nal_units.extend(b'\x00\x00\x00\x01')
|
||||
nal_units.append(nal_header)
|
||||
|
||||
nal_units.extend(payload[2:])
|
||||
|
||||
return bytes(nal_units)
|
||||
|
||||
def decode_h264_to_matrix(h264_data):
|
||||
"""Decode H.264 bitstream to image matrix using FFmpeg"""
|
||||
|
||||
# Use FFmpeg to decode
|
||||
process = subprocess.Popen([
|
||||
'ffmpeg',
|
||||
'-f', 'h264',
|
||||
'-i', 'pipe:0',
|
||||
'-f', 'rawvideo',
|
||||
'-pix_fmt', 'bgr24',
|
||||
'pipe:1'
|
||||
], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
stdout, stderr = process.communicate(input=h264_data)
|
||||
|
||||
# You need to know dimensions or parse from SPS
|
||||
# For now, assume 1920x1080
|
||||
width, height = 1920, 1080
|
||||
|
||||
if len(stdout) >= width * height * 3:
|
||||
frame = np.frombuffer(stdout[:width*height*3], dtype=np.uint8)
|
||||
frame = frame.reshape((height, width, 3))
|
||||
return frame
|
||||
|
||||
return None
|
||||
|
||||
# Usage
|
||||
rtp_packets = [bytes(x) for x in dump]
|
||||
depayloader = RTPDepayloader(payload_type=96)
|
||||
# rtp_packets = [...] # Your raw RTP packets
|
||||
h264_stream = depayloader.depayload_h264(rtp_packets)
|
||||
matrix = decode_h264_to_matrix(h264_stream)
|
||||
|
||||
|
||||
# %%
|
||||
|
||||
|
||||
bts = b''
|
||||
for i in range(10000):
|
||||
bts+=process.stdout.read(1024)
|
||||
print(i)
|
||||
# %%
|
||||
with open('dumpb','wb') as ff:
|
||||
ff.write(bts)
|
||||
# %%
|
||||
import re
|
||||
pattern = b'BM'
|
||||
|
||||
fcf = [m.start() for m in re.finditer(re.escape(pattern), bts)]
|
||||
|
||||
|
||||
# %%
|
||||
|
||||
with open('dumpb','rb') as ff:
|
||||
byte_stream = ff.read()[10:]
|
||||
|
||||
|
||||
import struct
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
|
||||
|
||||
|
||||
# %%
|
||||
import struct
|
||||
|
||||
|
||||
def read_bmp_frames(stream):
|
||||
"""Read individual BMP frames from a stream."""
|
||||
while True:
|
||||
# Read BMP signature (2 bytes)
|
||||
signature = stream.read(2)
|
||||
if len(signature) < 2:
|
||||
break
|
||||
|
||||
if signature != b'BM':
|
||||
print(f"Warning: Expected 'BM', got {signature}")
|
||||
break
|
||||
|
||||
# Read file size (4 bytes, little-endian)
|
||||
size_bytes = stream.read(4)
|
||||
if len(size_bytes) < 4:
|
||||
break
|
||||
|
||||
file_size = struct.unpack('<I', size_bytes)[0]
|
||||
|
||||
# Read the rest of the frame
|
||||
remaining_size = file_size - 6 # Already read 6 bytes
|
||||
frame_data = stream.read(remaining_size)
|
||||
|
||||
if len(frame_data) < remaining_size:
|
||||
break
|
||||
|
||||
# Complete frame
|
||||
complete_frame = signature + size_bytes + frame_data
|
||||
yield complete_frame
|
||||
|
||||
# Usage
|
||||
import subprocess as sp
|
||||
|
||||
cmd = "ffmpeg -rtsp_transport tcp -i rtsp://admin:marybear@192.168.1.153:554/h264Preview_01_sub -f image2pipe -vcodec bmp -an pipe:1"
|
||||
|
||||
# process = sp.Popen(
|
||||
# cmd.split(" "),
|
||||
# stdout=sp.PIPE,
|
||||
# stderr=sp.PIPE,
|
||||
# bufsize =512*896*3*3
|
||||
# )
|
||||
|
||||
|
||||
|
||||
|
||||
import asyncio
|
||||
import subprocess
|
||||
|
||||
async def read_stream():
|
||||
"""Read subprocess output asynchronously."""
|
||||
|
||||
process = await asyncio.create_subprocess_exec(*cmd.split(" "),
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE
|
||||
)
|
||||
frame_count = 0
|
||||
try:
|
||||
while True:
|
||||
# Read up to 65KB at a time
|
||||
chunk = await process.stdout.read(65536)
|
||||
print('chunk')
|
||||
if not chunk:
|
||||
break
|
||||
|
||||
frame_count += len(chunk)
|
||||
print(f"Read {len(chunk)} bytes (total: {frame_count})")
|
||||
|
||||
except asyncio.CancelledError:
|
||||
process.kill()
|
||||
await process.wait()
|
||||
|
||||
return frame_count
|
||||
|
||||
# Run
|
||||
frame_count = asyncio.run(read_stream())
|
||||
# %%
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# %%
|
||||
|
||||
import numpy as np
|
||||
fr = next(gen)
|
||||
import cv2
|
||||
|
||||
# %%
|
||||
|
||||
import av
|
||||
import numpy as np
|
||||
|
||||
def rtp_to_matrix(rtp_packets):
|
||||
"""Convert list of RTP packets to image matrix"""
|
||||
|
||||
# Create codec context (adjust codec based on your stream)
|
||||
codec = av.CodecContext.create('h264', 'r') # or 'h265', 'mjpeg', etc.
|
||||
|
||||
frames = []
|
||||
for rtp_packet in rtp_packets:
|
||||
# Extract payload (skip RTP header - usually 12 bytes)
|
||||
payload = rtp_packet[12:]
|
||||
|
||||
# Create packet
|
||||
packet = av.Packet(payload)
|
||||
|
||||
try:
|
||||
# Decode
|
||||
for frame in codec.decode(packet):
|
||||
# Convert to numpy array
|
||||
img = frame.to_ndarray(format='bgr24')
|
||||
frames.append(img)
|
||||
except Exception as e:
|
||||
print(f"Decode error: {e}")
|
||||
continue
|
||||
|
||||
# Flush decoder
|
||||
for frame in codec.decode(None):
|
||||
img = frame.to_ndarray(format='bgr24')
|
||||
frames.append(img)
|
||||
|
||||
return frames
|
||||
|
||||
# Usage
|
||||
# rtp_packets = [packet1, packet2, ...] # Your raw RTP packets
|
||||
# matrices = rtp_to_matrix(rtp_packets)
|
||||
255
flycheck_run_me.py
Normal file
255
flycheck_run_me.py
Normal file
@@ -0,0 +1,255 @@
|
||||
import numpy as np
|
||||
from functools import partial
|
||||
from hailo_platform import VDevice, HailoSchedulingAlgorithm, FormatType
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
|
||||
def resize_image(img_in, reshape_to_final=True):
|
||||
if not isinstance(img_in, np.ndarray):
|
||||
img_in = np.asarray(img_in)
|
||||
max_l = 640
|
||||
|
||||
asp_rat = img_in.shape[0] / img_in.shape[1]
|
||||
if asp_rat < 1:
|
||||
output_size = [int(asp_rat * max_l), max_l]
|
||||
else:
|
||||
output_size = [max_l, int(max_l / asp_rat)]
|
||||
|
||||
im_arr_not_pad = cv2.resize(img_in, output_size[::-1])
|
||||
pad_amt = [max_l, max_l] - np.asarray(im_arr_not_pad.shape[0:2])
|
||||
|
||||
left_pad, top_pad = (pad_amt / 2).astype(np.int64)
|
||||
right_pad, bottom_pad = pad_amt - [left_pad, top_pad]
|
||||
|
||||
im_pass = np.zeros(shape=(max_l, max_l, 3), dtype=np.uint8)
|
||||
im_pass[left_pad:(max_l - right_pad),
|
||||
top_pad:(max_l - bottom_pad)] = (im_arr_not_pad)
|
||||
data = im_pass
|
||||
if reshape_to_final:
|
||||
data = np.moveaxis(data, [2], [0])[None, :, :, :]
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def model_scoring_callback(completion_info, bindings, data):
|
||||
if completion_info.exception:
|
||||
# handle exception
|
||||
pass
|
||||
ff = bindings.output().get_buffer()
|
||||
|
||||
|
||||
timeout_ms = 1000
|
||||
|
||||
params = VDevice.create_params()
|
||||
params.scheduling_algorithm = HailoSchedulingAlgorithm.ROUND_ROBIN
|
||||
import time
|
||||
|
||||
# The vdevice is used as a context manager ("with" statement) to ensure it's released on time.
|
||||
with VDevice(params) as vdevice:
|
||||
# Create an infer model from an HEF:
|
||||
infer_model = vdevice.create_infer_model("yolov11l_inat.hef")
|
||||
|
||||
# Configure the infer model and create bindings for it
|
||||
with infer_model.configure() as configured_infer_model:
|
||||
bindings = configured_infer_model.create_bindings()
|
||||
st = time.time()
|
||||
for i in range(1):
|
||||
# Set input and output buffers
|
||||
buffer = inp # np.zeros(infer_model.input().shape).astype(np.uint8)
|
||||
bindings.input().set_buffer(buffer)
|
||||
|
||||
output_array = np.zeros([infer_model.output().shape[0]
|
||||
]).astype(np.float32)
|
||||
bindings.output().set_buffer(output_array)
|
||||
|
||||
# Run synchronous inference and access the output buffers
|
||||
configured_infer_model.run([bindings], timeout_ms)
|
||||
buffer = bindings.output().get_buffer()
|
||||
|
||||
# Run asynchronous inference
|
||||
job = configured_infer_model.run_async(
|
||||
[bindings],
|
||||
partial(example_callback, bindings=bindings, data=time.time()),
|
||||
)
|
||||
job.wait(timeout_ms)
|
||||
|
||||
# %%
|
||||
import cv2
|
||||
import time
|
||||
import multiprocessing
|
||||
import numpy as np
|
||||
import ctypes
|
||||
import shutil
|
||||
from utils import *
|
||||
|
||||
cameras = {
|
||||
"camera_sidefeeder": {
|
||||
'url': "rtsp://admin:marybear@192.168.1.157:554/h264Preview_01_sub",
|
||||
'resolution': (480, 640, 3)
|
||||
},
|
||||
"camera_driveway": {
|
||||
'url': "rtsp://admin:marybear@192.168.1.152:554/h264Preview_01_sub",
|
||||
'resolution': (480, 640, 3)
|
||||
},
|
||||
"camera_railing": {
|
||||
'url': "rtsp://admin:marybear@192.168.1.153:554/h264Preview_01_sub",
|
||||
'resolution': (512, 896, 3)
|
||||
},
|
||||
"camera_ptz_right": {
|
||||
'url': "rtsp://admin:marybear@192.168.1.155:554/h264Preview_01_sub",
|
||||
'resolution': (360, 640, 3)
|
||||
},
|
||||
"camera_wrenwatch": {
|
||||
'url': "rtsp://admin:marybear@192.168.1.158:554/h264Preview_01_sub",
|
||||
'resolution': (360, 640, 3)
|
||||
},
|
||||
"camera_backyard": {
|
||||
'url': "rtsp://admin:marybear@192.168.1.162:554/h264Preview_01_sub",
|
||||
'resolution': (432, 1536, 3),
|
||||
'split_into_two': True
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
from functools import partial
|
||||
|
||||
cameras = dict()
|
||||
for cam_name, details in cameras.items():
|
||||
rtsp_url = details['url']
|
||||
resolution = details['resolution']
|
||||
cameras[cam_name] = StreamManager( rtsp_url, resolution, cam_name)
|
||||
|
||||
|
||||
# %%
|
||||
details['cam_name'] = cam_name
|
||||
details['img_array'] = multiprocessing.Array(ctypes.c_uint8,
|
||||
int(array_len),
|
||||
lock=True)
|
||||
details['img_timestamp'] = multiprocessing.Value(ctypes.c_double)
|
||||
details['queue'] = multiprocessing.Queue()
|
||||
details['rtsp_url'] = format_ffmpeg_decode_url(details['url']).split(" ")
|
||||
details['process_func'] = partial(stream_wrapper,
|
||||
details['resolution'],
|
||||
details['rtsp_url'],
|
||||
camera_name=cam_name,
|
||||
queue=details['queue'],
|
||||
img_array=details['img_array'],
|
||||
img_timestamp=details['img_timestamp'])
|
||||
|
||||
for cam_name, details in cameras.items():
|
||||
p = multiprocessing.Process(target = details['process_func'])
|
||||
details['process'] = p
|
||||
p.start()
|
||||
|
||||
# %%
|
||||
img_array = details['img_array']
|
||||
img_timestamp = details['img_timestamp']
|
||||
|
||||
import time
|
||||
with img_timestamp.get_lock():
|
||||
img_timestamp.value = -1
|
||||
details['queue'].put('get')
|
||||
for i in range(1000):
|
||||
val = img_timestamp.value
|
||||
print(val)
|
||||
if val > 0:
|
||||
|
||||
print('Done')
|
||||
break
|
||||
time.sleep(0.001)
|
||||
|
||||
|
||||
# %%
|
||||
for cam_name, details in cameras.items():
|
||||
details['queue'].put('get')
|
||||
img_array = details['img_array']
|
||||
img_timestamp = details['img_timestamp']
|
||||
with img_array.get_lock(), img_timestamp.get_lock():
|
||||
reshaped_image = np.frombuffer(details['img_array'].get_obj(),
|
||||
dtype=np.uint8).reshape(
|
||||
details['resolution'])
|
||||
timestamp = img_timestamp.value
|
||||
img_timestamp.value = -1
|
||||
print('Writing for ' + cam_name + f' for {reshaped_image.shape}')
|
||||
cv2.imwrite('images/'+ cam_name + '.jpg', reshaped_image)
|
||||
|
||||
|
||||
|
||||
# %%
|
||||
import asyncio
|
||||
|
||||
img_scoring_queue = multiprocessing.Queue()
|
||||
|
||||
for cam_name, details in cameras.items():
|
||||
p = multiprocessing.Process(target=rtsp_stream_manager,
|
||||
args=(cam_name, details['gst_pipeline_str'],
|
||||
details['queue'], details['img_array'],
|
||||
details['img_timestamp']))
|
||||
details['process'] = p
|
||||
|
||||
asyncio.create_task(details['async_task'])
|
||||
|
||||
shape = (512, 896, 3)
|
||||
|
||||
asyncio.run(read_stream(shape, cmd))
|
||||
|
||||
import datetime as dt
|
||||
|
||||
for cam_name, details in cameras.items():
|
||||
details['process'].start()
|
||||
# %%
|
||||
for cam_name, details in cameras.items():
|
||||
details['queue'].put('restart')
|
||||
# %%
|
||||
for cam_name, details in cameras.items():
|
||||
details['queue'].put('get')
|
||||
|
||||
if os.path.exists('images/'):
|
||||
shutil.rmtree('images/')
|
||||
|
||||
os.makedirs('images/')
|
||||
|
||||
|
||||
def create_score_message(details, reshaped_image, timestamp):
|
||||
frames = list()
|
||||
|
||||
msg = list()
|
||||
if details.get('split_into_two', False):
|
||||
split_point = int(reshaped_image.shape[1] / 2)
|
||||
left_frame = resize_image(reshaped_image[:, :split_point, :],
|
||||
reshape_to_final=False)
|
||||
right_frame = resize_image(reshaped_image[:, split_point:, :],
|
||||
reshape_to_final=False)
|
||||
|
||||
left_frame = cv2.cvtColor(left_frame, cv2.COLOR_BGR2RGB)
|
||||
right_frame = cv2.cvtColor(right_frame, cv2.COLOR_BGR2RGB)
|
||||
msg.append({
|
||||
'camera_name': details['cam_name'] + '_left',
|
||||
'frame': left_frame,
|
||||
'image_timestamp': timestamp
|
||||
})
|
||||
msg.append({
|
||||
'camera_name': details['cam_name'] + '_right',
|
||||
'frame': right_frame,
|
||||
'image_timestamp': timestamp
|
||||
})
|
||||
|
||||
else:
|
||||
frame = resize_image(reshaped_image, reshape_to_final=False)
|
||||
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||
msg.append({
|
||||
'camera_name': details['cam_name'],
|
||||
'frame': frame,
|
||||
'image_timestamp': timestamp
|
||||
})
|
||||
|
||||
return msg
|
||||
|
||||
|
||||
for x in range(img_scoring_queue.qsize()):
|
||||
qu = img_scoring_queue.get()
|
||||
print(qu['camera_name'], qu['frame'].shape)
|
||||
cv2.imwrite(str(x) + '.jpg', qu['frame'])
|
||||
BIN
images/camera_backyard.jpg
Normal file
BIN
images/camera_backyard.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 495 KiB |
BIN
images/camera_driveway.jpg
Normal file
BIN
images/camera_driveway.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 198 KiB |
BIN
images/camera_ptz_right.jpg
Normal file
BIN
images/camera_ptz_right.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 176 KiB |
BIN
images/camera_railing.jpg
Normal file
BIN
images/camera_railing.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 222 KiB |
BIN
images/camera_side.jpg
Normal file
BIN
images/camera_side.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
BIN
images/camera_wrenwatch.jpg
Normal file
BIN
images/camera_wrenwatch.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 185 KiB |
182
run_me.py
182
run_me.py
@@ -2,7 +2,6 @@ import numpy as np
|
||||
from functools import partial
|
||||
from hailo_platform import VDevice, HailoSchedulingAlgorithm, FormatType
|
||||
import cv2
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
@@ -33,7 +32,6 @@ def resize_image(img_in, reshape_to_final=True):
|
||||
return data
|
||||
|
||||
|
||||
|
||||
def model_scoring_callback(completion_info, bindings, data):
|
||||
if completion_info.exception:
|
||||
# handle exception
|
||||
@@ -83,9 +81,11 @@ import multiprocessing
|
||||
import numpy as np
|
||||
import ctypes
|
||||
import shutil
|
||||
from utils import *
|
||||
|
||||
cameras = {
|
||||
"camera_side": {
|
||||
'url': "rtsp://admin:marybear@192.168.1.151:554/h264Preview_01_sub",
|
||||
"camera_sidefeeder": {
|
||||
'url': "rtsp://admin:marybear@192.168.1.157:554/h264Preview_01_sub",
|
||||
'resolution': (480, 640, 3)
|
||||
},
|
||||
"camera_driveway": {
|
||||
@@ -111,65 +111,92 @@ cameras = {
|
||||
},
|
||||
}
|
||||
|
||||
# # %%
|
||||
# import os
|
||||
# os.environ['OPENCV_FFMPEG_CAPTURE_OPTIONS'] = 'rtsp_transport;udp'
|
||||
# cap = cv2.VideoCapture(cameras['camera_railing']['url'])
|
||||
# # %%
|
||||
# while True:
|
||||
# _, frame = cap.read()
|
||||
|
||||
# # %%
|
||||
# _, frame = cap.read()
|
||||
# cv2.imwrite('FRAME.jpg', frame)
|
||||
|
||||
# # %%
|
||||
def format_gst_url(rtsp_url):
|
||||
gst_pipeline = f"rtspsrc location={rtsp_url} latency=50 ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! appsink max-buffers=1 drop=true"
|
||||
return gst_pipeline
|
||||
|
||||
|
||||
|
||||
from functools import partial
|
||||
|
||||
cameras = dict()
|
||||
for cam_name, details in cameras.items():
|
||||
array_len = np.prod(details['resolution'])
|
||||
rtsp_url = details['url']
|
||||
resolution = details['resolution']
|
||||
cameras[cam_name] = StreamManager( rtsp_url, resolution, cam_name)
|
||||
|
||||
|
||||
# %%
|
||||
details['cam_name'] = cam_name
|
||||
details['img_array'] = multiprocessing.Array(ctypes.c_uint8,
|
||||
int(array_len), lock = True)
|
||||
int(array_len),
|
||||
lock=True)
|
||||
details['img_timestamp'] = multiprocessing.Value(ctypes.c_double)
|
||||
details['queue'] = multiprocessing.Queue()
|
||||
details['gst_pipeline_str'] = format_gst_url(details['url'])
|
||||
details['rtsp_url'] = format_ffmpeg_decode_url(details['url']).split(" ")
|
||||
details['process_func'] = partial(stream_wrapper,
|
||||
details['resolution'],
|
||||
details['rtsp_url'],
|
||||
camera_name=cam_name,
|
||||
queue=details['queue'],
|
||||
img_array=details['img_array'],
|
||||
img_timestamp=details['img_timestamp'])
|
||||
|
||||
for cam_name, details in cameras.items():
|
||||
p = multiprocessing.Process(target = details['process_func'])
|
||||
details['process'] = p
|
||||
p.start()
|
||||
|
||||
# %%
|
||||
img_array = details['img_array']
|
||||
img_timestamp = details['img_timestamp']
|
||||
|
||||
import time
|
||||
with img_timestamp.get_lock():
|
||||
img_timestamp.value = -1
|
||||
details['queue'].put('get')
|
||||
for i in range(1000):
|
||||
val = img_timestamp.value
|
||||
print(val)
|
||||
if val > 0:
|
||||
|
||||
print('Done')
|
||||
break
|
||||
time.sleep(0.001)
|
||||
|
||||
|
||||
import datetime as dt
|
||||
def rtsp_stream_manager( camera_name, gst_pipeline_str, queue, img_array, img_timestamp):
|
||||
capture_handle = cv2.VideoCapture(gst_pipeline_str, cv2.CAP_GSTREAMER)
|
||||
while True:
|
||||
if not queue.empty():
|
||||
msg = queue.get_nowait()
|
||||
if msg == 'get':
|
||||
ret, frame = capture_handle.read()
|
||||
with img_timestamp.get_lock(), img_array.get_lock():
|
||||
if frame is None:
|
||||
print(f"Read empty frame for {camera_name}")
|
||||
img_array[:] = 0
|
||||
img_timestamp.value = 0
|
||||
else:
|
||||
print(f"Read frame for {camera_name} at {dt.datetime.now()}")
|
||||
img_array[:] = frame.flatten()[:]
|
||||
img_timestamp.value = time.time()
|
||||
elif msg == 'restart':
|
||||
print('Restarting')
|
||||
capture_handle = cv2.VideoCapture(gst_pipeline_str, cv2.CAP_GSTREAMER)
|
||||
elif msg == 'exit':
|
||||
print('Exiting')
|
||||
return
|
||||
# %%
|
||||
for cam_name, details in cameras.items():
|
||||
details['queue'].put('get')
|
||||
img_array = details['img_array']
|
||||
img_timestamp = details['img_timestamp']
|
||||
with img_array.get_lock(), img_timestamp.get_lock():
|
||||
reshaped_image = np.frombuffer(details['img_array'].get_obj(),
|
||||
dtype=np.uint8).reshape(
|
||||
details['resolution'])
|
||||
timestamp = img_timestamp.value
|
||||
img_timestamp.value = -1
|
||||
print('Writing for ' + cam_name + f' for {reshaped_image.shape}')
|
||||
cv2.imwrite('images/'+ cam_name + '.jpg', reshaped_image)
|
||||
|
||||
|
||||
|
||||
# %%
|
||||
import asyncio
|
||||
|
||||
img_scoring_queue = multiprocessing.Queue()
|
||||
|
||||
for cam_name, details in cameras.items():
|
||||
p = multiprocessing.Process(target=rtsp_stream_manager,
|
||||
args=(cam_name, details['gst_pipeline_str'],
|
||||
details['queue'], details['img_array'], details['img_timestamp']))
|
||||
details['queue'], details['img_array'],
|
||||
details['img_timestamp']))
|
||||
details['process'] = p
|
||||
|
||||
asyncio.create_task(details['async_task'])
|
||||
|
||||
shape = (512, 896, 3)
|
||||
|
||||
asyncio.run(read_stream(shape, cmd))
|
||||
|
||||
import datetime as dt
|
||||
|
||||
for cam_name, details in cameras.items():
|
||||
details['process'].start()
|
||||
@@ -180,60 +207,49 @@ for cam_name, details in cameras.items():
|
||||
for cam_name, details in cameras.items():
|
||||
details['queue'].put('get')
|
||||
|
||||
|
||||
if os.path.exists('images/'):
|
||||
shutil.rmtree('images/')
|
||||
|
||||
os.makedirs('images/')
|
||||
|
||||
|
||||
def create_score_message( details, reshaped_image, timestamp):
|
||||
def create_score_message(details, reshaped_image, timestamp):
|
||||
frames = list()
|
||||
|
||||
msg = list()
|
||||
if details.get('split_into_two', False):
|
||||
split_point = int(reshaped_image.shape[1]/2)
|
||||
left_frame = resize_image(reshaped_image[:,:split_point,:], reshape_to_final = False)
|
||||
right_frame = resize_image(reshaped_image[:,split_point:,:], reshape_to_final = False)
|
||||
split_point = int(reshaped_image.shape[1] / 2)
|
||||
left_frame = resize_image(reshaped_image[:, :split_point, :],
|
||||
reshape_to_final=False)
|
||||
right_frame = resize_image(reshaped_image[:, split_point:, :],
|
||||
reshape_to_final=False)
|
||||
|
||||
left_frame = cv2.cvtColor(left_frame, cv2.COLOR_BGR2RGB)
|
||||
right_frame = cv2.cvtColor(right_frame, cv2.COLOR_BGR2RGB)
|
||||
msg.append({'camera_name': details['cam_name']+'_left', 'frame': left_frame, 'image_timestamp': timestamp})
|
||||
msg.append({'camera_name': details['cam_name']+'_right', 'frame': right_frame, 'image_timestamp': timestamp})
|
||||
msg.append({
|
||||
'camera_name': details['cam_name'] + '_left',
|
||||
'frame': left_frame,
|
||||
'image_timestamp': timestamp
|
||||
})
|
||||
msg.append({
|
||||
'camera_name': details['cam_name'] + '_right',
|
||||
'frame': right_frame,
|
||||
'image_timestamp': timestamp
|
||||
})
|
||||
|
||||
else:
|
||||
frame = resize_image(reshaped_image, reshape_to_final = False)
|
||||
frame = resize_image(reshaped_image, reshape_to_final=False)
|
||||
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||
msg.append({'camera_name': details['cam_name'], 'frame': frame, 'image_timestamp': timestamp})
|
||||
|
||||
msg.append({
|
||||
'camera_name': details['cam_name'],
|
||||
'frame': frame,
|
||||
'image_timestamp': timestamp
|
||||
})
|
||||
|
||||
return msg
|
||||
|
||||
|
||||
|
||||
for cam_name, details in cameras.items():
|
||||
img_array = details['img_array']
|
||||
img_timestamp = details['img_timestamp']
|
||||
with img_array.get_lock(), img_timestamp.get_lock():
|
||||
reshaped_image = np.frombuffer(details['img_array'].get_obj(), dtype=np.uint8).reshape(details['resolution'])
|
||||
timestamp = img_timestamp.value
|
||||
for msg in create_score_message(details, reshaped_image, timestamp):
|
||||
img_scoring_queue.put(msg)
|
||||
|
||||
|
||||
print('Writing for ' + cam_name + f' for {reshaped_image.shape}')
|
||||
# cv2.imwrite('images/'+ cam_name + '.jpg', reshaped_image)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for x in range(img_scoring_queue.qsize()):
|
||||
qu = img_scoring_queue.get()
|
||||
print(qu['camera_name'],qu['frame'].shape)
|
||||
cv2.imwrite(str(x)+'.jpg', qu['frame'])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
qu = img_scoring_queue.get()
|
||||
print(qu['camera_name'], qu['frame'].shape)
|
||||
cv2.imwrite(str(x) + '.jpg', qu['frame'])
|
||||
|
||||
112
utils.py
Normal file
112
utils.py
Normal file
@@ -0,0 +1,112 @@
|
||||
import asyncio
|
||||
import numpy as np
|
||||
import struct
|
||||
import re
|
||||
import pickle
|
||||
import datetime as dt
|
||||
import time
|
||||
import numpy
|
||||
|
||||
|
||||
class StreamManager():
|
||||
def __init__(self, rtsp_url, resolution, camera_name = 'N/A'):
|
||||
self.cam_name = cam_name
|
||||
|
||||
|
||||
self.array_len = np.prod(resolution)
|
||||
self.cam_name = cam_name
|
||||
self.img_array = multiprocessing.Array(ctypes.c_uint8,
|
||||
int(array_len),
|
||||
lock=True)
|
||||
self.img_timestamp = multiprocessing.Value(ctypes.c_double)
|
||||
self.queue = multiprocessing.Queue()
|
||||
self.rtsp_url = format_ffmpeg_decode_url(rtsp_url).split(" ")
|
||||
self.process_func = partial(stream_wrapper,
|
||||
self.resolution,
|
||||
self.rtsp_url,
|
||||
camera_name=cam_name,
|
||||
queue=self.queue,
|
||||
img_array=self.img_array,
|
||||
img_timestamp=self.img_timestamp))
|
||||
|
||||
|
||||
def get_next_bitmap( byte_stream, shape):
|
||||
numel = np.prod(shape)
|
||||
string_find = b'BM' + struct.pack('<I',numel+54)
|
||||
fcf = [m.start() for m in re.finditer(re.escape(string_find), byte_stream)]
|
||||
for start_index in fcf:
|
||||
end_index = start_index + 60+numel
|
||||
frame_data_with_header = byte_stream[start_index:end_index]
|
||||
header = frame_data_with_header[:60]
|
||||
frame = frame_data_with_header[60:]
|
||||
nf = np.frombuffer(frame, dtype=np.uint8)
|
||||
if len(nf) != numel:
|
||||
return None, None
|
||||
pic = np.reshape(nf, shape)
|
||||
pic = pic[::-1,:,:]
|
||||
if len(nf) == numel:
|
||||
return pic
|
||||
|
||||
|
||||
def stream_wrapper( shape, cmd, camera_name = None, queue = None, img_array = None, img_timestamp = None):
|
||||
print('Starting wrapper')
|
||||
func = read_stream( shape, cmd, camera_name = camera_name, queue = queue, img_array = img_array, img_timestamp = img_timestamp)
|
||||
asyncio.run(func)
|
||||
|
||||
|
||||
|
||||
async def read_stream( shape, cmd, camera_name = None, queue = None, img_array = None, img_timestamp = None):
|
||||
print('Starting stream')
|
||||
byte_buffer = b''
|
||||
bytes_read = (np.prod(shape)+60)*2
|
||||
print(cmd)
|
||||
process = await asyncio.create_subprocess_exec(*cmd,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE
|
||||
)
|
||||
try:
|
||||
while True:
|
||||
# Read up to 65KB at a time
|
||||
chunk = await process.stdout.read(bytes_read)
|
||||
byte_buffer += chunk
|
||||
diff = len(byte_buffer) - bytes_read
|
||||
# print(len(byte_buffer))
|
||||
if diff > 0:
|
||||
byte_buffer = byte_buffer[diff::]
|
||||
|
||||
|
||||
if not queue.empty():
|
||||
msg = queue.get_nowait()
|
||||
print('got message! ' + str( msg))
|
||||
if msg == 'exit':
|
||||
return
|
||||
|
||||
if msg == 'get':
|
||||
print('doing get!')
|
||||
frame = get_next_bitmap(byte_buffer, shape)
|
||||
with img_timestamp.get_lock(), img_array.get_lock():
|
||||
if frame is None:
|
||||
print(f"Read empty frame for {camera_name}")
|
||||
img_array[:] = 0
|
||||
img_timestamp.value = 0
|
||||
else:
|
||||
print(f"Read frame for {camera_name} at {dt.datetime.now()}")
|
||||
img_array[:] = frame.flatten()[:]
|
||||
img_timestamp.value = time.time()
|
||||
|
||||
|
||||
except asyncio.CancelledError:
|
||||
print('Cancelled Error')
|
||||
process.kill()
|
||||
await process.wait()
|
||||
|
||||
|
||||
|
||||
|
||||
def format_gst_url(rtsp_url):
|
||||
gst_pipeline = f"rtspsrc location={rtsp_url} latency=50 ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! appsink max-buffers=1 drop=true"
|
||||
return gst_pipeline
|
||||
|
||||
def format_ffmpeg_decode_url(rtsp_url):
|
||||
cmd = f"ffmpeg -rtsp_transport tcp -i {rtsp_url} -f image2pipe -vcodec bmp -an pipe:1"
|
||||
return cmd
|
||||
Reference in New Issue
Block a user