更新ROI相关文件并修改配置

This commit is contained in:
shan 2026-01-07 18:38:19 +08:00
parent 1821dbcced
commit 189bd45223
9 changed files with 126 additions and 613 deletions

View File

@ -1,69 +0,0 @@
# ROI区域过滤验证工具
## 项目结构
```
ROI/
├── roi_filter.py # ROI过滤核心模块
├── validate_roi_setup.py # ROI设置验证工具
├── test_roi_logic.py # ROI逻辑测试
├── test_roi_rtsp.py # RTSP流测试含GUI
└── README.md # 本说明文档
```
## 验证结果
✅ **ROI设置验证成功!**
- 配置文件加载: 正常
- ROI区域定义: 正常 (2个区域)
- 坐标过滤功能: 正常
- RTSP流测试: 正常
## ROI区域配置
当前配置了以下ROI区域
1. **control_lever_area** (控制摇杆区域)
- 坐标范围: (0.10, 0.70) -> (0.30, 0.90)
- 状态: 启用
2. **valve_area** (阀门区域)
- 坐标范围: (0.70, 0.60) -> (0.80, 0.80)
- 状态: 启用
## 使用方法
### 1. 验证ROI设置
```bash
python validate_roi_setup.py
```
### 2. 在d8_5.py中集成ROI过滤
```python
from ROI.roi_filter import ROIManager
# 初始化ROI管理器
roi_manager = ROIManager("../config.yaml")
# 在检测循环中应用过滤
filtered_detections = roi_manager.filter_detections(detections, frame_width, frame_height)
```
### 3. 修改ROI配置
编辑项目根目录下的 `config.yaml` 文件,修改 `roi_filter` 部分:
```yaml
roi_filter:
enabled: true
regions:
- name: "区域名称"
x_min: 0.1 # X坐标最小值 (0-1)
x_max: 0.3 # X坐标最大值 (0-1)
y_min: 0.7 # Y坐标最小值 (0-1)
y_max: 0.9 # Y坐标最大值 (0-1)
description: "区域描述"
enabled: true # 是否启用
```
## 验证说明
- 红色矩形框表示ROI区域
- 在ROI区域内的检测目标将被过滤掉
- 可通过修改配置文件动态调整ROI区域

View File

@ -1,21 +0,0 @@
input:
height: 480
video_path: rtsp://10.0.0.50:8554/camera_test/scene1
width: 640
roi_filter:
enabled: true
regions:
- description: 控制摇杆区域
enabled: true
name: control_lever_area
x_max: 0.3
x_min: 0.1
y_max: 0.9
y_min: 0.7
- description: 阀门区域
enabled: true
name: valve_area
x_max: 0.8
x_min: 0.7
y_max: 0.8
y_min: 0.6

View File

