| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- """
- 手动调整功能
- """
- from .state_manager import save_state_for_undo
- from .drawing import clear_table_image_cache
- def create_adjustment_section(structure):
- """
- 创建手动调整区域
- """
- import streamlit as st
- st.divider()
- st.header("🛠️ 手动调整")
- horizontal_lines = structure.get('horizontal_lines', [])
- vertical_lines = structure.get('vertical_lines', [])
- adjusted = False
- # 行操作, 列操作
- adjustment_action = st.radio(
- "行&列操作",
- ["调整横线", "添加横线", "删除横线", "调整竖线", "添加竖线", "删除竖线", "微调旋转"],
- horizontal=True,
- index=None,
- label_visibility="collapsed",
- key="adjustment_action_radio"
- )
- if adjustment_action == "调整横线" and horizontal_lines:
- line_index = st.selectbox(
- "选择横线",
- range(len(horizontal_lines)),
- format_func=lambda i: f"R{i+1} (Y={horizontal_lines[i]})",
- key="adjust_h_select"
- )
- new_y = st.number_input(
- "新的Y坐标",
- min_value=0,
- value=horizontal_lines[line_index],
- step=1,
- key="adjust_h_value"
- )
- if st.button("✅ 应用横线调整"):
- if new_y != horizontal_lines[line_index]:
- save_state_for_undo(structure)
- structure['horizontal_lines'][line_index] = new_y
- # structure.setdefault('modified_h_lines', [])
- if line_index not in structure['modified_h_lines']:
- structure['modified_h_lines'].append(line_index)
- _update_row_intervals(structure)
- clear_table_image_cache()
- adjusted = True
- st.success(f"✅ R{line_index+1} 已更新")
- elif adjustment_action == "添加横线":
- new_h_y = st.number_input(
- "新横线的Y坐标",
- min_value=0,
- value=horizontal_lines[-1] + 50 if horizontal_lines else 100,
- step=1,
- key="add_h_value"
- )
- if st.button("➕ 确认添加横线"):
- save_state_for_undo(structure)
- structure['horizontal_lines'].append(new_h_y)
- structure['horizontal_lines'].sort()
- idx = structure['horizontal_lines'].index(new_h_y)
- # structure.setdefault('modified_h_lines', [])
- if idx not in structure['modified_h_lines']:
- structure['modified_h_lines'].append(idx)
- _update_row_intervals(structure)
- clear_table_image_cache()
- adjusted = True
- st.success(f"✅ 新增横线 Y={new_h_y}")
- elif adjustment_action == "删除横线" and len(horizontal_lines) > 2:
- to_delete = st.multiselect(
- "选择要删除的横线",
- range(len(horizontal_lines)),
- format_func=lambda i: f"R{i+1} (Y={horizontal_lines[i]})",
- key="del_h_select"
- )
- if to_delete and st.button("🗑️ 确认删除横线"):
- save_state_for_undo(structure)
- for idx in sorted(to_delete, reverse=True):
- del structure['horizontal_lines'][idx]
- structure['modified_h_lines'] = []
- _update_row_intervals(structure)
- clear_table_image_cache()
- adjusted = True
- st.success(f"✅ 已删除 {len(to_delete)} 条横线")
- elif adjustment_action == "调整竖线" and vertical_lines:
- line_index = st.selectbox(
- "选择竖线",
- range(len(vertical_lines)),
- format_func=lambda i: f"C{i+1} (X={vertical_lines[i]})",
- key="adjust_v_select"
- )
- new_x = st.number_input(
- "新的X坐标",
- min_value=0,
- value=vertical_lines[line_index],
- step=1,
- key="adjust_v_value"
- )
- if st.button("✅ 应用竖线调整"):
- if new_x != vertical_lines[line_index]:
- save_state_for_undo(structure)
- structure['vertical_lines'][line_index] = new_x
- # structure.setdefault('modified_v_lines', [])
- if line_index not in structure['modified_v_lines']:
- structure['modified_v_lines'].append(line_index)
- _update_column_intervals(structure)
- clear_table_image_cache()
- adjusted = True
- st.success(f"✅ C{line_index+1} 已更新")
- elif adjustment_action == "添加竖线":
- new_v_x = st.number_input(
- "新竖线的X坐标",
- min_value=0,
- value=vertical_lines[-1] + 100 if vertical_lines else 100,
- step=1,
- key="add_v_value"
- )
- if st.button("➕ 确认添加竖线"):
- structure['vertical_lines'].append(new_v_x)
- structure['vertical_lines'].sort()
- idx = structure['vertical_lines'].index(new_v_x)
- # structure.setdefault('modified_v_lines', [])
- if idx not in structure['modified_v_lines']:
- structure['modified_v_lines'].append(idx)
- _update_column_intervals(structure)
- clear_table_image_cache()
- adjusted = True
- st.success(f"✅ 新增竖线 X={new_v_x}")
- elif adjustment_action == "删除竖线" and len(vertical_lines) > 2:
- to_delete = st.multiselect(
- "选择要删除的竖线",
- range(len(vertical_lines)),
- format_func=lambda i: f"C{i+1} (X={vertical_lines[i]})",
- key="del_v_select"
- )
- if to_delete and st.button("🗑️ 确认删除竖线"):
- save_state_for_undo(structure)
- for idx in sorted(to_delete, reverse=True):
- del structure['vertical_lines'][idx]
- structure['modified_v_lines'] = []
- _update_column_intervals(structure)
- clear_table_image_cache()
- adjusted = True
- st.success(f"✅ 已删除 {len(to_delete)} 条竖线")
- elif adjustment_action == "微调旋转":
- st.info("📐 手动修正图片的倾斜角度。系统会根据设定的倾斜角度,进行**反向旋转**来校正图片。")
-
- if 'generator' in st.session_state:
- generator = st.session_state.generator
- current_skew = generator.ocr_data.get('skew_angle', 0.0)
- original_skew = generator.ocr_data.get('original_skew_angle', 0.0)
-
- # 计算实际执行的旋转角度
- applied_rotation = -current_skew
-
- st.markdown(f"""
- * **原始识别倾斜:** `{original_skew:.2f}°` (OCR模型检测到的原始角度)
- * **当前设定倾斜:** `{current_skew:.2f}°` (系统认为图片歪了多少)
- * **实际执行旋转:** `{applied_rotation:.2f}°` (系统实际执行的**反向**校正旋转)
- """)
-
- col1, col2 = st.columns([1, 1], width=300, gap="small")
- with col1:
- delta_angle = st.number_input(
- "调整设定值 (度)",
- min_value=-10.0,
- max_value=10.0,
- value=0.0,
- step=0.05,
- format="%.2f",
- help="增加设定值 -> 系统认为图片逆时针歪得更多 -> 执行更大幅度的顺时针旋转",
- label_visibility="collapsed",
- key="rotate_delta_input"
- )
- with col2:
- if st.button("🔄 应用调整", key="apply_rotate_btn"):
- if delta_angle != 0:
- # 更新 skew_angle
- generator.ocr_data['skew_angle'] = current_skew + delta_angle
-
- with st.spinner("正在重新校正图片..."):
- # 强制重新校正
- corrected_image, _ = generator.correct_skew(force=True)
- st.session_state.image = corrected_image
-
- # 清除缓存
- clear_table_image_cache()
- adjusted = True
-
- # 标记需要重新分析结构
- st.session_state.need_reanalysis = True
-
- st.success(f"✅ 已应用旋转 {delta_angle}°")
- st.rerun()
- else:
- st.warning("⚠️ 无法获取 TableLineGenerator 实例")
- return adjusted
- def _update_row_intervals(structure):
- """根据横线坐标更新行区间"""
- horizontal_lines = structure.get('horizontal_lines', [])
-
- rows = []
- for i in range(len(horizontal_lines) - 1):
- rows.append({
- 'y_start': horizontal_lines[i],
- 'y_end': horizontal_lines[i + 1],
- 'bboxes': []
- })
-
- structure['rows'] = rows
-
- # 更新表格边界框
- if 'table_bbox' in structure:
- vertical_lines = structure.get('vertical_lines', [])
- structure['table_bbox'] = [
- vertical_lines[0] if vertical_lines else 0,
- horizontal_lines[0],
- vertical_lines[-1] if vertical_lines else 0,
- horizontal_lines[-1]
- ]
- def _update_column_intervals(structure):
- """根据竖线坐标更新列区间"""
- vertical_lines = structure.get('vertical_lines', [])
-
- columns = []
- for i in range(len(vertical_lines) - 1):
- columns.append({
- 'x_start': vertical_lines[i],
- 'x_end': vertical_lines[i + 1]
- })
-
- structure['columns'] = columns
-
- # 更新列宽
- col_widths = [col['x_end'] - col['x_start'] for col in columns]
- structure['col_widths'] = col_widths
-
- # 更新表格边界框
- if 'table_bbox' in structure:
- horizontal_lines = structure.get('horizontal_lines', [])
- structure['table_bbox'] = [
- vertical_lines[0],
- horizontal_lines[0] if horizontal_lines else 0,
- vertical_lines[-1],
- horizontal_lines[-1] if horizontal_lines else 0
- ]
|