Browse Source

update 更新代码版本

master
lucas 3 days ago
parent
commit
b60af972b2
  1. 12
      app.py
  2. 76
      config.json
  3. 45
      config2.json
  4. 61
      configSer.py
  5. 6
      models/msg.py
  6. 57
      models/target.py
  7. 21
      tcp_Ser.py
  8. 6
      test/测试config.py
  9. 58
      test/测试opencv.py
  10. 16
      upload/DataReporter.py
  11. 17
      utils.py
  12. 8
      标靶识别.py
  13. 162
      标靶识别video.py

12
app.py

@ -1,3 +1,5 @@
from time import sleep
import configSer
import tcp_Ser
import upload.DataReporter
@ -11,9 +13,9 @@ if __name__ == '__main__':
json_str = config_obj.config_info.to_json(indent=4)
print(f"当前配置:{json_str}")
tcp_service = tcp_Ser.TcpSer("127.0.0.1", config_obj.config_info.server.port)
tcp_service = tcp_Ser.TcpSer("0.0.0.0", config_obj.config_info.server.port)
tcp_service.start()
reporter = upload.DataReporter.DataReporter()
reporter = upload.DataReporter.DataReporter(data_fps=config_obj.config_info.fps.data,video_fps=config_obj.config_info.fps.video)
reporter.register_handler(tcp_service.broadcast_message)
reporter.start()
# 启动video
@ -22,10 +24,10 @@ if __name__ == '__main__':
# 添加订阅者processor
tcp_service.add_subscribe(processor)
# 启动
processor.video_mode(0)
processor.video_mode(config_obj.config_info.capture)
while True:
sleep(10)
cv2.waitKey(0)
cv2.destroyAllWindows()

76
config.json

@ -2,46 +2,66 @@
"server": {
"port": 2230
},
"capture": 0,
"fps": {
"data": 10,
"video": 0
},
"capture": "0",
"targets": {
"0": {
"info": {
"rectangle_area": {
"x": 50,
"y": 371,
"w": 113,
"h": 91
"y": 230,
"w": 130,
"h": 100
},
"threshold": {
"binary": 120,
"gauss": 5
"binary": 180,
"gauss": 7
},
"radius_pix": 1,
"radius": 20.0,
"pix_length": 0.0,
"id": 0,
"desc": "0_biaoba",
"desc": "0_up",
"base": false
},
"perspective": [
[
1.02,
-0.277155559,
109.207622
],
[
0.0802663708,
1.00426514,
-34.8436318
],
[
3.80200276e-05,
2.664279e-06,
1.0
]
],
"handler_info": {
"radius_pix": 20.0,
"pix_length": 1.0,
"center_point": {
"x": 125.0,
"y": 272.0
},
"center_init": {
"x": 123.5,
"y": 272.0
},
"displacement_pix": {
"x": 1.5,
"y": 0.0
},
"displacement_phy": {
"x": 1.5,
"y": 0.0
}
}
}
},
"perspective": {
"0": [
[
1.02161644,
-0.277155559,
109.207622
],
[
0.0802663708,
1.00426514,
-34.8436318
],
[
3.80200276e-05,
2.664279e-06,
1.0
]
]
}
}

45
config2.json

@ -1,45 +0,0 @@
{
"server": {
"port": 2230
},
"capture": 0,
"targets": {
"0": {
"info": {
"rectangle_area": {
"x": 75,
"y": 310,
"w": 59,
"h": 55
},
"threshold": {
"binary": 128,
"gauss": 9
},
"radius": 20.0,
"id": 0,
"desc": "",
"base": false
}
}
},
"perspective2": {
"0": [
[
1.02161644,
-0.277155559,
109.207622
],
[
0.0802663708,
1.00426514,
-34.8436318
],
[
3.80200276e-05,
2.664279e-06,
1.0
]
]
}
}

61
configSer.py

