|
|
@@ -178,15 +178,28 @@ class OCRLayoutManager:
|
|
|
st.error(f"❌ 图像加载失败: {e}")
|
|
|
return None
|
|
|
|
|
|
- def render_content_by_mode(self, content: str, render_mode: str, font_size: int, container_height: int, layout_type: str):
|
|
|
- """根据渲染模式显示内容 - 增强版本"""
|
|
|
+ def render_content_by_mode(self, content: str, render_mode: str, font_size: int,
|
|
|
+ container_height: int, layout_type: str,
|
|
|
+ highlight_config: Optional[Dict] = None):
|
|
|
+ """
|
|
|
+ 根据渲染模式显示内容 - 增强版本
|
|
|
+
|
|
|
+ Args:
|
|
|
+ content: 要渲染的内容
|
|
|
+ render_mode: 渲染模式
|
|
|
+ font_size: 字体大小
|
|
|
+ container_height: 容器高度
|
|
|
+ layout_type: 布局类型
|
|
|
+ highlight_config: 高亮配置 {'has_bbox': bool, 'match_type': str}
|
|
|
+ """
|
|
|
if content is None or render_mode is None:
|
|
|
return
|
|
|
|
|
|
if render_mode == "HTML渲染":
|
|
|
- # 增强的HTML渲染样式,支持横向滚动
|
|
|
+ # 🎯 构建样式 - 包含基础样式和高亮样式
|
|
|
content_style = f"""
|
|
|
<style>
|
|
|
+ /* ========== 基础容器样式 ========== */
|
|
|
.{layout_type}-content-display {{
|
|
|
height: {container_height}px;
|
|
|
overflow-x: auto;
|
|
|
@@ -201,12 +214,12 @@ class OCRLayoutManager:
|
|
|
max-width: 100%;
|
|
|
}}
|
|
|
|
|
|
+ /* ========== 表格样式 ========== */
|
|
|
.{layout_type}-content-display table {{
|
|
|
- width: 100%; /* 修改:从100%改为auto,让表格自适应内容 */
|
|
|
+ width: 100%;
|
|
|
border-collapse: collapse;
|
|
|
margin: 10px 0;
|
|
|
- white-space: nowrap; /* 修改:允许文字换行 */
|
|
|
- /* table-layout: auto; *? /* 新增:自动表格布局 */
|
|
|
+ white-space: nowrap;
|
|
|
}}
|
|
|
|
|
|
.{layout_type}-content-display th,
|
|
|
@@ -214,11 +227,10 @@ class OCRLayoutManager:
|
|
|
border: 1px solid #ddd;
|
|
|
padding: 8px;
|
|
|
text-align: left;
|
|
|
- /* 移除:min-width固定限制 */
|
|
|
- max-width: 300px; /* 新增:设置最大宽度避免过宽 */
|
|
|
- word-wrap: break-word; /* 新增:长单词自动换行 */
|
|
|
- word-break: break-all; /* 新增:允许在任意字符间换行 */
|
|
|
- vertical-align: top; /* 新增:顶部对齐 */
|
|
|
+ max-width: 300px;
|
|
|
+ word-wrap: break-word;
|
|
|
+ word-break: break-all;
|
|
|
+ vertical-align: top;
|
|
|
}}
|
|
|
|
|
|
.{layout_type}-content-display th {{
|
|
|
@@ -226,30 +238,31 @@ class OCRLayoutManager:
|
|
|
position: sticky;
|
|
|
top: 0;
|
|
|
z-index: 1;
|
|
|
- font-weight: bold; /* 新增:表头加粗 */
|
|
|
+ font-weight: bold;
|
|
|
}}
|
|
|
|
|
|
- /* 新增:针对数字列的特殊处理 */
|
|
|
+ /* 数字列右对齐 */
|
|
|
.{layout_type}-content-display td.number {{
|
|
|
text-align: right;
|
|
|
white-space: nowrap;
|
|
|
font-family: 'Monaco', 'Menlo', monospace;
|
|
|
}}
|
|
|
|
|
|
- /* 新增:针对短文本列的处理 */
|
|
|
+ /* 短文本列不换行 */
|
|
|
.{layout_type}-content-display td.short-text {{
|
|
|
white-space: nowrap;
|
|
|
min-width: 80px;
|
|
|
}}
|
|
|
|
|
|
+ /* ========== 图片样式 ========== */
|
|
|
.{layout_type}-content-display img {{
|
|
|
max-width: 100%;
|
|
|
height: auto;
|
|
|
border-radius: 4px;
|
|
|
margin: 10px 0;
|
|
|
}}
|
|
|
-
|
|
|
- /* 新增:响应式表格 */
|
|
|
+
|
|
|
+ /* ========== 响应式设计 ========== */
|
|
|
@media (max-width: 768px) {{
|
|
|
.{layout_type}-content-display table {{
|
|
|
font-size: {max(font_size-2, 8)}px;
|
|
|
@@ -260,23 +273,54 @@ class OCRLayoutManager:
|
|
|
max-width: 150px;
|
|
|
}}
|
|
|
}}
|
|
|
-
|
|
|
- .highlight-text {{
|
|
|
- background-color: #ffeb3b !important;
|
|
|
+
|
|
|
+ /* ========== 高亮文本样式 ========== */
|
|
|
+ .{layout_type}-content-display .highlight-text {{
|
|
|
padding: 2px 4px;
|
|
|
border-radius: 3px;
|
|
|
cursor: pointer;
|
|
|
- color: #333333 !important;
|
|
|
+ font-weight: 500;
|
|
|
+ transition: all 0.2s ease;
|
|
|
+ }}
|
|
|
+
|
|
|
+ .{layout_type}-content-display .highlight-text:hover {{
|
|
|
+ opacity: 0.8;
|
|
|
+ transform: scale(1.02);
|
|
|
}}
|
|
|
|
|
|
- .selected-highlight {{
|
|
|
+ /* 🎯 精确匹配且有框 - 绿色 */
|
|
|
+ .{layout_type}-content-display .highlight-text.selected-highlight {{
|
|
|
background-color: #4caf50 !important;
|
|
|
color: white !important;
|
|
|
+ border: 1px solid #2e7d32 !important;
|
|
|
+ }}
|
|
|
+
|
|
|
+ /* 🎯 OCR匹配 - 蓝色 */
|
|
|
+ .{layout_type}-content-display .highlight-text.ocr-match {{
|
|
|
+ background-color: #2196f3 !important;
|
|
|
+ color: white !important;
|
|
|
+ border: 1px solid #1565c0 !important;
|
|
|
+ }}
|
|
|
+
|
|
|
+ /* 🎯 无边界框 - 橙色虚线 */
|
|
|
+ .{layout_type}-content-display .highlight-text.no-bbox {{
|
|
|
+ background-color: #ff9800 !important;
|
|
|
+ color: white !important;
|
|
|
+ border: 1px dashed #f57c00 !important;
|
|
|
+ }}
|
|
|
+
|
|
|
+ /* 🎯 默认高亮 - 黄色 */
|
|
|
+ .{layout_type}-content-display .highlight-text.default {{
|
|
|
+ background-color: #ffeb3b !important;
|
|
|
+ color: #333333 !important;
|
|
|
+ border: 1px solid #fbc02d !important;
|
|
|
}}
|
|
|
</style>
|
|
|
"""
|
|
|
+
|
|
|
st.markdown(content_style, unsafe_allow_html=True)
|
|
|
- st.markdown(f'<div class="{layout_type}-content-display">{content}</div>', unsafe_allow_html=True)
|
|
|
+ st.markdown(f'<div class="{layout_type}-content-display">{content}</div>',
|
|
|
+ unsafe_allow_html=True)
|
|
|
|
|
|
elif render_mode == "Markdown渲染":
|
|
|
converted_content = convert_html_table_to_markdown(content)
|
|
|
@@ -296,26 +340,25 @@ class OCRLayoutManager:
|
|
|
key=f"{layout_type}_text_area"
|
|
|
)
|
|
|
|
|
|
+
|
|
|
def create_compact_layout(self, config: Dict):
|
|
|
- """创建紧凑的对比布局"""
|
|
|
- # 主要内容区域
|
|
|
+ """创建紧凑的对比布局 - 增强搜索功能"""
|
|
|
layout = config['styles']['layout']
|
|
|
font_size = config['styles'].get('font_size', 10)
|
|
|
container_height = layout.get('default_height', 600)
|
|
|
zoom_level = layout.get('default_zoom', 1.0)
|
|
|
layout_type = "compact"
|
|
|
|
|
|
- left_col, right_col = st.columns([layout['content_width'], layout['sidebar_width']], vertical_alignment='top', border=True)
|
|
|
+ left_col, right_col = st.columns([layout['content_width'], layout['sidebar_width']],
|
|
|
+ vertical_alignment='top', border=True)
|
|
|
|
|
|
with left_col:
|
|
|
- # 快速定位文本选择器 - 增强版(搜索+下拉)
|
|
|
if self.validator.text_bbox_mapping:
|
|
|
# 搜索输入框
|
|
|
search_col, select_col = st.columns([1, 2])
|
|
|
|
|
|
- # 初始化session state
|
|
|
if "compact_search_query" not in st.session_state:
|
|
|
- st.session_state.compact_search_query = None
|
|
|
+ st.session_state.compact_search_query = ""
|
|
|
|
|
|
with search_col:
|
|
|
search_query = st.text_input(
|
|
|
@@ -325,38 +368,89 @@ class OCRLayoutManager:
|
|
|
key=f"{layout_type}_search_input",
|
|
|
label_visibility="collapsed"
|
|
|
)
|
|
|
- # 更新session state
|
|
|
st.session_state.compact_search_query = search_query
|
|
|
|
|
|
- # 构建选项列表
|
|
|
+ # 🎯 增强搜索逻辑:构建选项列表
|
|
|
text_options = ["请选择文本..."]
|
|
|
text_display = ["请选择文本..."]
|
|
|
+ match_info = [None] # 记录匹配信息
|
|
|
|
|
|
for text, info_list in self.validator.text_bbox_mapping.items():
|
|
|
- # 如果有搜索条件,进行过滤
|
|
|
+ # 🔑 关键改进:同时搜索 text 和 matched_text
|
|
|
if search_query and search_query.strip():
|
|
|
- if search_query.lower() not in text.lower():
|
|
|
- continue # 跳过不匹配的项
|
|
|
+ query_lower = search_query.lower()
|
|
|
+
|
|
|
+ # 1. 检查原始文本
|
|
|
+ text_match = query_lower in text.lower()
|
|
|
+
|
|
|
+ # 2. 检查 matched_text(OCR识别文本)
|
|
|
+ matched_text_match = False
|
|
|
+ matched_text = None
|
|
|
+ if info_list and isinstance(info_list[0], dict):
|
|
|
+ matched_text = info_list[0].get('matched_text', '')
|
|
|
+ matched_text_match = query_lower in matched_text.lower() if matched_text else False
|
|
|
+
|
|
|
+ # 如果都不匹配,跳过
|
|
|
+ if not text_match and not matched_text_match:
|
|
|
+ continue
|
|
|
+
|
|
|
+ # 记录匹配类型
|
|
|
+ if text_match:
|
|
|
+ match_type = "exact"
|
|
|
+ match_source = text
|
|
|
+ else:
|
|
|
+ match_type = "ocr"
|
|
|
+ match_source = matched_text
|
|
|
+ else:
|
|
|
+ match_type = None
|
|
|
+ match_source = text
|
|
|
|
|
|
text_options.append(text)
|
|
|
|
|
|
- # 检查是否是表格单元格
|
|
|
+ # 🎯 构建显示文本(带匹配提示)
|
|
|
if info_list and isinstance(info_list[0], dict):
|
|
|
first_info = info_list[0]
|
|
|
+
|
|
|
+ # 检查是否有 bbox
|
|
|
+ has_bbox = 'bbox' in first_info and first_info['bbox']
|
|
|
+
|
|
|
+ # 表格单元格显示
|
|
|
if 'row' in first_info and 'col' in first_info:
|
|
|
display_text = f"[R{first_info['row']},C{first_info['col']}] {text}"
|
|
|
- if len(display_text) > 47:
|
|
|
- display_text = display_text[:44] + "..."
|
|
|
else:
|
|
|
- display_text = text[:47] + "..." if len(text) > 50 else text
|
|
|
- else:
|
|
|
- display_text = text[:47] + "..." if len(text) > 50 else text
|
|
|
+ display_text = text
|
|
|
+
|
|
|
+ # 🎯 添加匹配提示
|
|
|
+ if match_type == "ocr":
|
|
|
+ display_text = f"🔍 {display_text} (OCR: {match_source[:20]}...)"
|
|
|
+ elif not has_bbox:
|
|
|
+ display_text = f"⚠️ {display_text} (无框)"
|
|
|
|
|
|
+ # 截断过长文本
|
|
|
+ if len(display_text) > 60:
|
|
|
+ display_text = display_text[:57] + "..."
|
|
|
+ else:
|
|
|
+ display_text = text[:57] + "..." if len(text) > 60 else text
|
|
|
+
|
|
|
text_display.append(display_text)
|
|
|
+ match_info.append({
|
|
|
+ 'type': match_type,
|
|
|
+ 'source': match_source,
|
|
|
+ 'has_bbox': has_bbox if info_list else False
|
|
|
+ })
|
|
|
|
|
|
- # 显示匹配数量
|
|
|
+ # 🎯 显示搜索统计
|
|
|
if search_query and search_query.strip():
|
|
|
- st.caption(f"找到 {len(text_options)-1} 个匹配项")
|
|
|
+ ocr_matches = sum(1 for m in match_info[1:] if m and m['type'] == 'ocr')
|
|
|
+ no_bbox_count = sum(1 for m in match_info[1:] if m and not m['has_bbox'])
|
|
|
+
|
|
|
+ stat_parts = [f"找到 {len(text_options)-1} 个匹配项"]
|
|
|
+ if ocr_matches > 0:
|
|
|
+ stat_parts.append(f"🔍 {ocr_matches} 个OCR匹配")
|
|
|
+ if no_bbox_count > 0:
|
|
|
+ stat_parts.append(f"⚠️ {no_bbox_count} 个无框")
|
|
|
+
|
|
|
+ st.caption(" | ".join(stat_parts))
|
|
|
|
|
|
# 确定默认选中的索引
|
|
|
default_index = 0
|
|
|
@@ -373,28 +467,78 @@ class OCRLayoutManager:
|
|
|
key=f"{layout_type}_quick_text_selector"
|
|
|
)
|
|
|
|
|
|
+ # 🎯 显示匹配详情
|
|
|
if selected_index > 0:
|
|
|
st.session_state.selected_text = text_options[selected_index]
|
|
|
-
|
|
|
- # 处理并显示OCR内容 - 只高亮选中的文本
|
|
|
+
|
|
|
+ # 获取匹配信息
|
|
|
+ selected_match_info = match_info[selected_index]
|
|
|
+ if selected_match_info:
|
|
|
+ if selected_match_info['type'] == 'ocr':
|
|
|
+ st.info(f"🔍 **OCR识别文本匹配**: `{selected_match_info['source']}`")
|
|
|
+ elif not selected_match_info['has_bbox']:
|
|
|
+ st.warning(f"⚠️ **未找到边界框**: 文本在MD中存在,但没有对应的坐标信息")
|
|
|
+
|
|
|
+ # 🎯 增强高亮显示逻辑
|
|
|
if self.validator.md_content:
|
|
|
highlighted_content = self.validator.md_content
|
|
|
|
|
|
- # 只高亮选中的文本
|
|
|
if st.session_state.selected_text:
|
|
|
selected_text = st.session_state.selected_text
|
|
|
+
|
|
|
+ # 获取匹配信息
|
|
|
+ info_list = self.validator.text_bbox_mapping.get(selected_text, [])
|
|
|
+ has_bbox = False
|
|
|
+ matched_text = None
|
|
|
+ match_type = None
|
|
|
+
|
|
|
+ if info_list and isinstance(info_list[0], dict):
|
|
|
+ has_bbox = 'bbox' in info_list[0] and info_list[0]['bbox']
|
|
|
+ matched_text = info_list[0].get('matched_text', '')
|
|
|
+
|
|
|
+ # 🔑 判断匹配类型
|
|
|
+ if matched_text and matched_text != selected_text:
|
|
|
+ match_type = "ocr"
|
|
|
+ elif has_bbox:
|
|
|
+ match_type = "exact"
|
|
|
+ else:
|
|
|
+ match_type = "no_bbox"
|
|
|
+
|
|
|
+ # 🎯 应用高亮
|
|
|
if len(selected_text) > 2:
|
|
|
- highlighted_content = highlighted_content.replace(
|
|
|
- selected_text,
|
|
|
- f'<span class="highlight-text selected-highlight" title="{selected_text}">{selected_text}</span>'
|
|
|
- )
|
|
|
+ # 1. 高亮原始文本
|
|
|
+ if selected_text in highlighted_content:
|
|
|
+ if match_type == "exact":
|
|
|
+ highlight_class = "highlight-text selected-highlight"
|
|
|
+ elif match_type == "no_bbox":
|
|
|
+ highlight_class = "highlight-text no-bbox"
|
|
|
+ else:
|
|
|
+ highlight_class = "highlight-text default"
|
|
|
+
|
|
|
+ highlighted_content = highlighted_content.replace(
|
|
|
+ selected_text,
|
|
|
+ f'<span class="{highlight_class}" title="{selected_text}">{selected_text}</span>'
|
|
|
+ )
|
|
|
+
|
|
|
+ # 2. 如果有 matched_text 且不同,也高亮
|
|
|
+ if matched_text and matched_text != selected_text and matched_text in highlighted_content:
|
|
|
+ highlighted_content = highlighted_content.replace(
|
|
|
+ matched_text,
|
|
|
+ f'<span class="highlight-text ocr-match" title="OCR: {matched_text}">{matched_text}</span>'
|
|
|
+ )
|
|
|
|
|
|
- self.render_content_by_mode(highlighted_content, "HTML渲染", font_size, container_height, layout_type)
|
|
|
-
|
|
|
+ # 🎯 调用渲染方法(样式已内置)
|
|
|
+ self.render_content_by_mode(
|
|
|
+ highlighted_content,
|
|
|
+ "HTML渲染",
|
|
|
+ font_size,
|
|
|
+ container_height,
|
|
|
+ layout_type
|
|
|
+ )
|
|
|
+
|
|
|
with right_col:
|
|
|
- # 修复的对齐图片显示
|
|
|
self.create_aligned_image_display(zoom_level, "compact")
|
|
|
-
|
|
|
+
|
|
|
def create_aligned_image_display(self, zoom_level: float = 1.0, layout_type: str = "aligned"):
|
|
|
"""创建响应式图片显示"""
|
|
|
|
|
|
@@ -453,6 +597,7 @@ class OCRLayoutManager:
|
|
|
if image:
|
|
|
try:
|
|
|
resized_image, all_boxes, selected_boxes = self.zoom_image(image, self.zoom_level)
|
|
|
+
|
|
|
# 创建交互式图片
|
|
|
fig = self.create_resized_interactive_plot(resized_image, selected_boxes, self.zoom_level, all_boxes)
|
|
|
|
|
|
@@ -518,44 +663,81 @@ class OCRLayoutManager:
|
|
|
|
|
|
return resized_image, all_boxes, selected_boxes
|
|
|
|
|
|
- def _add_bboxes_to_plot(self, fig: go.Figure, bboxes: List[List[int]], image_height: int,
|
|
|
- line_color: str = "blue", line_width: int = 1,
|
|
|
- fill_color: str = "rgba(0, 100, 200, 0.2)"):
|
|
|
+ def _add_bboxes_to_plot_batch(self, fig: go.Figure, bboxes: List[List[int]],
|
|
|
+ image_height: int,
|
|
|
+ line_color: str = "blue",
|
|
|
+ line_width: int = 1,
|
|
|
+ fill_color: str = "rgba(0, 100, 200, 0.2)"):
|
|
|
"""
|
|
|
- 在plotly图表上添加边界框
|
|
|
-
|
|
|
- Args:
|
|
|
- fig: plotly图表对象
|
|
|
- bboxes: 边界框列表,每个bbox格式为[x1, y1, x2, y2]
|
|
|
- image_height: 图片高度,用于Y轴坐标转换
|
|
|
- line_color: 边框线颜色
|
|
|
- line_width: 边框线宽度
|
|
|
- fill_color: 填充颜色(RGBA格式)
|
|
|
+ 批量添加边界框(性能优化版)
|
|
|
"""
|
|
|
if not bboxes or len(bboxes) == 0:
|
|
|
return
|
|
|
-
|
|
|
+
|
|
|
+ # 🎯 关键优化:构建 shapes 列表,一次性添加
|
|
|
+ shapes = []
|
|
|
for bbox in bboxes:
|
|
|
if len(bbox) < 4:
|
|
|
continue
|
|
|
-
|
|
|
+
|
|
|
x1, y1, x2, y2 = bbox[:4]
|
|
|
|
|
|
- # 转换为Plotly坐标系(翻转Y轴)
|
|
|
- # JSON格式: 原点在左上角, y向下增加
|
|
|
- # Plotly格式: 原点在左下角, y向上增加
|
|
|
+ # 转换坐标
|
|
|
plot_x1 = x1
|
|
|
plot_x2 = x2
|
|
|
- plot_y1 = image_height - y2 # JSON的y2(底部) -> Plotly的底部
|
|
|
- plot_y2 = image_height - y1 # JSON的y1(顶部) -> Plotly的顶部
|
|
|
+ plot_y1 = image_height - y2
|
|
|
+ plot_y2 = image_height - y1
|
|
|
|
|
|
- fig.add_shape(
|
|
|
+ shapes.append(dict(
|
|
|
type="rect",
|
|
|
x0=plot_x1, y0=plot_y1,
|
|
|
x1=plot_x2, y1=plot_y2,
|
|
|
line=dict(color=line_color, width=line_width),
|
|
|
fillcolor=fill_color,
|
|
|
- )
|
|
|
+ ))
|
|
|
+
|
|
|
+ # 🎯 一次性更新所有形状
|
|
|
+ fig.update_layout(shapes=fig.layout.shapes + tuple(shapes))
|
|
|
+
|
|
|
+ def _add_bboxes_as_scatter(self, fig: go.Figure, bboxes: List[List[int]],
|
|
|
+ image_height: int,
|
|
|
+ line_color: str = "blue",
|
|
|
+ line_width: int = 1,
|
|
|
+ name: str = "boxes"):
|
|
|
+ """
|
|
|
+ 使用 Scatter 绘制边界框(极致性能优化)
|
|
|
+ """
|
|
|
+ if not bboxes or len(bboxes) == 0:
|
|
|
+ return
|
|
|
+
|
|
|
+ # 🎯 收集所有矩形的边框线坐标
|
|
|
+ x_coords = []
|
|
|
+ y_coords = []
|
|
|
+
|
|
|
+ for bbox in bboxes:
|
|
|
+ if len(bbox) < 4:
|
|
|
+ continue
|
|
|
+
|
|
|
+ x1, y1, x2, y2 = bbox[:4]
|
|
|
+
|
|
|
+ # 转换坐标
|
|
|
+ plot_y1 = image_height - y2
|
|
|
+ plot_y2 = image_height - y1
|
|
|
+
|
|
|
+ # 绘制矩形:5个点(闭合)
|
|
|
+ x_coords.extend([x1, x2, x2, x1, x1, None]) # None用于断开线段
|
|
|
+ y_coords.extend([plot_y1, plot_y1, plot_y2, plot_y2, plot_y1, None])
|
|
|
+
|
|
|
+ # 🎯 一次性添加所有边框
|
|
|
+ fig.add_trace(go.Scatter(
|
|
|
+ x=x_coords,
|
|
|
+ y=y_coords,
|
|
|
+ mode='lines',
|
|
|
+ line=dict(color=line_color, width=line_width),
|
|
|
+ name=name,
|
|
|
+ showlegend=False,
|
|
|
+ hoverinfo='skip'
|
|
|
+ ))
|
|
|
|
|
|
def create_resized_interactive_plot(self, image: Image.Image, selected_boxes: List[List[int]],
|
|
|
zoom_level: float, all_boxes: List[List[int]]) -> go.Figure:
|
|
|
@@ -579,23 +761,23 @@ class OCRLayoutManager:
|
|
|
|
|
|
# 显示所有bbox(淡蓝色)
|
|
|
if all_boxes:
|
|
|
- self._add_bboxes_to_plot(
|
|
|
+ self._add_bboxes_as_scatter(
|
|
|
fig=fig,
|
|
|
bboxes=all_boxes,
|
|
|
image_height=image.height,
|
|
|
- line_color="blue",
|
|
|
+ line_color="rgba(0, 100, 200, 0.8)",
|
|
|
line_width=1,
|
|
|
- fill_color="rgba(0, 100, 200, 0.2)"
|
|
|
+ name="all_boxes"
|
|
|
)
|
|
|
|
|
|
# 高亮显示选中的bbox(红色)
|
|
|
if selected_boxes:
|
|
|
- self._add_bboxes_to_plot(
|
|
|
+ self._add_bboxes_to_plot_batch(
|
|
|
fig=fig,
|
|
|
bboxes=selected_boxes,
|
|
|
image_height=image.height,
|
|
|
line_color="red",
|
|
|
- line_width=3,
|
|
|
+ line_width=1,
|
|
|
fill_color="rgba(255, 0, 0, 0.3)"
|
|
|
)
|
|
|
|