Spaces:
Sleeping
Sleeping
| import re | |
| import gradio as gr | |
| import os | |
| import tempfile | |
| import logging | |
| import json | |
| from pathlib import Path | |
| from datetime import datetime | |
| import cv2 | |
| import numpy as np | |
| from PIL import Image | |
| import fitz # PyMuPDF | |
| from typing import Dict, List, Tuple, Optional | |
| # Load environment variables | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| from backend import BackendManager | |
| from enhanced_indentation import EnhancedIndentationDetector, OpenCVTextAnalyzer | |
| # Configure logging | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| # Initialize backend manager | |
| backend_manager = BackendManager() | |
| # Initialize enhanced indentation detector with OpenCV | |
| indent_detector = EnhancedIndentationDetector() | |
| opencv_analyzer = OpenCVTextAnalyzer() | |
| # Check if python-docx is available | |
| try: | |
| from docx import Document | |
| from docx.shared import Inches, Pt | |
| from docx.enum.table import WD_TABLE_ALIGNMENT | |
| HAS_DOCX_SUPPORT = True | |
| logger.info("DOCX export available") | |
| except ImportError: | |
| HAS_DOCX_SUPPORT = False | |
| logger.info("DOCX export not available - install python-docx to enable") | |
| # Check OpenCV availability | |
| try: | |
| import cv2 | |
| HAS_OPENCV_SUPPORT = True | |
| logger.info("OpenCV text block analysis and bold detection available") | |
| except ImportError: | |
| HAS_OPENCV_SUPPORT = False | |
| logger.info("OpenCV not available - text block analysis and bold detection disabled") | |
| # Global variables for enhanced crop management with OpenCV | |
| current_pdf_data = { | |
| 'path': None, | |
| 'page_count': 0, | |
| 'page_images': {}, | |
| 'crop_settings': {}, | |
| 'default_crop_all': True, | |
| 'opencv_analysis': {} | |
| } | |
| class PDFPageManager: | |
| """Manages PDF page previews and crop settings with OpenCV-enhanced analysis""" | |
| def __init__(self): | |
| self.pdf_doc = None | |
| self.page_images = {} | |
| self.crop_settings = {} | |
| self.current_page = 0 | |
| self.high_res_scale = 2.0 # Optimized for OpenCV analysis | |
| self.opencv_analysis = {} | |
| def load_pdf(self, pdf_path: str) -> Dict: | |
| """Load PDF and generate high-resolution page previews with OpenCV analysis""" | |
| try: | |
| if self.pdf_doc: | |
| self.pdf_doc.close() | |
| self.pdf_doc = fitz.open(pdf_path) | |
| page_count = len(self.pdf_doc) | |
| # Generate high-resolution previews and OpenCV analysis for all pages | |
| self.page_images = {} | |
| self.opencv_analysis = {} | |
| for page_num in range(page_count): | |
| # Generate high-resolution preview | |
| img_array = self._generate_high_res_preview(page_num) | |
| self.page_images[page_num] = img_array | |
| # Perform OpenCV analysis if available | |
| if HAS_OPENCV_SUPPORT and img_array is not None: | |
| # Extract text lines for OpenCV correlation | |
| page = self.pdf_doc.load_page(page_num) | |
| text_content = page.get_text() | |
| text_lines = text_content.split('\n') | |
| # Perform OpenCV text block analysis | |
| opencv_result = opencv_analyzer.analyze_text_blocks(img_array, text_lines) | |
| self.opencv_analysis[page_num] = opencv_result | |
| logger.info(f"OpenCV analysis for page {page_num + 1}: {opencv_result.get('block_count', 0)} text blocks, bold detected: {opencv_result.get('bold_text_detected', False)}") | |
| # Initialize default crop settings for all pages | |
| self.crop_settings = { | |
| i: {'top': 0, 'bottom': 0, 'left': 0, 'right': 0, 'custom': False} | |
| for i in range(page_count) | |
| } | |
| logger.info(f"PDF loaded successfully with OpenCV enhancement: {page_count} pages") | |
| return { | |
| 'success': True, | |
| 'page_count': page_count, | |
| 'pages': list(range(page_count)), | |
| 'opencv_enhanced': HAS_OPENCV_SUPPORT, | |
| 'opencv_analysis_available': bool(self.opencv_analysis) | |
| } | |
| except Exception as e: | |
| logger.error(f"Error loading PDF: {e}") | |
| return {'success': False, 'error': str(e)} | |
| def _generate_high_res_preview(self, page_num: int) -> np.ndarray: | |
| """Generate high-resolution preview optimized for OpenCV analysis""" | |
| try: | |
| if not self.pdf_doc: | |
| return None | |
| page = self.pdf_doc.load_page(page_num) | |
| # Use high resolution matrix for better OpenCV analysis | |
| mat = fitz.Matrix(self.high_res_scale, self.high_res_scale) | |
| pix = page.get_pixmap(matrix=mat) | |
| img_data = pix.tobytes("png") | |
| # Convert to PIL Image and then to numpy array | |
| import io | |
| pil_image = Image.open(io.BytesIO(img_data)) | |
| img_array = np.array(pil_image) | |
| # Convert RGBA to RGB if needed, then to BGR for OpenCV | |
| if len(img_array.shape) == 3 and img_array.shape[2] == 4: | |
| img_array = img_array[:, :, :3] | |
| # Convert RGB to BGR for OpenCV compatibility | |
| if len(img_array.shape) == 3: | |
| img_array = cv2.cvtColor(img_array, cv2.COLOR_RGB2BGR) | |
| return img_array | |
| except Exception as e: | |
| logger.error(f"Error generating preview for page {page_num}: {e}") | |
| return None | |
| def update_crop_visualization(self, page_num: int, crop_coords: Dict) -> np.ndarray: | |
| """Update crop visualization with OpenCV-enhanced preview and text block overlay""" | |
| if page_num not in self.page_images or self.page_images[page_num] is None: | |
| logger.warning(f"No image available for page {page_num}") | |
| return None | |
| try: | |
| img_array = self.page_images[page_num].copy() | |
| height, width = img_array.shape[:2] | |
| # Convert coordinates from percentages to pixels | |
| x1 = int(crop_coords.get('left', 0) * width / 100) | |
| y1 = int(crop_coords.get('top', 0) * height / 100) | |
| x2 = width - int(crop_coords.get('right', 0) * width / 100) | |
| y2 = height - int(crop_coords.get('bottom', 0) * height / 100) | |
| # Ensure coordinates are valid | |
| x1 = max(0, min(x1, width)) | |
| x2 = max(0, min(x2, width)) | |
| y1 = max(0, min(y1, height)) | |
| y2 = max(0, min(y2, height)) | |
| # Create overlay | |
| overlay = img_array.copy() | |
| # Draw crop areas in semi-transparent red (areas to be removed) | |
| alpha = 0.3 | |
| if crop_coords.get('top', 0) > 0 and y1 > 0: | |
| cv2.rectangle(overlay, (0, 0), (width, y1), (0, 0, 255), -1) | |
| if crop_coords.get('bottom', 0) > 0 and y2 < height: | |
| cv2.rectangle(overlay, (0, y2), (width, height), (0, 0, 255), -1) | |
| if crop_coords.get('left', 0) > 0 and x1 > 0: | |
| cv2.rectangle(overlay, (0, 0), (x1, height), (0, 0, 255), -1) | |
| if crop_coords.get('right', 0) > 0 and x2 < width: | |
| cv2.rectangle(overlay, (x2, 0), (width, height), (0, 0, 255), -1) | |
| # Draw content area outline in green | |
| if x2 > x1 and y2 > y1: | |
| thickness = max(2, int(self.high_res_scale * 2)) | |
| cv2.rectangle(overlay, (x1, y1), (x2, y2), (0, 255, 0), thickness) | |
| # Add OpenCV text block visualization if available | |
| if HAS_OPENCV_SUPPORT and page_num in self.opencv_analysis: | |
| opencv_result = self.opencv_analysis[page_num] | |
| if opencv_result.get('success', False): | |
| # Draw text blocks in blue | |
| for block in opencv_result.get('text_blocks', []): | |
| block_x = block.get('x', 0) | |
| block_y = block.get('y', 0) | |
| block_w = block.get('width', 0) | |
| block_h = block.get('height', 0) | |
| cv2.rectangle(overlay, (block_x, block_y), | |
| (block_x + block_w, block_y + block_h), | |
| (255, 100, 0), 2) # Blue for text blocks | |
| # Draw bold regions in orange | |
| for bold_region in opencv_result.get('bold_regions', []): | |
| if bold_region.get('is_likely_header', False): | |
| bold_x = bold_region.get('x', 0) | |
| bold_y = bold_region.get('y', 0) | |
| bold_w = bold_region.get('width', 0) | |
| bold_h = bold_region.get('height', 0) | |
| cv2.rectangle(overlay, (bold_x, bold_y), | |
| (bold_x + bold_w, bold_y + bold_h), | |
| (0, 165, 255), 3) # Orange for bold headers | |
| # Blend overlay with original | |
| result = cv2.addWeighted(img_array, 1-alpha, overlay, alpha, 0) | |
| # Add informative text with OpenCV enhancement info | |
| font_scale = max(0.8, self.high_res_scale / 3) | |
| thickness = max(1, int(self.high_res_scale)) | |
| text_color = (255, 255, 255) | |
| background_color = (0, 0, 0) | |
| # Add text with background for better visibility | |
| texts = [ | |
| f"Page {page_num + 1}", | |
| "RED: Remove areas", | |
| "GREEN: Content area" | |
| ] | |
| # Add OpenCV-specific information | |
| if HAS_OPENCV_SUPPORT and page_num in self.opencv_analysis: | |
| opencv_result = self.opencv_analysis[page_num] | |
| if opencv_result.get('success', False): | |
| texts.extend([ | |
| "BLUE: Text blocks", | |
| "ORANGE: Bold headers", | |
| f"Blocks: {opencv_result.get('block_count', 0)}", | |
| f"Bold detected: {'Yes' if opencv_result.get('bold_text_detected', False) else 'No'}" | |
| ]) | |
| texts.append(f"Crop: T{crop_coords.get('top', 0):.1f}% B{crop_coords.get('bottom', 0):.1f}% L{crop_coords.get('left', 0):.1f}% R{crop_coords.get('right', 0):.1f}%") | |
| y_offset = 30 | |
| for i, text in enumerate(texts): | |
| y_pos = y_offset + (i * 30) | |
| # Add background rectangle for text | |
| (text_width, text_height), _ = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, font_scale, thickness) | |
| cv2.rectangle(result, (10, y_pos - text_height - 5), (text_width + 20, y_pos + 5), background_color, -1) | |
| cv2.putText(result, text, (15, y_pos), cv2.FONT_HERSHEY_SIMPLEX, font_scale, text_color, thickness) | |
| # Convert back to RGB for display | |
| result_rgb = cv2.cvtColor(result, cv2.COLOR_BGR2RGB) | |
| return result_rgb | |
| except Exception as e: | |
| logger.error(f"Error updating crop visualization: {e}") | |
| if page_num in self.page_images and self.page_images[page_num] is not None: | |
| # Convert BGR to RGB for display | |
| return cv2.cvtColor(self.page_images[page_num], cv2.COLOR_BGR2RGB) | |
| return None | |
| def set_crop_for_page(self, page_num: int, crop_coords: Dict): | |
| """Set crop coordinates for specific page""" | |
| if page_num in self.crop_settings: | |
| self.crop_settings[page_num].update(crop_coords) | |
| self.crop_settings[page_num]['custom'] = True | |
| logger.info(f"Set crop for page {page_num}: {crop_coords}") | |
| def set_crop_for_all_pages(self, crop_coords: Dict): | |
| """Apply same crop settings to all pages""" | |
| for page_num in self.crop_settings: | |
| if not self.crop_settings[page_num].get('custom', False): | |
| self.crop_settings[page_num].update(crop_coords) | |
| logger.info(f"Applied crop to all non-custom pages: {crop_coords}") | |
| def get_crop_settings_for_processing(self) -> Dict: | |
| """Get crop settings in format expected by backend""" | |
| return { | |
| 'per_page_crops': self.crop_settings, | |
| 'has_custom_crops': any(page.get('custom', False) for page in self.crop_settings.values()), | |
| 'enhanced_resolution': True, | |
| 'resolution_scale': self.high_res_scale, | |
| 'opencv_enhanced': HAS_OPENCV_SUPPORT, | |
| 'opencv_analysis': self.opencv_analysis | |
| } | |
| def get_opencv_analysis(self, page_num: int = None) -> Dict: | |
| """Get OpenCV analysis for specific page or all pages""" | |
| if page_num is not None: | |
| return self.opencv_analysis.get(page_num, {}) | |
| return self.opencv_analysis | |
| def close(self): | |
| """Clean up resources""" | |
| if self.pdf_doc: | |
| self.pdf_doc.close() | |
| self.pdf_doc = None | |
| self.page_images.clear() | |
| self.crop_settings.clear() | |
| self.opencv_analysis.clear() | |
| # Global page manager instance | |
| pdf_manager = PDFPageManager() | |
| def load_pdf_for_preview(pdf_file): | |
| """Load PDF and return page thumbnails with OpenCV analysis""" | |
| if pdf_file is None: | |
| return None, gr.update(choices=[], value=None), gr.update(visible=False), "No PDF loaded" | |
| try: | |
| result = pdf_manager.load_pdf(pdf_file.name) | |
| if result['success']: | |
| # Create page choices for dropdown | |
| page_choices = [f"Page {i+1}" for i in range(result['page_count'])] | |
| # Get first page preview with default crop and OpenCV overlay | |
| first_page_preview = pdf_manager.update_crop_visualization(0, { | |
| 'top': 0, 'bottom': 0, 'left': 0, 'right': 0 | |
| }) if 0 in pdf_manager.page_images else None | |
| # Create status message with OpenCV information | |
| status_parts = [f"PDF loaded successfully: {result['page_count']} pages"] | |
| if result.get('opencv_enhanced'): | |
| status_parts.append("OpenCV text block analysis: Enabled") | |
| opencv_analysis = pdf_manager.get_opencv_analysis() | |
| if opencv_analysis: | |
| total_blocks = sum(analysis.get('block_count', 0) for analysis in opencv_analysis.values()) | |
| bold_pages = sum(1 for analysis in opencv_analysis.values() if analysis.get('bold_text_detected', False)) | |
| status_parts.append(f"Total text blocks detected: {total_blocks}") | |
| status_parts.append(f"Pages with bold text: {bold_pages}") | |
| else: | |
| status_parts.append("OpenCV analysis: Not available") | |
| status = " | ".join(status_parts) | |
| return (first_page_preview, | |
| gr.update(choices=page_choices, value=page_choices[0] if page_choices else None, visible=True), | |
| gr.update(visible=True), | |
| status) | |
| else: | |
| return None, gr.update(choices=[], value=None, visible=False), gr.update(visible=False), f"Error: {result['error']}" | |
| except Exception as e: | |
| logger.error(f"Error in load_pdf_for_preview: {e}") | |
| return None, gr.update(choices=[], value=None, visible=False), gr.update(visible=False), f"Error loading PDF: {str(e)}" | |
| def change_preview_page(page_selection, crop_top, crop_bottom, crop_left, crop_right): | |
| """Change preview to selected page with OpenCV-enhanced visualization""" | |
| if not page_selection: | |
| return None | |
| try: | |
| page_num = int(page_selection.split()[1]) - 1 # Extract page number | |
| # Get current crop settings for this page | |
| crop_coords = { | |
| 'top': crop_top, | |
| 'bottom': crop_bottom, | |
| 'left': crop_left, | |
| 'right': crop_right | |
| } | |
| # Update visualization with OpenCV enhancement | |
| preview_image = pdf_manager.update_crop_visualization(page_num, crop_coords) | |
| return preview_image | |
| except Exception as e: | |
| logger.error(f"Error changing preview page: {e}") | |
| return None | |
| def update_crop_preview_interactive(page_selection, crop_top, crop_bottom, crop_left, crop_right, apply_to_all): | |
| """Update crop preview with OpenCV-enhanced interactive feedback""" | |
| if not page_selection or not pdf_manager.pdf_doc: | |
| return None | |
| try: | |
| page_num = int(page_selection.split()[1]) - 1 | |
| crop_coords = { | |
| 'top': crop_top, | |
| 'bottom': crop_bottom, | |
| 'left': crop_left, | |
| 'right': crop_right | |
| } | |
| # Apply to current page or all pages based on setting | |
| if apply_to_all: | |
| pdf_manager.set_crop_for_all_pages(crop_coords) | |
| else: | |
| pdf_manager.set_crop_for_page(page_num, crop_coords) | |
| # Return updated preview with OpenCV enhancement | |
| return pdf_manager.update_crop_visualization(page_num, crop_coords) | |
| except Exception as e: | |
| logger.error(f"Error updating crop preview: {e}") | |
| return None | |
| def process_pdf_with_opencv_enhancement(pdf_file, ocr_method, enable_header_footer_removal, | |
| crop_top, crop_bottom, crop_left, crop_right, | |
| apply_to_all_pages, current_page_selection, | |
| progress=gr.Progress()): | |
| """Process PDF with OpenCV-enhanced text block analysis, bold detection, and comprehensive formatting""" | |
| if pdf_file is None: | |
| return "No file uploaded.", "", "", "Error: No file selected" | |
| try: | |
| progress(0.1, desc="Initializing OpenCV-enhanced processing with text block analysis and bold detection...") | |
| # Prepare enhanced preprocessing options with OpenCV data | |
| preprocessing_options = { | |
| 'enable_header_footer_removal': enable_header_footer_removal, | |
| 'enhanced_crop_processing': True, | |
| 'opencv_enhanced': HAS_OPENCV_SUPPORT, | |
| 'crop_settings': pdf_manager.get_crop_settings_for_processing() if enable_header_footer_removal else None | |
| } | |
| progress(0.3, desc="Processing with OpenCV text block analysis, bold detection, and comprehensive indentation...") | |
| # Process the PDF with OpenCV-enhanced analysis | |
| result = backend_manager.process_pdf_with_enhanced_resolution( | |
| pdf_file.name, ocr_method, preprocessing_options | |
| ) | |
| progress(0.9, desc="Finalizing OpenCV-enhanced processing...") | |
| progress(1.0, desc="Complete!") | |
| if result['success']: | |
| # Clean any remaining artifacts from text and HTML | |
| result['text'] = result['text'].replace(':unselected:', '').replace(':selected:', '') | |
| result['html'] = result['html'].replace(':unselected:', '').replace(':selected:', '') | |
| metadata_info = format_opencv_enhanced_metadata(result['metadata'], result['method_used']) | |
| status_parts = [f"Success: Processed using {result['method_used']}"] | |
| status_parts.append("OpenCV text block analysis: Enabled") | |
| status_parts.append("Bold text detection: Enabled") | |
| status_parts.append("Comprehensive indentation detection: Enabled") | |
| status_parts.append("Intelligent text classification: Enabled") | |
| status = " | ".join(status_parts) | |
| # Return text, HTML, metadata, and status | |
| return (result['text'], | |
| result.get('html', ''), | |
| metadata_info, | |
| status) | |
| else: | |
| error_msg = result.get('error', 'Unknown error occurred') | |
| return f"Error: {error_msg}", "", "", f"Processing failed: {error_msg}" | |
| except Exception as e: | |
| logger.error(f"OpenCV-enhanced processing error: {e}") | |
| return f"Error: {str(e)}", "", "", f"Unexpected error: {str(e)}" | |
| def format_opencv_enhanced_metadata(metadata, method_used): | |
| """Enhanced metadata formatting with OpenCV text block analysis and bold detection info""" | |
| if not metadata: | |
| return f"Method used: {method_used}" | |
| info_lines = [f"Method used: {method_used}"] | |
| if 'pages' in metadata: | |
| info_lines.append(f"Pages processed: {metadata['pages']}") | |
| if metadata.get('opencv_enhanced', False): | |
| info_lines.append("OpenCV enhancement: Enabled") | |
| if metadata.get('opencv_text_block_analysis', False): | |
| info_lines.append("OpenCV text block analysis: Enabled") | |
| if metadata.get('opencv_bold_detection', False): | |
| info_lines.append("OpenCV bold text detection: Enabled") | |
| if metadata.get('opencv_spacing_analysis', False): | |
| info_lines.append("OpenCV spacing analysis: Enabled") | |
| if metadata.get('header_indentation_suppression', False): | |
| info_lines.append("Header indentation suppression: Enabled") | |
| if metadata.get('enhanced_processing', False): | |
| info_lines.append("Enhanced processing: Enabled") | |
| if metadata.get('html_processing', False): | |
| info_lines.append("HTML generation: Enabled") | |
| if metadata.get('comprehensive_indentation', False): | |
| info_lines.append("Comprehensive indentation detection: Enabled") | |
| if metadata.get('intelligent_text_classification', False): | |
| info_lines.append("Intelligent text classification: Enabled") | |
| if metadata.get('parenthetical_patterns_supported', False): | |
| info_lines.append("Parenthetical patterns: Supported (Arabic, Thai, Letters, Roman)") | |
| if metadata.get('enhanced_resolution', False) and 'resolution_scale' in metadata: | |
| info_lines.append(f"Enhanced resolution: {metadata.get('resolution_scale', 'N/A')}x") | |
| if 'custom_crops_applied' in metadata: | |
| info_lines.append(f"Custom crops per page: {metadata['custom_crops_applied']}") | |
| if 'tables' in metadata: | |
| info_lines.append(f"Tables detected: {metadata['tables']}") | |
| # OpenCV-specific analysis information | |
| if 'opencv_global_analysis' in metadata: | |
| opencv_analysis = metadata['opencv_global_analysis'] | |
| if opencv_analysis.get('success', False): | |
| info_lines.append(f"OpenCV text blocks detected: {opencv_analysis.get('block_count', 0)}") | |
| info_lines.append(f"OpenCV paragraphs detected: {opencv_analysis.get('paragraph_count', 0)}") | |
| info_lines.append(f"OpenCV bold text detected: {'Yes' if opencv_analysis.get('bold_text_detected', False) else 'No'}") | |
| # Document structure analysis information | |
| if 'document_structure_analysis' in metadata: | |
| analysis = metadata['document_structure_analysis'] | |
| if not analysis.get('analysis_failed', False): | |
| info_lines.append(f"Patterned lines detected: {analysis.get('patterned_lines', 0)}") | |
| info_lines.append(f"Maximum indentation level: {analysis.get('max_level', 0)}") | |
| info_lines.append(f"Pattern coverage: {analysis.get('coverage_percentage', 0):.1f}%") | |
| # Text classification results | |
| if 'text_classification' in analysis: | |
| classification = analysis['text_classification'] | |
| info_lines.append(f"Headers detected: {analysis.get('header_count', 0)}") | |
| info_lines.append(f"Paragraphs detected: {analysis.get('paragraph_count', 0)}") | |
| info_lines.append(f"List items detected: {analysis.get('list_item_count', 0)}") | |
| if analysis.get('dominant_patterns'): | |
| dominant = analysis['dominant_patterns'][0][0] if analysis['dominant_patterns'] else 'None' | |
| info_lines.append(f"Dominant pattern: {dominant}") | |
| if 'processing_time_seconds' in metadata: | |
| info_lines.append(f"Processing time: {metadata['processing_time_seconds']:.2f} seconds") | |
| return "\n".join(info_lines) | |
| def prepare_opencv_enhanced_downloads(pdf_file, method, enable_header_footer_removal, | |
| crop_top, crop_bottom, crop_left, crop_right, | |
| apply_to_all_pages, current_page_selection): | |
| """Prepare OpenCV-enhanced downloads with text block analysis and bold detection""" | |
| text, html, metadata, status = process_pdf_with_opencv_enhancement( | |
| pdf_file, method, enable_header_footer_removal, | |
| crop_top, crop_bottom, crop_left, crop_right, | |
| apply_to_all_pages, current_page_selection | |
| ) | |
| # Prepare downloads if processing was successful | |
| if text and not text.startswith("Error:") and not text.startswith("No file"): | |
| try: | |
| # Create OpenCV-enhanced download files | |
| download_files = backend_manager.create_enhanced_downloads(text, html, metadata) | |
| # Prepare gradio updates for download buttons | |
| updates = [ | |
| text, metadata, status, # Display outputs | |
| gr.update(visible=True, value=download_files.get('txt')) if 'txt' in download_files else gr.update(visible=False), | |
| gr.update(visible=True, value=download_files.get('docx')) if 'docx' in download_files else gr.update(visible=False), | |
| gr.update(visible=True, value=download_files.get('html')) if 'html' in download_files else gr.update(visible=False) | |
| ] | |
| return tuple(updates) | |
| except Exception as file_error: | |
| logger.error(f"OpenCV-enhanced file creation error: {file_error}") | |
| return (text, metadata, status, | |
| gr.update(visible=False), | |
| gr.update(visible=False), | |
| gr.update(visible=False)) | |
| else: | |
| return (text, metadata, status, | |
| gr.update(visible=False), | |
| gr.update(visible=False), | |
| gr.update(visible=False)) | |
| def get_opencv_enhanced_method_info(method): | |
| """Get information about selected OCR method with OpenCV enhancements""" | |
| opencv_status = "with OpenCV Text Block Analysis & Bold Detection" if HAS_OPENCV_SUPPORT else "(OpenCV not available)" | |
| method_descriptions = { | |
| "auto": f"**Auto Selection**: Automatically chooses the best available method {opencv_status}, comprehensive indentation detection, intelligent text classification, HTML processing, enhanced pattern recognition for hierarchical numbering (including parenthetical patterns like (1), (๑), (a)), bullets, and multi-language support with header indentation suppression.", | |
| "azure": f"**Azure Document Intelligence**: Advanced cloud-based OCR {opencv_status}, comprehensive indentation detection, intelligent text classification, HTML generation, layout preservation, smart table detection, bold text recognition, and support for complex document structures including hierarchical numbering and parenthetical patterns with header detection.", | |
| "tesseract": f"**Tesseract OCR**: Open-source OCR enhanced {opencv_status}, comprehensive indentation detection, intelligent text classification, HTML output, advanced image preprocessing, resolution scaling, bold text detection, and pattern recognition for various numbering styles including parenthetical patterns and bullet points with header analysis.", | |
| "pymupdf": f"**PyMuPDF**: Fast extraction enhanced {opencv_status}, comprehensive indentation detection, intelligent text classification, HTML processing, improved formatting preservation, bold text recognition, and pattern recognition for maintaining document structure and hierarchy including parenthetical numbering with header detection." | |
| } | |
| return method_descriptions.get(method, "Select a method to see details.") | |
| def check_opencv_enhanced_service_status(): | |
| """Check and display OpenCV-enhanced service status with text block analysis and bold detection capabilities""" | |
| available_methods = backend_manager.get_available_methods() | |
| status_lines = ["**Available OCR Methods (Enhanced with OpenCV Text Block Analysis & Bold Detection):**"] | |
| opencv_status = " + OpenCV Enhanced" if HAS_OPENCV_SUPPORT else " (OpenCV not available)" | |
| if "azure" in available_methods: | |
| status_lines.append(f"✅ Azure Document Intelligence - Ready (HTML + Tables + Comprehensive Indentation + Text Classification{opencv_status})") | |
| else: | |
| status_lines.append("❌ Azure Document Intelligence - Not configured") | |
| if "tesseract" in available_methods: | |
| status_lines.append(f"✅ Tesseract OCR - Ready (HTML Enhanced + Comprehensive Indentation + Text Classification{opencv_status})") | |
| else: | |
| status_lines.append("❌ Tesseract OCR - Not available") | |
| if "pymupdf" in available_methods: | |
| status_lines.append(f"✅ PyMuPDF - Ready (HTML Enhanced + Comprehensive Indentation + Text Classification{opencv_status})") | |
| else: | |
| status_lines.append("❌ PyMuPDF - Not available") | |
| # Add OpenCV features status | |
| status_lines.append("") | |
| if HAS_OPENCV_SUPPORT: | |
| status_lines.append("**OpenCV Text Block Analysis & Bold Detection Features:**") | |
| status_lines.append("✅ Text Block Detection & Analysis") | |
| status_lines.append("✅ Bold Text Recognition for Headers") | |
| status_lines.append("✅ Automatic Spacing & Paragraph Detection") | |
| status_lines.append("✅ Visual Text Element Analysis") | |
| status_lines.append("✅ Header Indentation Suppression") | |
| status_lines.append("✅ Real-time Crop Preview with Text Overlay") | |
| status_lines.append("✅ Enhanced High-Resolution Processing") | |
| else: | |
| status_lines.append("**OpenCV Features:**") | |
| status_lines.append("❌ OpenCV not available - install opencv-python to enable") | |
| status_lines.append("❌ Text block analysis disabled") | |
| status_lines.append("❌ Bold detection disabled") | |
| # Add enhanced features status | |
| status_lines.append("") | |
| status_lines.append("**Comprehensive Indentation Detection Features:**") | |
| status_lines.append("✅ Hierarchical Decimal Numbering (1.1.1.1.1...)") | |
| status_lines.append("✅ Mixed Hierarchical Numbering (1.2.a.i.A...)") | |
| status_lines.append("✅ Legal Numbering (1.1.1(a)(i))") | |
| status_lines.append("✅ Outline Numbering (I.A.1.a.i.)") | |
| status_lines.append("✅ Section Numbering (§1.2.3, Article 1.1.1)") | |
| status_lines.append("✅ Parenthetical Arabic Numerals ((1), (2), (3))") | |
| status_lines.append("✅ Parenthetical Thai Numerals ((๑), (๒), (๓))") | |
| status_lines.append("✅ Parenthetical Letters ((a), (b), (A), (B))") | |
| status_lines.append("✅ Parenthetical Roman Numerals ((i), (ii), (I), (II))") | |
| status_lines.append("✅ Parenthetical Thai Letters ((ก), (ข), (ค))") | |
| status_lines.append("✅ Thai Script Support (มาตรา, ข้อ, ก.ข.ค.)") | |
| status_lines.append("✅ Multiple Bullet Styles (•◦▪→ and more)") | |
| status_lines.append("✅ Checkbox Items ([x], [ ], [✓])") | |
| status_lines.append("✅ Roman Numerals (I.II.III, i.ii.iii)") | |
| status_lines.append("✅ Letter Lists (A.B.C, a.b.c)") | |
| status_lines.append("✅ Space-based Indentation Detection") | |
| status_lines.append("✅ Priority-based Pattern Matching") | |
| status_lines.append("") | |
| status_lines.append("**Intelligent Text Classification Features:**") | |
| status_lines.append("✅ Header Detection (title case, all caps, short lines)") | |
| status_lines.append("✅ Paragraph Classification (long text, proper punctuation)") | |
| status_lines.append("✅ List Item Recognition (patterned content)") | |
| status_lines.append("✅ Context-aware Analysis (position, font size)") | |
| status_lines.append("✅ Confidence Scoring") | |
| status_lines.append("✅ Document Structure Analysis") | |
| if HAS_OPENCV_SUPPORT: | |
| status_lines.append("✅ OpenCV-Enhanced Bold Text Detection") | |
| status_lines.append("✅ Header Indentation Suppression") | |
| status_lines.append("") | |
| status_lines.append("**Enhanced Processing Features:**") | |
| status_lines.append("✅ HTML Processing - Available") | |
| status_lines.append("✅ Enhanced Table Handling - Available") | |
| status_lines.append("✅ Smart Text Preservation - Available") | |
| status_lines.append("✅ Multi-Page Crop Preview - Available") | |
| status_lines.append("✅ Per-Page Crop Customization - Available") | |
| status_lines.append("✅ Document Structure Analysis - Available") | |
| if HAS_OPENCV_SUPPORT: | |
| status_lines.append("✅ OpenCV Text Block Overlay - Available") | |
| status_lines.append("✅ Bold Text Visualization - Available") | |
| if HAS_DOCX_SUPPORT: | |
| status_lines.append("✅ Enhanced DOCX Export - Available (with OpenCV-enhanced indentation formatting)") | |
| else: | |
| status_lines.append("❌ Enhanced DOCX Export - Install python-docx to enable") | |
| status_lines.append("✅ HTML File Export - Available") | |
| status_lines.append("✅ Enhanced Text Export - Available") | |
| # Add pattern detection statistics | |
| pattern_count = len(indent_detector.patterns) | |
| status_lines.append(f"✅ Pattern Detection Engine - {pattern_count} patterns supported") | |
| return "\n".join(status_lines) | |
| def create_opencv_enhanced_interface(): | |
| """Create OpenCV-enhanced Gradio interface with text block analysis and bold detection""" | |
| with gr.Blocks( | |
| title="PDF OCR Service - Enhanced with OpenCV Text Block Analysis & Bold Detection", | |
| theme=gr.themes.Soft(), | |
| css=""" | |
| .main-header { text-align: center; margin-bottom: 2rem; } | |
| .config-panel { border: 2px solid #007bff; padding: 1.5rem; border-radius: 0.8rem; background-color: #f8f9fa; margin-bottom: 1rem; } | |
| .instructions-panel { border: 2px solid #28a745; padding: 1.5rem; border-radius: 0.8rem; background-color: #f0fff0; margin-bottom: 1rem; } | |
| .crop-controls { border: 2px solid #ffc107; padding: 1rem; border-radius: 0.5rem; background-color: #fffef7; } | |
| .page-preview { border: 2px solid #17a2b8; padding: 1rem; border-radius: 0.5rem; background-color: #f0f8ff; } | |
| .results-panel { border: 2px solid #6f42c1; padding: 1rem; border-radius: 0.5rem; background-color: #f8f5ff; } | |
| .status-box { border-left: 4px solid #007bff; padding: 1rem; background-color: #f8f9fa; } | |
| .opencv-panel { border: 2px solid #e74c3c; padding: 1rem; border-radius: 0.5rem; background-color: #fdf2f2; } | |
| """ | |
| ) as interface: | |
| gr.HTML(f""" | |
| <div class="main-header"> | |
| <h1>PDF OCR Service - Enhanced with OpenCV Text Block Analysis & Bold Detection</h1> | |
| <p>Convert PDF documents to text using OpenCV-enhanced OCR with text block detection, bold text recognition, HTML intermediate processing, smart table handling, comprehensive indentation pattern recognition including parenthetical patterns like (1), (๑), (a), and intelligent text classification for headers, paragraphs, and list items</p> | |
| <p><strong>OpenCV Status:</strong> {'✅ Available - Text block analysis and bold detection enabled' if HAS_OPENCV_SUPPORT else '❌ Not available - Install opencv-python for enhanced features'}</p> | |
| </div> | |
| """) | |
| # Instructions at the top | |
| with gr.Group(elem_classes=["instructions-panel"]): | |
| gr.HTML("<h3>Instructions & OpenCV-Enhanced Features</h3>") | |
| gr.HTML(f""" | |
| <div style="background-color: #e7f3ff; padding: 1rem; border-radius: 0.5rem;"> | |
| <h4>How to Use:</h4> | |
| <ol> | |
| <li><strong>Upload PDF:</strong> Select your PDF file in the configuration panel below</li> | |
| <li><strong>Choose Method:</strong> Select OCR method (Auto recommended for best results)</li> | |
| <li><strong>Configure Crop (Optional):</strong> Enable header/footer removal and adjust crop settings with OpenCV visualization</li> | |
| <li><strong>Process:</strong> Click the process button to extract text with OpenCV text block analysis and bold detection</li> | |
| <li><strong>Download:</strong> Get results in TXT, DOCX, or HTML format with preserved formatting and header detection</li> | |
| </ol> | |
| <h4>OpenCV Text Block Analysis & Bold Detection Features:</h4> | |
| <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: 0.5rem;"> | |
| <div> | |
| <strong>OpenCV Enhancements {'✅' if HAS_OPENCV_SUPPORT else '❌'}:</strong> | |
| <ul> | |
| <li>Text Block Detection & Analysis</li> | |
| <li>Entire Line Bold Text Recognition for Headers</li> | |
| <li>Automatic Spacing & Paragraph Detection</li> | |
| <li>Visual Text Element Analysis</li> | |
| <li>Header Indentation Suppression</li> | |
| <li>Real-time Text Block Overlay</li> | |
| <li>4-Space Indentation System</li> | |
| </ul> | |
| </div> | |
| <div> | |
| <strong>Hierarchical Numbering:</strong> | |
| <ul> | |
| <li>Decimal: 1.1.1.1.1...</li> | |
| <li>Mixed: 1.2.a.i.A...</li> | |
| <li>Legal: 1.1.1(a)(i)</li> | |
| <li>Outline: I.A.1.a.i.</li> | |
| <li>Section: §1.2.3, Article 1.1.1</li> | |
| </ul> | |
| </div> | |
| </div> | |
| <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: 0.5rem;"> | |
| <div> | |
| <strong>Parenthetical Patterns:</strong> | |
| <ul> | |
| <li>Arabic: (1), (2), (3)</li> | |
| <li>Thai Numerals: (๑), (๒), (๓)</li> | |
| <li>Letters: (a), (b), (A), (B)</li> | |
| <li>Roman: (i), (ii), (I), (II)</li> | |
| <li>Thai Letters: (ก), (ข), (ค)</li> | |
| </ul> | |
| </div> | |
| <div> | |
| <strong>Multi-Language & Symbols:</strong> | |
| <ul> | |
| <li>Thai Script: มาตรา, ข้อ, ก.ข.ค.</li> | |
| <li>Bullets: •◦▪→ and 20+ more</li> | |
| <li>Roman: I.II.III, i.ii.iii</li> | |
| <li>Letters: A.B.C, a.b.c</li> | |
| <li>Checkboxes: [x], [ ], [✓]</li> | |
| </ul> | |
| </div> | |
| </div> | |
| <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: 0.5rem;"> | |
| <div> | |
| <strong>Intelligent Text Classification:</strong> | |
| <ul> | |
| <li>Header Detection: Title case, all caps, short lines</li> | |
| <li>Paragraph Recognition: Long text, proper punctuation</li> | |
| <li>List Item Identification: Patterned content</li> | |
| <li>Context Analysis: Position, font size, formatting</li> | |
| <li>Confidence Scoring: Reliability assessment</li> | |
| <li>OpenCV Bold Detection: {'Enabled' if HAS_OPENCV_SUPPORT else 'Disabled'}</li> | |
| </ul> | |
| </div> | |
| <div> | |
| <strong>Technical Enhancements:</strong> | |
| <ul> | |
| <li><strong>OpenCV Text Block Analysis:</strong> {'Enabled' if HAS_OPENCV_SUPPORT else 'Disabled'}</li> | |
| <li><strong>Bold Text Recognition:</strong> {'Enabled' if HAS_OPENCV_SUPPORT else 'Disabled'}</li> | |
| <li><strong>Header Indentation Suppression:</strong> {'Enabled' if HAS_OPENCV_SUPPORT else 'Disabled'}</li> | |
| <li><strong>Smart Table Detection:</strong> 70% overlap threshold prevents text loss</li> | |
| <li><strong>HTML Processing:</strong> Better structure and formatting preservation</li> | |
| <li><strong>Multi-format Export:</strong> TXT, DOCX, and HTML downloads with preserved indentation</li> | |
| </ul> | |
| </div> | |
| </div> | |
| </div> | |
| """) | |
| # Configuration Panel - Top Left | |
| with gr.Group(elem_classes=["config-panel"]): | |
| gr.HTML("<h3>Configuration Panel</h3>") | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| # File upload | |
| pdf_input = gr.File( | |
| label="Upload PDF File", | |
| file_types=[".pdf"], | |
| file_count="single" | |
| ) | |
| # PDF loading status | |
| pdf_load_status = gr.Textbox( | |
| label="PDF Status", | |
| interactive=False, | |
| lines=1, | |
| value="No PDF loaded" | |
| ) | |
| with gr.Column(scale=1): | |
| # OCR method selection | |
| method_choice = gr.Dropdown( | |
| choices=["auto", "azure", "tesseract", "pymupdf"], | |
| value="auto", | |
| label="OCR Method", | |
| info=f"Choose OCR method (all enhanced with OpenCV {'✅' if HAS_OPENCV_SUPPORT else '❌'} + comprehensive indentation detection and text classification)" | |
| ) | |
| # Method information display | |
| method_info = gr.Markdown( | |
| value=get_opencv_enhanced_method_info("auto"), | |
| elem_classes=["method-info"] | |
| ) | |
| # Enhanced Header/Footer Removal Section | |
| with gr.Group(elem_classes=["crop-controls"]): | |
| gr.HTML("<h4>Header/Footer Removal & Crop Settings with OpenCV Enhancement</h4>") | |
| enable_header_footer_removal = gr.Checkbox( | |
| label="Enable Enhanced Header/Footer Removal with OpenCV Analysis", | |
| value=False, | |
| info=f"Remove headers and footers with high-resolution processing {'+ OpenCV text block analysis' if HAS_OPENCV_SUPPORT else ''}" | |
| ) | |
| # Multi-page controls | |
| with gr.Group(visible=False) as crop_controls: | |
| gr.HTML(f"<h5>Multi-Page Crop Control {'with OpenCV Text Block Overlay' if HAS_OPENCV_SUPPORT else ''}</h5>") | |
| with gr.Row(): | |
| # Page selection | |
| page_selector = gr.Dropdown( | |
| label="Select Page for Preview", | |
| choices=[], | |
| value=None, | |
| info=f"Choose page to preview and customize crop settings {'(with OpenCV overlay)' if HAS_OPENCV_SUPPORT else ''}", | |
| visible=False | |
| ) | |
| # Apply to all pages toggle | |
| apply_to_all_pages = gr.Checkbox( | |
| label="Apply crop settings to all pages", | |
| value=True, | |
| info="When enabled, changes apply to all pages" | |
| ) | |
| if HAS_OPENCV_SUPPORT: | |
| gr.HTML("<h5>OpenCV Visual Indicators</h5>") | |
| gr.HTML(""" | |
| <div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.5rem; font-size: 0.9em;"> | |
| <div style="color: #ff0000;"><strong>🔴 RED:</strong> Crop areas</div> | |
| <div style="color: #00ff00;"><strong>🟢 GREEN:</strong> Content area</div> | |
| <div style="color: #0066ff;"><strong>🔵 BLUE:</strong> Text blocks</div> | |
| <div style="color: #ff6600;"><strong>🟠 ORANGE:</strong> Bold headers</div> | |
| </div> | |
| """) | |
| gr.HTML("<h5>Crop Areas (% of page)</h5>") | |
| with gr.Row(): | |
| crop_top = gr.Slider( | |
| minimum=0, | |
| maximum=40, | |
| value=8, | |
| step=0.5, | |
| label="Top Crop %" | |
| ) | |
| crop_bottom = gr.Slider( | |
| minimum=0, | |
| maximum=40, | |
| value=8, | |
| step=0.5, | |
| label="Bottom Crop %" | |
| ) | |
| with gr.Row(): | |
| crop_left = gr.Slider( | |
| minimum=0, | |
| maximum=30, | |
| value=3, | |
| step=0.5, | |
| label="Left Crop %" | |
| ) | |
| crop_right = gr.Slider( | |
| minimum=0, | |
| maximum=30, | |
| value=3, | |
| step=0.5, | |
| label="Right Crop %" | |
| ) | |
| # Quick preset buttons | |
| with gr.Row(): | |
| preset_light = gr.Button("Light Crop (5%)", size="sm") | |
| preset_medium = gr.Button("Medium Crop (10%)", size="sm") | |
| preset_heavy = gr.Button("Heavy Crop (15%)", size="sm") | |
| preset_reset = gr.Button("Reset", size="sm") | |
| # Process button | |
| process_btn = gr.Button( | |
| f"Process PDF with OpenCV {'✅' if HAS_OPENCV_SUPPORT else '❌'} + Comprehensive Indentation Detection & Text Classification", | |
| variant="primary", | |
| size="lg" | |
| ) | |
| # Results and Preview Section | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| # Enhanced crop preview with OpenCV overlay | |
| with gr.Group(visible=False, elem_classes=["page-preview"]) as preview_group: | |
| gr.HTML(f"<h4>Page Preview with OpenCV-Enhanced Crop Visualization {'& Text Block Overlay' if HAS_OPENCV_SUPPORT else ''}</h4>") | |
| crop_preview = gr.Image( | |
| label="High-Resolution Page Preview with OpenCV Enhancement", | |
| interactive=False, | |
| height=500, | |
| show_label=False | |
| ) | |
| if HAS_OPENCV_SUPPORT: | |
| gr.HTML(""" | |
| <p style="font-size: 0.9em; color: #666; text-align: center;"> | |
| <strong>Red areas:</strong> Will be removed | <strong>Green outline:</strong> Content area | | |
| <strong>Blue rectangles:</strong> OpenCV text blocks | <strong>Orange rectangles:</strong> Bold headers | | |
| <strong>Enhanced:</strong> 2x resolution processing with OpenCV analysis | |
| </p> | |
| """) | |
| else: | |
| gr.HTML(""" | |
| <p style="font-size: 0.9em; color: #666; text-align: center;"> | |
| <strong>Red areas:</strong> Will be removed | <strong>Green outline:</strong> Content area | | |
| <strong>Enhanced:</strong> 2x resolution processing | |
| </p> | |
| """) | |
| with gr.Column(scale=2): | |
| with gr.Group(elem_classes=["results-panel"]): | |
| gr.HTML("<h3>Results & Downloads</h3>") | |
| # Processing status | |
| processing_status = gr.Textbox( | |
| label="Processing Status", | |
| interactive=False, | |
| lines=1 | |
| ) | |
| # Extracted text output | |
| text_output = gr.Textbox( | |
| label=f"Extracted Text (OpenCV {'✅' if HAS_OPENCV_SUPPORT else '❌'} Enhanced with Comprehensive Indentation Detection & Text Classification)", | |
| placeholder=f"Processed text with {'OpenCV text block analysis, bold detection, ' if HAS_OPENCV_SUPPORT else ''}comprehensive indentation detection, intelligent text classification, HTML enhancement, and preserved formatting will appear here...", | |
| lines=20, | |
| max_lines=30, | |
| interactive=False, | |
| show_copy_button=True | |
| ) | |
| # Metadata information | |
| metadata_output = gr.Textbox( | |
| label="Processing Information & Document Analysis", | |
| interactive=False, | |
| lines=10 | |
| ) | |
| # Enhanced download buttons | |
| with gr.Row(): | |
| download_txt_btn = gr.DownloadButton( | |
| "Download Enhanced TXT", | |
| visible=False, | |
| variant="secondary" | |
| ) | |
| download_docx_btn = gr.DownloadButton( | |
| f"Download Enhanced DOCX (with OpenCV {'✅' if HAS_OPENCV_SUPPORT else '❌'} + Indentation & Classification)", | |
| visible=False, | |
| variant="secondary" | |
| ) | |
| download_html_btn = gr.DownloadButton( | |
| "Download HTML File", | |
| visible=False, | |
| variant="secondary" | |
| ) | |
| # Service Status at the bottom | |
| with gr.Group(elem_classes=["status-box"]): | |
| gr.HTML("<h4>Service Status & OpenCV-Enhanced Capabilities</h4>") | |
| service_status = gr.Markdown( | |
| value=check_opencv_enhanced_service_status() | |
| ) | |
| # Refresh status button | |
| refresh_btn = gr.Button("Refresh Status", size="sm") | |
| # Event handlers with OpenCV enhancement | |
| # PDF upload handler | |
| pdf_input.change( | |
| fn=load_pdf_for_preview, | |
| inputs=[pdf_input], | |
| outputs=[crop_preview, page_selector, crop_controls, pdf_load_status] | |
| ) | |
| # Method info handler | |
| method_choice.change( | |
| fn=get_opencv_enhanced_method_info, | |
| inputs=[method_choice], | |
| outputs=[method_info] | |
| ) | |
| # Header/footer removal handler | |
| enable_header_footer_removal.change( | |
| fn=lambda enabled: [ | |
| gr.update(visible=enabled), | |
| gr.update(visible=enabled) | |
| ], | |
| inputs=[enable_header_footer_removal], | |
| outputs=[crop_controls, preview_group] | |
| ) | |
| # Page selection handler | |
| page_selector.change( | |
| fn=change_preview_page, | |
| inputs=[page_selector, crop_top, crop_bottom, crop_left, crop_right], | |
| outputs=[crop_preview] | |
| ) | |
| # Crop parameter handlers - update preview in real-time with OpenCV enhancement | |
| for crop_input in [crop_top, crop_bottom, crop_left, crop_right, apply_to_all_pages]: | |
| crop_input.change( | |
| fn=update_crop_preview_interactive, | |
| inputs=[page_selector, crop_top, crop_bottom, crop_left, crop_right, apply_to_all_pages], | |
| outputs=[crop_preview] | |
| ) | |
| # Preset button handlers | |
| def apply_preset(top, bottom, left, right): | |
| return top, bottom, left, right | |
| preset_light.click( | |
| fn=lambda: apply_preset(5, 5, 2, 2), | |
| outputs=[crop_top, crop_bottom, crop_left, crop_right] | |
| ) | |
| preset_medium.click( | |
| fn=lambda: apply_preset(10, 10, 5, 5), | |
| outputs=[crop_top, crop_bottom, crop_left, crop_right] | |
| ) | |
| preset_heavy.click( | |
| fn=lambda: apply_preset(15, 15, 8, 8), | |
| outputs=[crop_top, crop_bottom, crop_left, crop_right] | |
| ) | |
| preset_reset.click( | |
| fn=lambda: apply_preset(0, 0, 0, 0), | |
| outputs=[crop_top, crop_bottom, crop_left, crop_right] | |
| ) | |
| # Status refresh handler | |
| refresh_btn.click( | |
| fn=check_opencv_enhanced_service_status, | |
| outputs=[service_status] | |
| ) | |
| # Main processing handler with OpenCV enhancement | |
| process_btn.click( | |
| fn=prepare_opencv_enhanced_downloads, | |
| inputs=[pdf_input, method_choice, enable_header_footer_removal, | |
| crop_top, crop_bottom, crop_left, crop_right, | |
| apply_to_all_pages, page_selector], | |
| outputs=[text_output, metadata_output, processing_status, | |
| download_txt_btn, download_docx_btn, download_html_btn] | |
| ) | |
| return interface | |
| def launch_opencv_enhanced_ui(): | |
| """Launch the OpenCV-enhanced Gradio interface with text block analysis and bold detection""" | |
| try: | |
| interface = create_opencv_enhanced_interface() | |
| interface.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| share=False, | |
| show_error=True | |
| ) | |
| finally: | |
| # Clean up resources | |
| pdf_manager.close() | |
| if __name__ == "__main__": | |
| launch_opencv_enhanced_ui() |