@ -2,9 +2,9 @@ import json
import os
from dataclasses import (
dataclass,
field, asdict
field
)
from typing import Dict, Optional
from typing import Dict
import numpy as np
from dataclasses_json import dataclass_json
@ -19,15 +19,20 @@ _file_path: str
class Server:
port: int = 0
@dataclass_json
@dataclass
class Fps:
data: int = 0
video: int = 0
@dataclass_json
@dataclass
class ConfigInfo:
server:Server
capture: int = 0
fps:Fps
capture: str = "0"
# 标靶配置
targets: Dict[int, models.target.CircleTarget] = field(default_factory=dict)
# 标靶透视矩阵
perspective: Dict[int, np.ndarray] = field(default_factory=dict)
class ConfigOperate:
_file_path: str
@ -46,29 +51,29 @@ class ConfigOperate:
config = json.load(json_file)
return config
def load2obj_sample2(self):
""""读取配置"""
dic=self.load2dict()
ts = dic["targets"]
capture = dic["capture"]
# 获取矩阵数据
matrix_dict = dic.get("perspective", {})
# n0=convert_to_ndarray(self.matrix_dict["0"])
# 将矩阵转换为字符串
# matrix_str = np.array2string(n0, precision=8, separator=', ', suppress_small=True)
for _,t in ts.items():
obj = models.target.TargetInfo(**t)
area = models.target.RectangleArea.from_dict(obj.rectangle_area)
thres = models.target.Threshold(**obj.threshold)
self.targets[obj.id] = models.target.CircleTarget(
obj.id,
obj.desc,
area,
obj.radius,
thres,
obj.base
)
return self.targets
# def load2obj_sample2(self):
# """"读取配置"""
# dic=self.load2dict()
# ts = dic["targets"]
# capture = dic["capture"]
# # 获取矩阵数据
# matrix_dict = dic.get("perspective", {})
# # n0=convert_to_ndarray(self.matrix_dict["0"])
# # 将矩阵转换为字符串
# # matrix_str = np.array2string(n0, precision=8, separator=', ', suppress_small=True)
# for _,t in ts.items():
# obj = models.target.TargetInfo(**t)
# area = models.target.RectangleArea.from_dict(obj.rectangle_area)
# thres = models.target.Threshold(**obj.threshold)
# self.targets[obj.id] = models.target.CircleTarget(
# obj.id,
# obj.desc,
# area,
# obj.radius,
# thres,
# obj.base
# )
# return self.targets
def load2obj_sample(self):
dic=self.load2dict()

6
models/msg.py

@ -12,14 +12,8 @@ class Msg:
def to_json_(self) -> str:
"""将数据类序列化为 JSON 字符串"""
# return json.dumps(self.__dict__, indent=4, default=lambda x: x.__dict__)
return self.to_json()
# @classmethod
# def from_json(cls, json_str: str) -> 'Msg':
# """从 JSON 字符串反序列化为数据类"""
# data_dict = json.loads(json_str)
# return cls(**data_dict)

57
models/target.py