@ -1,77 +0,0 @@
# roi_filter.py
import yaml
import cv2
import numpy as np
class ROIManager:
def __init__(self, config_path="../config.yaml"):
self.config_path = config_path
self.roi_config = self.load_config()
def load_config(self):
try:
with open(self.config_path, 'r', encoding='utf-8') as f:
config = yaml.safe_load(f)
roi_config = config.get('roi_filter', {})
return roi_config
except FileNotFoundError:
print(f"配置文件 {self.config_path} 不存在")
return {"enabled": False, "regions": []}
except yaml.YAMLError as e:
print(f"解析YAML配置文件出错: {e}")
return {"enabled": False, "regions": []}
def is_in_any_roi(self, center_x, center_y):
if not self.roi_config.get('enabled', False):
return False, None
regions = self.roi_config.get('regions', [])
for region in regions:
if (region.get('enabled', True) and
region['x_min'] <= center_x <= region['x_max'] and
region['y_min'] <= center_y <= region['y_max']):
return True, region.get('name', 'unknown')
return False, None
def filter_detections(self, detections, img_width, img_height):
if not self.roi_config.get('enabled', False):
return detections
filtered_detections = []
for det in detections:
center_x = ((det[0] + det[2]) / 2) / img_width
center_y = ((det[1] + det[3]) / 2) / img_height
in_roi, roi_name = self.is_in_any_roi(center_x, center_y)
if not in_roi:
filtered_detections.append(det)
else:
print(f"过滤检测框: 位置({center_x:.2f}, {center_y:.2f}) 在ROI区域 {roi_name}")
return filtered_detections
def draw_roi_regions(self, frame):
if not self.roi_config.get('enabled', False):
return frame
height, width = frame.shape[:2]
regions = self.roi_config.get('regions', [])
frame_with_roi = frame.copy()
for region in regions:
if region.get('enabled', True):
x_min = int(region['x_min'] * width)
x_max = int(region['x_max'] * width)
y_min = int(region['y_min'] * height)
y_max = int(region['y_max'] * height)
cv2.rectangle(frame_with_roi, (x_min, y_min), (x_max, y_max), (0, 0, 255), 2)
cv2.putText(frame_with_roi, region['name'], (x_min, y_min - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)
return frame_with_roi
def draw_roi_on_frame(frame, config_path="../config.yaml"):
roi_manager = ROIManager(config_path)
return roi_manager.draw_roi_regions(frame)

View File

@ -1,110 +0,0 @@
# test_roi_logic.py
import yaml
import numpy as np
from roi_filter import ROIManager
def test_roi_logic():
print("="*50)
print("ROI配置逻辑验证测试")
print("="*50)
# 初始化ROI管理器
roi_manager = ROIManager("../config.yaml")
print(f"✅ ROI配置加载完成")
print(f" ROI过滤启用状态: {roi_manager.roi_config.get('enabled', False)}")
regions = roi_manager.roi_config.get('regions', [])
print(f" 定义的ROI区域数量: {len(regions)}")
for i, region in enumerate(regions):
print(f" 区域 {i+1}: {region.get('name', 'N/A')} - "
f"({region.get('x_min', 0):.2f}, {region.get('y_min', 0):.2f}) 到 "
f"({region.get('x_max', 1):.2f}, {region.get('y_max', 1):.2f})")
print("\n" + "="*50)
print("ROI坐标检测验证")
print("="*50)
# 测试一些坐标点
test_points = [
(0.2, 0.8), # 应该在control_lever_area区域 (如果x_min=0.1, x_max=0.3, y_min=0.7, y_max=0.9)
(0.75, 0.7), # 应该在valve_area区域 (如果x_min=0.7, x_max=0.8, y_min=0.6, y_max=0.8)
(0.5, 0.5), # 应该在非ROI区域
]
for x, y in test_points:
in_roi, roi_name = roi_manager.is_in_any_roi(x, y)
status = "🔴 在ROI区域" if in_roi else "🟢 不在ROI区域"
print(f"坐标 ({x:.2f}, {y:.2f}): {status} {roi_name if in_roi else ''}")
print("\n" + "="*50)
print("ROI过滤功能验证")
print("="*50)
# 模拟检测结果 [x1, y1, x2, y2, conf, class_id]
# 假设图像尺寸为640x480
mock_detections = [
[50, 50, 150, 150, 0.8, 0], # 左上角 (0.08, 0.1) - 不在ROI
[100, 300, 200, 400, 0.9, 0], # 左下角 (0.16, 0.71) - 可能在control_lever_area
[400, 250, 500, 350, 0.7, 0], # 右下角 (0.63, 0.64) - 可能不在ROI
[450, 300, 550, 400, 0.85, 0], # 右下角 (0.7, 0.71) - 可能在valve_area
]
print(f"原始检测数量: {len(mock_detections)}")
filtered_detections = roi_manager.filter_detections(mock_detections, 640, 480)
print(f"过滤后检测数量: {len(filtered_detections)}")
print(f"\n✅ ROI逻辑验证完成")
print(f" - 配置文件加载: {'成功' if roi_manager.roi_config else '失败'}")
print(f" - ROI区域检测: {'正常' if len(regions) > 0 else '无区域定义'}")
print(f" - 坐标过滤功能: {'正常' if True else '异常'}") # 假设总是正常的
return True
def test_roi_with_sample_config():
"""创建并测试示例配置"""
sample_config = {
'roi_filter': {
'enabled': True,
'regions': [
{
'name': 'control_lever_area',
'x_min': 0.1,
'x_max': 0.3,
'y_min': 0.7,
'y_max': 0.9,
'description': '控制摇杆区域',
'enabled': True
},
{
'name': 'valve_area',
'x_min': 0.7,
'x_max': 0.8,
'y_min': 0.6,
'y_max': 0.8,
'description': '阀门区域',
'enabled': True
}
]
}
}
# 保存示例配置
with open('../config.yaml', 'w', encoding='utf-8') as f:
yaml.dump(sample_config, f, default_flow_style=False, allow_unicode=True)
print("✅ 示例配置已创建")
return test_roi_logic()
if __name__ == "__main__":
import os
# 检查配置文件是否存在
config_path = "../config.yaml"
if not os.path.exists(config_path):
print("⚠️ 主配置文件不存在,创建示例配置...")
test_roi_with_sample_config()
else:
test_roi_logic()

View File

@ -1,164 +0,0 @@
# test_roi_rtsp.py
import cv2
import numpy as np
from roi_filter import draw_roi_on_frame
import sys
import os
def test_roi_with_rtsp():
print("="*50)
print("ROI区域RTSP流验证测试")
print("请检查红色矩形框是否出现在RTSP流图像上")
print("'q'退出")
print("="*50)
# RTSP流地址 - 根据您的配置
rtsp_url = "rtsp://10.0.0.50:8554/camera_test/scene1"
# 创建视频捕获对象
cap = cv2.VideoCapture(rtsp_url)
# 设置一些参数以优化RTSP流
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) # 减少缓冲延迟
if not cap.isOpened():
print(f"❌ 无法连接到RTSP流: {rtsp_url}")
print("请检查RTSP流地址是否正确")
return
print(f"✅ 成功连接到RTSP流: {rtsp_url}")
print("等待视频流开始...")
frame_count = 0
while True:
ret, frame = cap.read()
if not ret:
print("❌ 无法读取视频帧可能RTSP流已断开")
break
frame_count += 1
# 应用ROI区域绘制
frame_with_roi = draw_roi_on_frame(frame, "../config.yaml")
# 添加状态信息
status_text = f'Frame: {frame_count} | ROI Test Active'
cv2.putText(frame_with_roi, status_text, (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
cv2.putText(frame_with_roi, 'Press Q to quit', (10, 60),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
# 显示带有ROI的帧
cv2.imshow('ROI RTSP Verification', frame_with_roi)
# 按'q'退出
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 释放资源
cap.release()
cv2.destroyAllWindows()
print("✅ RTSP验证测试结束")
def test_roi_with_rtsp_advanced():
"""
增强版RTSP验证包含更多调试信息
"""
print("="*50)
print("增强版ROI区域RTSP流验证测试")
print("'q'退出,按'r'重新连接")
print("="*50)
rtsp_url = "rtsp://10.0.0.50:8554/camera_test/scene1"
cap = None
reconnect_count = 0
while True:
if cap is None or not cap.isOpened():
print(f"尝试连接RTSP流 (重连次数: {reconnect_count})...")
cap = cv2.VideoCapture(rtsp_url)
# 设置RTSP参数
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
cap.set(cv2.CAP_PROP_FPS, 30)
if not cap.isOpened():
print(f"连接失败等待3秒后重试...")
cv2.waitKey(3000)
reconnect_count += 1
continue
else:
print(f"✅ 成功连接到RTSP流: {rtsp_url}")
reconnect_count = 0
ret, frame = cap.read()
if not ret:
print("⚠️ 视频流断开,尝试重连...")
cap.release()
cap = None
cv2.waitKey(1000)
continue
# 应用ROI区域绘制
frame_with_roi = draw_roi_on_frame(frame, "../config.yaml")
# 添加状态信息
status_text = f'RTSP: Connected | ROI Test | Frame: {cv2.getTickCount() % 10000}'
cv2.putText(frame_with_roi, status_text, (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
cv2.putText(frame_with_roi, 'Press Q to quit, R to reconnect', (10, 60),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
cv2.imshow('Advanced ROI RTSP Test', frame_with_roi)
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
elif key == ord('r'):
print("🔄 手动重连RTSP流...")
cap.release()
cap = None
if cap:
cap.release()
cv2.destroyAllWindows()
print("✅ 增强版RTSP验证测试结束")
if __name__ == "__main__":
# 检查配置文件是否存在
config_path = "../config.yaml"
if not os.path.exists(config_path):
print(f"⚠️ 配置文件 {config_path} 不存在,将创建示例配置")
sample_config = '''roi_filter:
enabled: true
regions:
- name: "control_lever_area"
x_min: 0.1
x_max: 0.3
y_min: 0.7
y_max: 0.9
description: "控制摇杆区域"
enabled: true
- name: "valve_area"
x_min: 0.7
x_max: 0.8
y_min: 0.6
y_max: 0.8
description: "阀门区域"
enabled: true
input:
video_path: "rtsp://10.0.0.50:8554/camera_test/scene1"
width: 640
height: 480'''
with open(config_path, 'w', encoding='utf-8') as f:
f.write(sample_config)
print(f"✅ 已创建示例配置文件: {config_path}")
# 选择测试模式
if len(sys.argv) > 1 and sys.argv[1] == "advanced":
test_roi_with_rtsp_advanced()
else:
test_roi_with_rtsp()

View File

@ -1,172 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
ROI设置验证脚本
用于验证ROI区域配置是否正确设置
"""
import yaml
import numpy as np
import os
import sys
try:
import cv2
OPENCV_AVAILABLE = True
except ImportError:
OPENCV_AVAILABLE = False
print("⚠️ OpenCV未安装将跳过RTSP流测试")
from roi_filter import ROIManager
def print_header(title):
"""打印带分隔符的标题"""
print("="*60)
print(f"{title:^60}")
print("="*60)
def test_config_loading():
"""测试配置文件加载"""
print_header("1. 配置文件加载测试")
roi_manager = ROIManager("../config.yaml")
print(f"✅ ROI配置加载: {'成功' if roi_manager.roi_config else '失败'}")
print(f" ROI过滤启用: {roi_manager.roi_config.get('enabled', False)}")
regions = roi_manager.roi_config.get('regions', [])
print(f" ROI区域数量: {len(regions)}")
if regions:
print(" ROI区域详情:")
for i, region in enumerate(regions):
print(f" {i+1}. {region.get('name', 'N/A')}: "
f"({region.get('x_min', 0):.2f}, {region.get('y_min', 0):.2f}) -> "
f"({region.get('x_max', 1):.2f}, {region.get('y_max', 1):.2f}) "
f"[{'启用' if region.get('enabled', True) else '禁用'}]")
return roi_manager
def test_coordinate_detection(roi_manager):
"""测试坐标检测功能"""
print_header("2. ROI坐标检测测试")
# 测试一些坐标点
test_points = [
(0.2, 0.8), # 应该在control_lever_area区域
(0.75, 0.7), # 应该在valve_area区域
(0.5, 0.5), # 应该在非ROI区域
(0.15, 0.75), # 应该在control_lever_area区域
(0.72, 0.65), # 应该在valve_area区域
]
for x, y in test_points:
in_roi, roi_name = roi_manager.is_in_any_roi(x, y)
status = "🔴 在ROI区域" if in_roi else "🟢 不在ROI区域"
print(f" 坐标 ({x:.2f}, {y:.2f}): {status} {roi_name if in_roi else ''}")
def test_detection_filtering(roi_manager):
"""测试检测结果过滤功能"""
print_header("3. ROI检测过滤功能测试")
# 模拟检测结果 [x1, y1, x2, y2, conf, class_id]
# 假设图像尺寸为640x480
mock_detections = [
[50, 50, 150, 150, 0.8, 0], # 左上角 (0.08, 0.1) - 不在ROI
[100, 300, 200, 400, 0.9, 0], # 左下角 (0.16, 0.71) - 可能在control_lever_area
[400, 250, 500, 350, 0.7, 0], # 右下角 (0.63, 0.64) - 可能不在ROI
[450, 300, 550, 400, 0.85, 0], # 右下角 (0.7, 0.71) - 可能在valve_area
[120, 350, 220, 450, 0.75, 1], # 左下角 (0.19, 0.79) - 可能在control_lever_area
[480, 280, 580, 380, 0.9, 1], # 右下角 (0.75, 0.73) - 可能在valve_area
]
print(f" 原始检测数量: {len(mock_detections)}")
filtered_detections = roi_manager.filter_detections(mock_detections, 640, 480)
print(f" 过滤后检测数量: {len(filtered_detections)}")
print(f" 过滤了 {len(mock_detections) - len(filtered_detections)} 个检测框")
def test_rtsp_verification():
"""测试RTSP流验证如果有OpenCV"""
if not OPENCV_AVAILABLE:
print_header("4. RTSP流验证测试 (跳过)")
print(" ⚠️ OpenCV未安装无法进行RTSP流测试")
return False
print_header("4. RTSP流验证测试")
rtsp_url = "rtsp://10.0.0.50:8554/camera_test/scene1"
print(f" RTSP流地址: {rtsp_url}")
try:
cap = cv2.VideoCapture(rtsp_url)
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
if cap.isOpened():
ret, frame = cap.read()
if ret:
print(" ✅ RTSP流连接成功")
print(f" ✅ 成功获取帧,尺寸: {frame.shape[1]}x{frame.shape[0]}")
# 测试ROI绘制功能
from roi_filter import draw_roi_on_frame
frame_with_roi = draw_roi_on_frame(frame, "../config.yaml")
if frame_with_roi is not None:
print(" ✅ ROI区域绘制功能正常")
print(" 💡 提示: ROI区域会以红色矩形显示")
cap.release()
return True
else:
print(" ❌ 无法读取RTSP流帧")
cap.release()
return False
else:
print(" ❌ 无法连接到RTSP流")
return False
except Exception as e:
print(f" ❌ RTSP流测试出错: {str(e)}")
return False
def main():
"""主函数"""
print_header("🎯 ROI设置验证工具")
print(" 本工具将验证ROI区域配置是否正确设置")
print(" 包括配置加载、坐标检测、过滤功能和RTSP流测试")
# 1. 测试配置文件加载
roi_manager = test_config_loading()
# 2. 测试坐标检测功能
test_coordinate_detection(roi_manager)
# 3. 测试检测过滤功能
test_detection_filtering(roi_manager)
# 4. 测试RTSP流验证
rtsp_success = test_rtsp_verification()
# 总结
print_header("📋 验证总结")
config_loaded = bool(roi_manager.roi_config)
regions_defined = len(roi_manager.roi_config.get('regions', [])) > 0
filtering_works = True # 假设过滤功能正常
print(f" 配置文件加载: {'✅ 正常' if config_loaded else '❌ 异常'}")
print(f" ROI区域定义: {'✅ 正常' if regions_defined else '❌ 未定义'}")
print(f" 坐标过滤功能: {'✅ 正常' if filtering_works else '❌ 异常'}")
print(f" RTSP流测试: {'✅ 正常' if rtsp_success else '❌ 跳过或失败'}")
if config_loaded and regions_defined and filtering_works:
print("\n🎉 ROI设置验证成功!")
print(" 您的ROI区域配置已正确设置可以用于过滤检测结果。")
else:
print("\n❌ ROI设置存在问题请检查配置文件。")
return config_loaded and regions_defined and filtering_works
if __name__ == "__main__":
success = main()
sys.exit(0 if success else 1)

View File

@ -117,3 +117,17 @@ compreface_service:
det_prob_threshold: 0.99
# 识别图像中人脸的个数0代表没有限制。
limit: 0
roi:
#设置ROI区域
ignore_rois:
cam_01:
- [320, 1, 560, 719]
- [620, 1, 860, 719]
cam_02:
- [1, 500, 1000, 520]
cam_03:
- [320, 1, 560, 719]

View File

@ -54,6 +54,7 @@ import uuid
import requests
import json
import datetime
from roi_filter import is_in_ignore_roi, draw_ignore_rois, init_ignore_rois
from compreface import CompreFace
@ -74,6 +75,9 @@ client = Minio(
secure=configData['minioConfig']['secure']
)
# 初始化ROI区域
init_ignore_rois("cam_01")
# 保存token
tokenResult = {}
getTokenUrl = configData['dataConfig']['getTokenUrl']
@ -353,6 +357,10 @@ def plot_one_box(x, img, color=[0, 255, 0], label=None, line_thickness=2):
# 画框
color = [255, 0, 0] # 蓝色BGR
cv2.rectangle(img, c1, c2, color, thickness=line_thickness, lineType=cv2.LINE_AA)
# 画出ROI区域
if is_in_ignore_roi(x):
print("鞋子在 ROI 忽略区域内,跳过检测")
draw_ignore_rois(img) # 调试可视化
return [1, '未穿戴劳保鞋']
if label == 'face':

104
roi_filter.py Normal file
View File

@ -0,0 +1,104 @@
# roi_filter.py
# =========================
# ROI 屏蔽 / 过滤模块
# =========================
import cv2
import yaml
import os
# =========================
# 全局变量(常量风格)
# =========================
CAMERA_ID = None
IGNORE_ROIS = []
# =========================
# 读取配置
# =========================
def load_ignore_rois(camera_id, config_path="config.yaml"):
"""
从配置文件中读取指定摄像头的 ROI 忽略区域
"""
if not os.path.exists(config_path):
print(f"[WARN] config file not found: {config_path}")
return []
with open(config_path, "r", encoding="utf-8") as f:
cfg = yaml.safe_load(f) or {}
return cfg.get("roi", {}).get("ignore_rois", {}).get(camera_id, [])
# =========================
# 初始化(由主程序调用一次)
# =========================
def init_ignore_rois(camera_id, config_path="config.yaml"):
"""
初始化 ROI 忽略区域必须调用
"""
global CAMERA_ID, IGNORE_ROIS
CAMERA_ID = camera_id
IGNORE_ROIS = load_ignore_rois(camera_id, config_path)
print(f"[ROI] camera_id={camera_id}, ignore_rois={IGNORE_ROIS}")
# =========================
# 判断是否在忽略区域
# =========================
def is_in_ignore_roi(bbox, mode="center"):
"""
判断检测框是否需要被屏蔽
:param bbox: (x1, y1, x2, y2)
:param mode:
- center : 中心点判断推荐
- iou : 有交集即忽略
:return: True = 忽略
"""
if not IGNORE_ROIS:
return False
x1, y1, x2, y2 = bbox
if mode == "center":
cx = (x1 + x2) // 2
cy = (y1 + y2) // 2
for rx1, ry1, rx2, ry2 in IGNORE_ROIS:
if rx1 <= cx <= rx2 and ry1 <= cy <= ry2:
return True
return False
if mode == "iou":
for rx1, ry1, rx2, ry2 in IGNORE_ROIS:
ix1 = max(x1, rx1)
iy1 = max(y1, ry1)
ix2 = min(x2, rx2)
iy2 = min(y2, ry2)
if ix1 < ix2 and iy1 < iy2:
return True
return False
return False
# =========================
# 调试:画出忽略区域
# =========================
def draw_ignore_rois(img):
"""
调试用在画面中把 ROI 忽略区域画出来
"""
for x1, y1, x2, y2 in IGNORE_ROIS:
cv2.rectangle(img, (x1, y1), (x2, y2), (128, 128, 128), 2)
cv2.putText(
img,
"IGNORE ROI",
(x1 + 5, y1 + 20),
cv2.FONT_HERSHEY_SIMPLEX,
0.6,
(128, 128, 128),
2
)