AI agents are transforming software development by empowering developers to build complex applications through iterative development, debugging, and optimization. These agents can analyze requirements, propose architectures, generate code, and even troubleshoot issues—dramatically accelerating the development lifecycle.
In this tutorial, we'll explore how to leverage Claude Sonnect 4 to build a sophisticated desktop GUI application from scratch using the Dynamsoft Capture Vision SDK. The result will be a multi-modal computer vision application capable of detecting barcodes/QR codes, normalizing documents, and extracting Machine Readable Zones (MRZ) from passports and ID cards.
Demo: Scan Barcodes, MRZ, and Documents with a Python Desktop App
This demo showcases how AI-assisted development can deliver professional-grade applications that rival commercial solutions.
Prerequisites
- 30-day trial license for Dynamsoft Capture Vision
-
Python dependencies:
dynamsoft-capture-vision-bundle>=2.0.20 PySide6>=6.5.0 opencv-python>=4.8.0 Pillow>=10.0.0 numpy>=1.24.0 facenet-pytorch>=2.5.0 torch>=1.11.0 torchvision>=0.12.0 psutil>=5.9.0
Project Overview
What We Built
A comprehensive desktop application featuring:
- Dual-mode interface: Picture processing and real-time camera capture
- Multi-detection capabilities: Barcodes/QR codes, document normalization, and MRZ reading
- Advanced UI: Tabbed interface with zoom controls, annotation overlays, and export functionality
- Face detection: Integrated MTCNN for passport/ID processing
Technology Stack
- Python 3.11+ - PySide6 (Qt6) for modern GUI - Dynamsoft Capture Vision SDK (The powerhouse behind all detection) - facenet-pytorch for face detection
Why Dynamsoft Capture Vision SDK?
The Dynamsoft Capture Vision SDK is the cornerstone of our application, providing enterprise-grade computer vision capabilities that would be extremely difficult to implement from scratch. Here's why it was the perfect choice:
- Barcode/QR Code Reading: Supports 1D, 2D, and postal codes
- Document Detection: Advanced edge detection and perspective correction
- MRZ Processing: Specialized OCR for Machine Readable Zones with field validation
- Unified API: Single SDK handles multiple detection types seamlessly
- Cross-platform: Consistent performance across Windows, Linux, and macOS
- Flexible Templates: Pre-configured detection templates for common scenarios
- Intermediate Results: Access to detection pipeline stages for custom processing
- Extensive Customization: Fine-tune detection parameters for specific use cases
AI-Assisted Development Workflow
The Iterative Approach
Our development process followed a systematic AI-assisted methodology:
graph TD A[Initial Requirements] --> B[AI Analysis & Planning] B --> C[Code Generation] C --> D[Testing & Validation] D --> E[Issue Identification] E --> F[AI Debugging & Fix] F --> G[Verification] G --> H{More Issues?} H -->|Yes| E H -->|No| I[Feature Enhancement] I --> J[Optimization] J --> K[Final Validation]
AI Agent Collaboration Pattern
- Requirement Analysis: AI breaks down complex requirements into manageable components
- Architecture Design: AI suggests optimal design patterns and project structure
- Code Generation: AI writes initial implementations with proper error handling
- Debugging Partnership: Human identifies issues, AI diagnoses and provides solutions
- Optimization Cycles: AI suggests performance improvements and best practices
Initial Requirements and Architecture
User Requirements
"I want a desktop application that can: - Detect barcodes and QR codes from images and camera - Process documents (scan and normalize) - Read passport/ID card information (MRZ) - Have a modern, user-friendly interface - Support both file upload and real-time camera processing"
AI's Initial Architecture Analysis
The AI agent analyzed these requirements and proposed:
# Core Architecture Components class BarcodeReaderMainWindow(QMainWindow): """Main application window with tabbed interface""" class CameraWidget(QWidget): """Real-time camera capture and processing""" class ImageDisplayWidget(QLabel): """Image display with zoom and annotation capabilities""" class ProcessingWorker(QThread): """Background processing to keep UI responsive""" class MyIntermediateResultReceiver(IntermediateResultReceiver): """SDK integration for advanced processing"""
Iterative Development Process
Phase 1: Basic GUI Structure
AI's First Implementation:
def setup_ui(self): """Setup the main user interface with tabbed layout.""" central_widget = QWidget() self.setCentralWidget(central_widget) # Main layout main_layout = QVBoxLayout(central_widget) # Create tab widget self.tab_widget = QTabWidget() main_layout.addWidget(self.tab_widget) # Create tabs self.picture_tab = self.create_picture_mode_tab() self.camera_tab = self.create_camera_mode_tab() self.tab_widget.addTab(self.picture_tab, "📁 Picture Mode") self.tab_widget.addTab(self.camera_tab, "📷 Camera Mode")
Key AI Decisions:
- Tabbed interface for clear mode separation
- Responsive layout with proper widget sizing
- Consistent styling and iconography
Phase 2: SDK Integration
Challenge: Complex Dynamsoft SDK integration
AI Solution: Proper license management and error handling
def initialize_license_once(): """Initialize Dynamsoft license globally, only once.""" global _LICENSE_INITIALIZED if not _LICENSE_INITIALIZED: try: error_code, error_message = LicenseManager.init_license(LICENSE_KEY) if error_code == EnumErrorCode.EC_OK or error_code == EnumErrorCode.EC_LICENSE_CACHE_USED: _LICENSE_INITIALIZED = True print("✅ Dynamsoft license initialized successfully!") return True else: print(f"❌ License initialization failed: {error_code}, {error_message}") return False except Exception as e: print(f"❌ Error initializing license: {e}") return False return True
Phase 3: Camera Integration
Challenge: Real-time camera processing with Qt integration
AI Approach: Hybrid OpenCV/Qt solution
def update_frame(self): """Update camera frame display with real-time results fetching.""" if not self.camera_running or not self.opencv_capture: return try: ret, frame = self.opencv_capture.read() if not ret: return # Store the raw frame for detection processing with QMutexLocker(self.frame_mutex): self.current_frame = frame.copy() # Send frame for detection if enabled if self.detection_enabled and self.frame_fetcher: try: image_data = convertMat2ImageData(frame) self.frame_fetcher.add_frame(image_data) except Exception as e: pass # Silently ignore frame processing errors # Process and display results self.display_annotated_frame(frame) except Exception as e: pass # Silently ignore frame update errors
Key Technical Challenges and Solutions
Challenge 1: Directory Tracking for User Experience
Problem: File dialogs always opening in current directory
AI Enhancement: Persistent directory tracking
def update_last_used_directory(self, file_path): """Update the last used directory from a file path.""" if file_path: directory = os.path.dirname(os.path.abspath(file_path)) self.last_used_directory = directory print(f"📁 Updated last used directory to: {directory}") def get_last_used_directory(self): """Get the last used directory, or current directory if none.""" return self.last_used_directory if self.last_used_directory else os.getcwd()
Challenge 2: Multi-Threading for UI Responsiveness
Problem: Heavy processing blocking the UI
AI Solution: QThread-based background processing
class ProcessingWorker(QThread): """Worker thread for detection processing to keep UI responsive.""" # Define signals finished = Signal(object) # Processing results error = Signal(str) # Error message progress = Signal(str) # Progress message def run(self): """Run detection in background thread.""" try: mode_name = self.detection_mode.split(" - ")[0] if " - " in self.detection_mode else self.detection_mode self.progress.emit(f"🔍 Starting {mode_name} detection...") # Get the appropriate template for the detection mode template = DETECTION_MODES[mode_name]["template"] results = self.cvr_instance.capture_multi_pages(self.file_path, template) self.finished.emit(results) except Exception as e: self.error.emit(str(e))
Challenge 3: Complex Result Handling
Problem: Different result types for different detection modes
AI Approach: Unified result processing pipeline
def on_processing_finished(self, results): """Handle completion of detection processing.""" try: # Get current detection mode current_mode_text = self.picture_detection_mode_combo.currentText() mode_name = current_mode_text.split(" - ")[0] result_list = results.get_results() # Build the page mapping from results to maintain correct order for i, result in enumerate(result_list): if result.get_error_code() == EnumErrorCode.EC_OK: # Extract items based on detection mode items = [] if mode_name == "Barcode": items = result.get_items() elif mode_name == "Document": processed_doc_result = result.get_processed_document_result() if processed_doc_result: items = processed_doc_result.get_deskewed_image_result_items() elif mode_name == "MRZ": # Handle both text lines and parsed results line_result = result.get_recognized_text_lines_result() if line_result: items.extend(line_result.get_items()) parsed_result = result.get_parsed_result() if parsed_result: items.extend(parsed_result.get_items()) # Store results for display self.page_results[i] = items
Code Architecture and Design Patterns
1. Model-View-Controller (MVC) Pattern
# Model: Data handling and SDK integration class DataManager: def __init__(self): self.cvr_instance = CaptureVisionRouter() self.current_pages = {} self.detection_results = {} # View: UI components class BarcodeReaderMainWindow(QMainWindow): # Main view class CameraWidget(QWidget): # Camera view class ImageDisplayWidget(QLabel): # Image display view # Controller: Business logic and event handling def process_current_file(self): # File processing controller def on_detection_mode_changed(self): # Mode switching controller
2. Observer Pattern for Real-time Updates
class CameraWidget(QWidget): # Signals for loose coupling barcodes_detected = Signal(list) frame_processed = Signal(object) error_occurred = Signal(str) def update_frame(self): # Emit signals for observers if latest_items: self.barcodes_detected.emit(latest_items) self.frame_processed.emit(display_frame)
3. Factory Pattern for Detection Modes
DETECTION_MODES = { "Barcode": { "template": EnumPresetTemplate.PT_READ_BARCODES.value, "description": "Detect barcodes and QR codes" }, "Document": { "template": EnumPresetTemplate.PT_DETECT_AND_NORMALIZE_DOCUMENT.value, "description": "Detect and normalize documents" }, "MRZ": { "template": "ReadPassportAndId", "description": "Read passport and ID cards (MRZ)" } }
4. Strategy Pattern for Export Formats
class ExportStrategy: def export(self, data, file_path): raise NotImplementedError class TextExporter(ExportStrategy): def export(self, data, file_path): # Text export implementation pass class CSVExporter(ExportStrategy): def export(self, data, file_path): # CSV export implementation pass class JSONExporter(ExportStrategy): def export(self, data, file_path): # JSON export implementation pass
Performance Optimization
Memory Management
def cleanup_old_barcode_colors(): """Remove barcode colors for barcodes not seen recently.""" current_time = time.time() expired_barcodes = [] for barcode_text, last_seen in BARCODE_LAST_SEEN.items(): if current_time - last_seen > 10: # Remove after 10 seconds expired_barcodes.append(barcode_text) for barcode_text in expired_barcodes: BARCODE_COLORS.pop(barcode_text, None) BARCODE_LAST_SEEN.pop(barcode_text, None)
Efficient Frame Processing
def update_frame(self): """Optimized frame processing with minimal allocations.""" if not self.camera_running or not self.opencv_capture: return try: ret, frame = self.opencv_capture.read() if not ret: return # Efficient frame copying with mutex protection with QMutexLocker(self.frame_mutex): self.current_frame = frame.copy() # Non-blocking detection processing if self.detection_enabled and self.frame_fetcher: try: image_data = convertMat2ImageData(frame) self.frame_fetcher.add_frame(image_data) except Exception: pass # Continue processing even if detection fails
Running the Application
# Install dependencies pip install -r requirements.txt # Run the application python main.py
Source Code
https://github.com/yushulx/python-barcode-qrcode-sdk/tree/main/examples/official/dcv
Top comments (0)