@ -1,8 +1,11 @@
from dataclasses import dataclass, field
from typing import Optional
from typing import Optional, Dict
import numpy as np
from dataclasses_json import dataclass_json, config
import utils
@dataclass_json
@dataclass
@ -38,10 +41,8 @@ class TargetInfo:
# 标靶方形区域
rectangle_area:RectangleArea
threshold:Threshold
radius_pix:float= 1
# 标靶物理半径
radius:float=0.0
pix_length:float=0.0
id:int =-1
desc:str=""
base:bool=False
@ -57,15 +58,13 @@ class TargetInfo:
def from_dict(cls,data: dict):
return cls(data['id'],data['rectangle_area'],data['radius'])
@dataclass_json
@dataclass
class CircleTarget:
# 标靶方形区域
info:TargetInfo
# 初始标靶中心
class HandlerInfo:
# 初始话
is_init=True
radius_pix:float= 1.0
pix_length:float=0.0
# 标靶中心
center_point: Optional[Point]= field(default=None, metadata=config(exclude=lambda x: x is None))
center_init : Optional[Point]= field(default=None, metadata=config(exclude=lambda x: x is None))
@ -73,25 +72,41 @@ class CircleTarget:
displacement_pix: Optional[Point]= field(default=None, metadata=config(exclude=lambda x: x is None))
displacement_phy: Optional[Point]= field(default=None, metadata=config(exclude=lambda x: x is None))
def __init__(self,info:TargetInfo,center_point,center_init,displacement_pix,displacement_phy):
self.info=info
self.center_point=center_point
self.center_init=center_init
self. displacement_pix=displacement_pix
self.displacement_phy=displacement_phy
@dataclass_json
@dataclass
class CircleTarget:
# 标靶方形区域
info:TargetInfo
# 标靶透视矩阵
perspective: np.ndarray = field(
metadata=config(
encoder=utils.encode_perspective,
decoder=utils.decode_perspective
)
)
handler_info: Optional[HandlerInfo]=None
# def __init__(self,info:TargetInfo,center_point,center_init,displacement_pix,displacement_phy):
# self.info=info
# self.center_point=center_point
# self.center_init=center_init
# self. displacement_pix=displacement_pix
# self.displacement_phy=displacement_phy
@classmethod
def init_by_info(cls,t:TargetInfo):
return CircleTarget(t,None,None,None,None)
def circle_displacement(self):
previous = self.center_init
previous = self.handler_info.center_init
if previous != ():
self.displacement_pix = Point(self.center_point.x - previous.x, self.center_point.y - previous.y)
self.handler_info.displacement_pix = Point(self.handler_info.center_point.x - previous.x,
self.handler_info.center_point.y - previous.y)
if self.info.radius != 0:
# 单位像素距离
self.info.pix_length = self.info.radius / self.info.radius_pix
offset_x = round(float(self.displacement_pix.x * self.info.pix_length), 5)
offset_y = round(float(self.displacement_pix.y * self.info.pix_length), 5)
self.displacement_phy = Point(offset_x, offset_y)
self.handler_info.pix_length = self.info.radius / self.handler_info.radius_pix
offset_x = round(float(self.handler_info.displacement_pix.x * self.handler_info.pix_length), 5)
offset_y = round(float(self.handler_info.displacement_pix.y * self.handler_info.pix_length), 5)
self.handler_info.displacement_phy = Point(offset_x, offset_y)
return self

21
tcp_Ser.py

@ -28,20 +28,30 @@ class TcpSer(threading.Thread):
# 保持连接,直到客户端断开
while True:
# 接收客户端数据(如果需要)
data = client_socket.recv(1024)
data = client_socket.recv(4096)
msg_str=data.decode('utf-8')
if not data:
break # 如果没有数据,退出循环
print(f"{client_socket.getpeername()} 收到: {msg_str}")
# 反序列化为 实例
s_cmd = Msg.from_json(msg_str)
valid_msg:bool=True
match s_cmd.cmd:
case "getPoints" | "setPoints":
self.on_data(s_cmd)
self.on_data(s_cmd,valid_msg)
case "videoFps"| "dataFps":
self.on_data(s_cmd,valid_msg)
case "setCap":
self.on_data(s_cmd,valid_msg)
# todo 添加处理
case "xxxxx":
self.on_data(s_cmd)
case _:
valid_msg = False
err_msg=f"valid cmd={s_cmd.cmd}"
resp=f"""{{"_from": "dev","cmd": "{s_cmd.cmd}","values": {{"operate": false,"err": "{err_msg}"}}}}"""
client_socket.sendall(resp.encode())
print("非法命令",resp)
print("通讯完成")
except Exception as e:
print(f"处理客户端时出错: {e}")
finally:
@ -58,7 +68,7 @@ class TcpSer(threading.Thread):
self.consumers.append(consumer)
else:
print("consumer 缺少on_data函数,订阅无效 ")
def on_data(self,msg):
def on_data(self,msg,valid):
for consumer in self.consumers:
try:
resp=consumer.on_data(msg)
@ -72,6 +82,7 @@ class TcpSer(threading.Thread):
if len(message)==0:
return
message+="\n\n"
for client in self.connected_clients:
try:
client.sendall(message.encode())

6
test/测试config.py

@ -6,11 +6,11 @@ import configSer
def test_load_config():
config_path = "../config.json"
# 读取配置文件
config = configSer.ConfigOperate(config_path)
config: configSer.ConfigOperate = configSer.ConfigOperate(config_path)
json_str2 = config.config_info.to_json(indent=4)
print("json=",json_str2)
config_dict = asdict(config)
config.capture=1
# 测试修改相机id
config.config_info.capture=1
config.save2json_file()
# 更新配置文件
updates = {

58
test/测试opencv.py

@ -1,4 +1,5 @@
import logging
from time import sleep
import cv2
print(cv2.__version__)
@ -6,33 +7,58 @@ def open_video(video_id):
cap = cv2.VideoCapture(video_id)
if not cap.isOpened():
logging.info("无法打开摄像头")
exit()
return cap
class VideoProcessor:
capture: cv2.VideoCapture
rtsp_url ="rtsp://admin:123456abc@192.168.1.64:554/h264/ch1/main/av_stream"
capture = open_video(rtsp_url)
fps = capture.get(cv2.CAP_PROP_FPS)
width = int(capture.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
print("开始读取2")
capture=open_video(2)
vp = VideoProcessor()
vp.capture = capture
fps = vp.capture .get(cv2.CAP_PROP_FPS)
width = int(vp.capture .get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(vp.capture .get(cv2.CAP_PROP_FRAME_HEIGHT))
print(f"fps={fps}")
print("width={width}, height={height}".format(width=width, height=height))
# 定义视频编码器和输出文件
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('output.mp4', fourcc, fps, (width, height))
# 读取一帧图像
cv2.namedWindow('frame')
i = 0
while True:
ret, frame = capture.read()
print("-->")
ret, frame = vp.capture .read()
if ret:
print("-->")
cv2.imshow("frame", frame)
i=i+1
if i>10:
break
# 写入帧到输出文件
# out.write(frame)
else:
logging.info("无法读取图像帧")
break
if cv2.waitKey(1) & 0xFF == ord('q'): # 按'q'退出循环
break
print("释放2")
vp.capture.release()
cv2.destroyAllWindows()
print("开始读取0")
sleep(2)
vp.capture = open_video(0)
# # 定义视频编 = open_video(0)码器和输出文件
# fourcc = cv2.VideoWriter_fourcc(*'mp4v')
# out = cv2.VideoWriter('output.mp4', fourcc, fps, (width, height))
while True:
ret, frame = vp.capture .read()
if ret:
cv2.imshow("frame", frame)
# 写入帧到输出文件
out.write(frame)
# out.write(frame)
else:
logging.info("无法读取帧")
logging.info("无法读取图像")
if cv2.waitKey(1) & 0xFF == ord('q'): # 按'q'退出循环
break
capture.release()
out.release()
vp.capture.release()
# out.release()

16
upload/DataReporter.py

@ -8,12 +8,12 @@ from upload.RateLimiter import RateLimiter
class DataReporter(threading.Thread):
call_back=None
def __init__(self,):
def __init__(self,data_fps:int,video_fps:int):
super().__init__()
self.image_queue = queue.Queue(maxsize=10) # 图片队列
self.data_queue = queue.Queue(maxsize=50) # 数据队列
self.image_limiter = RateLimiter(max_rate=1, time_window=1) # 图片限速: 5张/秒
self.data_limiter = RateLimiter(max_rate=1, time_window=1) # 数据限速: 20条/秒
self.image_queue = queue.Queue(maxsize=video_fps) # 图片队列
self.data_queue = queue.Queue(maxsize=data_fps) # 数据队列
self.image_limiter = RateLimiter(max_rate=video_fps, time_window=1) # 图片限速: 5张/秒
self.data_limiter = RateLimiter(max_rate=data_fps, time_window=1) # 数据限速: 20条/秒
self.running = True
self.image_dropped = 0 # 统计丢弃的图片数量
self.data_dropped = 0 # 统计丢弃的数据数量
@ -27,7 +27,7 @@ class DataReporter(threading.Thread):
if not self.image_queue.empty() and self.image_limiter.allow_request():
try:
image_data = self.image_queue.get_nowait()
# self._report_image(image_data)
self._report_image(image_data)
except queue.Empty:
pass
@ -66,6 +66,8 @@ class DataReporter(threading.Thread):
if data_type == 'image':
with self.image_limiter.lock:
self.image_limiter.max_rate = new_rate
self.image_queue= queue.Queue(maxsize=new_rate)
else:
with self.data_limiter.lock:
self.data_limiter.max_rate = new_rate
self.data_limiter.max_rate = new_rate
self.data_queue = queue.Queue(maxsize=new_rate)

17
utils.py

@ -1,5 +1,11 @@
from typing import Dict, List
import cv2
import base64
import numpy as np
def frame_to_base64(frame, format="JPEG"):
"""将 OpenCV 读取的图片帧转换为 Base64 编码的字符串"""
# 将图片帧编码为 JPEG 或 PNG 格式
@ -16,4 +22,13 @@ def frame_to_base64(frame, format="JPEG"):
# 将编码后的字节流转换为 Base64 字符串
base64_string = base64.b64encode(encoded_frame).decode("utf-8")
return base64_string
return base64_string
# 自定义编码器和解码器
def encode_perspective(value: np.ndarray) -> List[List[float]]:
return value.tolist()
def decode_perspective(value: List[List[float]]) -> np.ndarray:
return np.array(value)

8
标靶识别.py

@ -230,7 +230,9 @@ def image_mode():
show_image(img_raw)
def rtsp_mode():
rtsp_url ="rtsp://admin:123456abc@192.168.1.64:554"
# rtsp_url ="rtsp://admin:123456abc@192.168.1.64:554"
rtsp_url ="rtsp://localhost:8554/rtsp"
capture = open_video(rtsp_url)
fps = capture.get(cv2.CAP_PROP_FPS)
print(f"fps={fps}")
@ -242,8 +244,8 @@ def rtsp_mode():
if __name__ == '__main__':
signal.signal(signal.SIGINT, check_exit)
# rtsp_mode()
video_mode(0)
rtsp_mode()
# video_mode(0)
# image_mode()
cv2.waitKey(0)

162
标靶识别video.py

@ -1,20 +1,17 @@
import gc
from datetime import datetime
import json
import queue
import time
from time import sleep
from dataclasses import asdict
import cv2
import numpy as np
import signal
import sys
import threading
import logging
import configSer
import models.target
import models.sampleMsg
import tcp_Ser
import upload.DataReporter
import utils
from models.msg import Msg
@ -59,9 +56,9 @@ def add_rectangle(event, x, y, flags, param):
"test add",
area,
radius,
models.target.Threshold(128,9),
models.target.Threshold(190,9),
False)
new_target = models.target.CircleTarget(t_info,None,None,None,None)
new_target = models.target.CircleTarget(t_info,None,None)
logging.info(f"新增区域[{target_id}] => {start_point, end_point}")
configObj.config_info.targets[target_id] = new_target
@ -69,7 +66,8 @@ def read_target_rectangle():
return configObj.config_info.targets
class VideoProcessor:
reporter: upload.DataReporter.DataReporter
capture: cv2.VideoCapture
is_opened: bool= False
def __init__(self, reporter:upload.DataReporter.DataReporter):
self.reporter = reporter
@ -78,33 +76,56 @@ class VideoProcessor:
logging.info(f"msg={msg}")
match msg.cmd:
case "getPoints":
data_dict = {k: asdict(v.info) for k, v in configObj.config_info.targets.items()}
resp_msg = models.msg.Msg(_from="dev", cmd="getPoints", values={"targets": data_dict})
targets=configObj.config_info.targets.copy()
for k,v in targets.items():
targets[k].handler_info=None
resp_msg = models.msg.Msg(_from="dev", cmd="getPoints", values={"targets": targets})
resp_json = resp_msg.to_json_()
return resp_json
case "setPoints":
v=msg.values
ts=v["targets"]
# 清空原配置
configObj.config_info.targets={}
# # 清空原配置
# configObj.config_info.targets={}
for _,t in ts.items():
t_str=json.dumps(t)
t_info = models.target.TargetInfo.from_json(t_str)
c_target=models.target.CircleTarget.init_by_info(t_info)
configObj.config_info.targets[c_target.info.id] =c_target
new_c_target = models.target.CircleTarget.from_json(t_str)
configObj.config_info.targets[new_c_target.info.id] =new_c_target
configObj.save2json_file()
resp_msg = models.msg.Msg(_from="dev", cmd="setPoints", values={"operate": True})
resp_json = resp_msg.to_json()
return resp_json
case "videoFps":
v = msg.values
fps = v["fps"]
self.reporter.adjust_rate(fps,"image")
configObj.config_info.fps.video = fps
configObj.save2json_file()
resp_msg = models.msg.Msg(_from="dev", cmd="setPoints", values={"operate": True})
resp_json = resp_msg.to_json()
return resp_json
case "dataFps":
v = msg.values
fps = v["fps"]
self.reporter.adjust_rate(fps,"data")
configObj.config_info.fps.data=fps
configObj.save2json_file()
resp_msg = models.msg.Msg(_from="dev", cmd="setPoints", values={"operate": True})
resp_json = resp_msg.to_json()
return resp_json
case "setCap":
v = msg.values
cap = v["cap"]
self.switch_video(cap)
resp_msg = models.msg.Msg(_from="dev", cmd="setPoints", values={"operate": True})
resp_json = resp_msg.to_json()
return resp_json
print("==")
def update_thresh_binary(self,v:int):
self.thresh_binary = v
def pre_handler_img(self,gray_frame,now_str:str):
# 将灰度图压缩为 JPEG 格式,并存储到内存缓冲区
img_base64 = utils.frame_to_base64(gray_frame, format="JPEG")
@ -139,7 +160,7 @@ class VideoProcessor:
ret, sub_binary_frame = cv2.threshold(sub_image, tr.info.threshold.binary, 255, cv2.THRESH_BINARY)
# 高斯滤波
sub_binary_frame = cv2.GaussianBlur(sub_binary_frame, (tr.info.threshold.gauss, tr.info.threshold.gauss), 1)
sub_binary_frame = cv2.GaussianBlur(sub_binary_frame, (tr.info.threshold.gauss, tr.info.threshold.gauss), 10,borderType=cv2.BORDER_REPLICATE)
cv2.imshow(f'{tr.info.id}_binaryImg', sub_binary_frame)
# 覆盖原图
@ -149,30 +170,29 @@ class VideoProcessor:
circles = self.circle2_detect(sub_binary_frame)
if len(circles) == 0:
continue
center,radius=self.circle_show(img,circles,_start_point)
center,radius_pix=self.circle_show(img,circles,_start_point)
# 纪录圆心位置
tr.center_point=center
tr.radius_pix=radius
if tr.is_init:
tr.center_init=tr.center_point
tr.is_init=False
if tr.handler_info is None:
tr.handler_info= models.target.HandlerInfo()
if tr.handler_info.is_init:
tr.handler_info.is_init=False
tr.handler_info.center_init = center
tr.handler_info.center_point=center
tr.handler_info.radius_pix=radius_pix
tr.circle_displacement()
all_upload_data.data.append(
models.sampleMsg.SensorData(
str(tr.info.id),
tr.displacement_phy.x,
tr.displacement_phy.y)
tr.handler_info.displacement_phy.x,
tr.handler_info.displacement_phy.y)
)
#过滤无效空数据
if len(all_upload_data.data)==0:
return
# json_str = json.dumps(
# {k:asdict(v) for k, v in once_upload.items() if v.is_init==False}
# )
# print(f"标靶数据={json_str}",json_str)
self.enqueue_data(all_upload_data)
@ -235,30 +255,58 @@ class VideoProcessor:
def open_video(self,video_id):
cap = cv2.VideoCapture(video_id)
# cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1600) # 宽度
# cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 900) # 高度
if not cap.isOpened():
logging.info("无法打开摄像头")
exit()
return cap
print(f"打开摄像头 -> {video_id}")
self.capture = cv2.VideoCapture(video_id)
frame_width = int(self.capture.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(self.capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
print(f"默认分辨率= {frame_width}*{frame_height}")
logging.info(f"{video_id}地址->{self.capture}")
fps = self.capture.get(cv2.CAP_PROP_FPS)
print(f"fps={fps},video_id={video_id},")
# self.capture.set(cv2.CAP_PROP_FRAME_WIDTH, 1600) # 宽度
# self.capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 900) # 高度
if not self.capture.isOpened():
self.capture.release()
logging.info(f"无法打开摄像头{video_id},release 地址 -> {self.capture}")
return
self.is_opened=True
def switch_video(self,video_id:str):
print(f"切换摄像头 -> {video_id}")
self.is_opened = False
self.capture.release()
cv2.destroyAllWindows()
if str.isdigit(video_id):
video_id=int(video_id)
self.open_video(video_id)
def show_video(self,cap):
def show_video(self):
global sigExit,start_point, end_point, drawing
cv2.namedWindow('Frame')
cv2.setMouseCallback('Frame', add_rectangle)
# 读取一帧图像
while True:
ret, frame = cap.read()
if not self.is_opened:
print(f"摄像头 标记is_opened={self.is_opened}")
sleep(5)
continue
ret, frame = self.capture.read()
if ret:
self.frame_handle(frame)
else:
logging.info("无法读取帧")
logging.info(f"无法读取帧,cap地址- >{self.capture}")
sleep(1)
# self.capture.release()
# self.capture= cv2.VideoCapture(0) # 再次尝试
if cv2.waitKey(1) & 0xFF == ord('q'): # 按'q'退出循环
break
if sigExit:
break
# 显示图像
if frame is not None:
cv2.imshow('Frame', frame)
def show_image(self,frame):
global start_point, end_point, drawing
cv2.namedWindow('Frame')
@ -279,8 +327,6 @@ class VideoProcessor:
if drawing:
cv2.rectangle(frame, tuple(start_point), tuple(end_point), (0, 200, 200), 4)
# print(f"鼠标位置 {start_point} -> {end_point}")
# 显示图像
cv2.imshow('Frame', frame)
# 读取图像
#img_copy = img.copy() # 复制图像用于还原
@ -292,24 +338,26 @@ class VideoProcessor:
self.show_image(img_raw)
# 支持
def video_mode(self,video_id):
capture = self.open_video(video_id)
fps = capture.get(cv2.CAP_PROP_FPS)
print(f"fps={fps}")
self.show_video(capture)
def video_mode(self,video_id:str):
if str.isdigit(video_id):
video_id=int(video_id)
self.open_video(video_id)
# if self.is_opened:
self.show_video()
# 释放摄像头资源并关闭所有窗口
capture.release()
print("退出 video")
self.capture.release()
cv2.destroyAllWindows()
def rtsp_mode(self,rtsp_url:str):
# rtsp_url ="rtsp://admin:123456abc@192.168.1.64:554"
# rtsp_url ="rtsp://admin:123456abc@192.168.1.64:554/h264/ch1/main/av_stream"
capture = self.open_video(rtsp_url)
fps = capture.get(cv2.CAP_PROP_FPS)
print(f"fps={fps}")
self.show_video(capture)
self.open_video(rtsp_url)
fps = self.capture.get(cv2.CAP_PROP_FPS)
print(f"rtsp fps={fps}")
self.show_video()
# 释放摄像头资源并关闭所有窗口
capture.release()
self.capture.release()
cv2.destroyAllWindows()
def enqueue_data(self,data):
@ -321,7 +369,8 @@ class VideoProcessor:
try:
self.reporter.data_queue.put((dt, data), block=False)
except queue.Full:
self.reporter.data_dropped += 1
# self.reporter.data_dropped += 1
pass
def enqueue_image(self,data):
# 获取当前时间戳
timestamp = time.time()
@ -331,7 +380,8 @@ class VideoProcessor:
try:
self.reporter.image_queue.put((dt, data), block=False)
except queue.Full:
self.reporter.image_dropped += 1
pass
#self.reporter.image_dropped += 1
#数据广播
def check_exit(sig, frame):

Loading…
Cancel
Save