引言:工业级扫码的技术演进与挑战

在物流仓储、零售结算、资产管理等工业场景中,二维码/条码扫描技术是数字化升级的核心环节。传统的扫码方案面临诸多挑战:光线变化、条码污损、运动模糊、远距离识别等。本文将深入探讨如何结合CameraX的高性能相机控制与ML Kit的强大机器学习能力,构建一个工业级的扫码解决方案。

第一章:架构设计 - 工业级扫码系统的七大要素

1.1 工业场景的技术挑战分析

挑战维度 传统方案问题 CameraX+ML Kit解决方案
识别距离 固定焦距,无法自适应 自动变焦+数字变焦组合
环境光线 依赖外部补光 HDR+多帧合成降噪
运动模糊 要求完全静止 运动补偿+陀螺仪辅助
多码同框 只能识别单个 批量识别+区域优先级
角度倾斜 垂直角度限制小 3D空间角度补偿
污损遮挡 识别率骤降 局部特征匹配+AI修复
实时性能 延迟高,CPU占用大 GPU加速+智能帧选择

1.2 分层架构设计

┌─────────────────────────────────────┐
│       应用层:业务逻辑与UI           │
├─────────────────────────────────────┤
│    服务层:扫码服务管理与调度        │
│  ┌─────────────────────────────┐   │
│  │  批量任务队列 │ 优先级调度   │   │
│  └─────────────────────────────┘   │
├─────────────────────────────────────┤
│    识别引擎层:ML Kit智能识别        │
│  ┌─────────────────────────────┐   │
│  │ 多格式支持 │ 角度补偿 │ AI增强│   │
│  └─────────────────────────────┘   │
├─────────────────────────────────────┤
│  图像处理层:CameraX实时处理        │
│  ┌─────────────────────────────┐   │
│  │ 图像增强 │ 运动补偿 │ ROI提取│   │
│  └─────────────────────────────┘   │
├─────────────────────────────────────┤
│    硬件控制层:CameraX相机控制      │
│  ┌─────────────────────────────┐   │
│  │ 自动对焦 │ 曝光补偿 │ 变焦   │   │
│  └─────────────────────────────┘   │
├─────────────────────────────────────┤
│      传感器融合层                   │
│  ┌─────────────────────────────┐   │
│  │ 陀螺仪 │ 距离传感器 │ 光线传感器│ │
│  └─────────────────────────────┘   │
└─────────────────────────────────────┘

第二章:CameraX相机配置 - 工业级优化

2.1 多模式相机配置策略

class IndustrialCameraConfigurator(context: Context) {
    
    enum class ScanMode {
        CLOSE_RANGE,      // 近距离高精度
        LONG_RANGE,       // 远距离识别
        HIGH_SPEED,       // 高速流水线
        LOW_LIGHT,        // 低光照环境
        MULTI_CODE        // 多码同框
    }
    
    fun configureCamera(mode: ScanMode): CameraConfig {
        return when (mode) {
            ScanMode.CLOSE_RANGE -> createCloseRangeConfig()
            ScanMode.LONG_RANGE -> createLongRangeConfig()
            ScanMode.HIGH_SPEED -> createHighSpeedConfig()
            ScanMode.LOW_LIGHT -> createLowLightConfig()
            ScanMode.MULTI_CODE -> createMultiCodeConfig()
        }
    }
    
    private fun createCloseRangeConfig(): CameraConfig {
        return CameraConfig(
            preview = Preview.Builder()
                .setTargetResolution(Size(1920, 1080))
                .setTargetAspectRatio(AspectRatio.RATIO_16_9)
                .build(),
            
            imageAnalysis = ImageAnalysis.Builder()
                .setTargetResolution(Size(1280, 720)) // 平衡性能与精度
                .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
                .setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_YUV_420_888)
                .build(),
            
            imageCapture = ImageCapture.Builder()
                .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
                .setTargetResolution(Size(4032, 3024)) // 备用高分辨率
                .build(),
            
            cameraControl = CameraControl.Builder()
                .setZoomRatio(1.0f) // 标准焦距
                .setLinearZoom(0.0f)
                .build(),
            
            scanArea = RectF(0.3f, 0.3f, 0.7f, 0.7f) // 中心区域扫描
        )
    }
    
    private fun createLongRangeConfig(): CameraConfig {
        return CameraConfig(
            preview = Preview.Builder()
                .setTargetResolution(Size(3840, 2160)) // 4K用于远距离
                .build(),
            
            imageAnalysis = ImageAnalysis.Builder()
                .setTargetResolution(Size(1920, 1080))
                .setBackpressureStrategy(ImageAnalysis.STRATEGY_BLOCK_PRODUCER)
                .setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_YUV_420_888)
                .build(),
            
            cameraControl = CameraControl.Builder()
                .setZoomRatio(2.0f) // 数字变焦
                .build(),
            
            // 启用自动变焦搜索
            autoZoomEnabled = true,
            zoomSearchRange = 1.0f..4.0f
        )
    }
    
    private fun createHighSpeedConfig(): CameraConfig {
        return CameraConfig(
            imageAnalysis = ImageAnalysis.Builder()
                .setTargetResolution(Size(960, 540)) // 低分辨率提升帧率
                .setBackpressureStrategy(ImageAnalysis.STRATEGY_DROP_LATEST)
                .setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_YUV_420_888)
                .build(),
            
            // 高帧率模式
            targetFrameRate = Range(60, 60),
            
            // 运动预测
            motionPredictionEnabled = true,
            predictionHistorySize = 5
        )
    }
}

2.2 智能对焦策略实现

class IntelligentFocusController(
    private val cameraControl: CameraControl,
    private val cameraInfo: CameraInfo
) {
    
    private var currentFocusState = FocusState.IDLE
    private val focusHistory = ArrayDeque<FocusResult>(10)
    private var lastSuccessfulFocusDistance = 0.0f
    
    enum class FocusState {
        IDLE,              // 空闲状态
        SCANNING,          // 正在对焦搜索
        LOCKED,            // 对焦锁定
        TRACKING,          // 追踪模式
        FAILED             // 对焦失败
    }
    
    data class FocusResult(
        val distance: Float,
        val confidence: Float,
        val timestamp: Long
    )
    
    /**
     * 工业级对焦策略:根据条码特征优化对焦
     */
    fun optimizeFocusForBarcode(
        detectedBarcodes: List<Barcode>,
        frameMetadata: FrameMetadata
    ): ListenableFuture<FocusResult> {
        val future = SettableFuture.create<FocusResult>()
        
        if (detectedBarcodes.isEmpty()) {
            // 没有检测到条码,使用区域对比度对焦
            performContrastFocus(frameMetadata, future)
        } else {
            // 基于条码位置和大小进行对焦
            val primaryBarcode = selectPrimaryBarcode(detectedBarcodes)
            performBarcodeAwareFocus(primaryBarcode, frameMetadata, future)
        }
        
        return future
    }
    
    private fun performContrastFocus(
        metadata: FrameMetadata,
        future: SettableFuture<FocusResult>
    ) {
        // 获取当前对焦距离
        val currentFocusDistance = cameraInfo.focusState.value?.lensFocusDistance ?: 0f
        
        // 使用爬山算法寻找最佳对焦位置
        val focusMeter = ContrastFocusMeter()
        
        // 定义对焦搜索范围
        val searchRange = if (lastSuccessfulFocusDistance > 0) {
            // 基于上次成功对焦进行微调
            val min = max(0.1f, lastSuccessfulFocusDistance * 0.8f)
            val max = min(10.0f, lastSuccessfulFocusDistance * 1.2f)
            min..max
        } else {
            // 全范围搜索
            0.1f..10.0f
        }
        
        // 执行对焦搜索
        val optimalFocus = findOptimalFocusByContrast(
            focusMeter, 
            searchRange, 
            step = 0.2f
        )
        
        // 应用对焦
        val focusRequest = FocusRequest.Builder(
            CameraControl.AF_MODE_AUTO,
            optimalFocus.distance
        ).build()
        
        cameraControl.setFocusRequest(focusRequest)
            .addListener({
                future.set(FocusResult(
                    distance = optimalFocus.distance,
                    confidence = optimalFocus.confidence,
                    timestamp = System.currentTimeMillis()
                ))
            }, CameraXExecutors.mainThreadExecutor())
    }
    
    private fun performBarcodeAwareFocus(
        barcode: Barcode,
        metadata: FrameMetadata,
        future: SettableFuture<FocusResult>
    ) {
        // 计算条码在图像中的尺寸占比
        val barcodeArea = barcode.boundingBox?.width()?.times(
            barcode.boundingBox.height()
        ) ?: 0
        
        val frameArea = metadata.width * metadata.height
        val areaRatio = barcodeArea.toFloat() / frameArea.toFloat()
        
        // 根据条码大小估算距离
        val estimatedDistance = estimateDistanceFromBarcodeSize(
            barcode.format,
            barcodeArea,
            areaRatio
        )
        
        // 条码清晰度评估
        val sharpnessScore = evaluateBarcodeSharpness(barcode, metadata)
        
        if (sharpnessScore < 0.7f) {
            // 清晰度不足,需要重新对焦
            val focusRequest = FocusRequest.Builder(
                CameraControl.AF_MODE_AUTO,
                estimatedDistance
            ).setFocusPriority(CameraControl.FOCUS_PRIORITY_HIGH)
             .build()
            
            cameraControl.setFocusRequest(focusRequest)
                .addListener({
                    // 验证对焦后条码清晰度
                    val newSharpness = evaluateBarcodeSharpness(barcode, metadata)
                    future.set(FocusResult(
                        distance = estimatedDistance,
                        confidence = newSharpness,
                        timestamp = System.currentTimeMillis()
                    ))
                }, CameraXExecutors.mainThreadExecutor())
        } else {
            // 清晰度足够,保持当前对焦
            future.set(FocusResult(
                distance = estimatedDistance,
                confidence = sharpnessScore,
                timestamp = System.currentTimeMillis()
            ))
        }
    }
    
    /**
     * 自动变焦搜索:远距离条码识别
     */
    fun performZoomSearch(
        startZoom: Float = 1.0f,
        endZoom: Float = 4.0f,
        step: Float = 0.5f
    ): ListenableFuture<Float> {
        val future = SettableFuture.create<Float>()
        
        // 使用二分搜索找到最佳变焦位置
        binarySearchOptimalZoom(startZoom, endZoom, step) { zoomRatio ->
            cameraControl.setZoomRatio(zoomRatio)
            // 返回该变焦下的条码识别置信度
            evaluateFrameQuality()
        }.addListener({
            future.set(it.get())
        }, CameraXExecutors.mainThreadExecutor())
        
        return future
    }
    
    private fun evaluateFrameQuality(): Float {
        // 综合评估帧质量:对比度、噪声、运动模糊
        return 0.8f // 简化实现
    }
}

第三章:ML Kit条码识别 - 高级配置与优化

3.1 工业级条码识别器配置

class IndustrialBarcodeScanner {
    
    private lateinit var barcodeScanner: BarcodeScanner
    private var processingQueue = LinkedBlockingQueue<BarcodeTask>()
    private var isProcessing = AtomicBoolean(false)
    
    // 支持的条码格式(工业场景常见格式)
    private val industrialFormats = arrayOf(
        Barcode.FORMAT_CODE_128,
        Barcode.FORMAT_CODE_39,
        Barcode.FORMAT_CODE_93,
        Barcode.FORMAT_CODABAR,
        Barcode.FORMAT_DATA_MATRIX,
        Barcode.FORMAT_EAN_13,
        Barcode.FORMAT_EAN_8,
        Barcode.FORMAT_ITF,
        Barcode.FORMAT_QR_CODE,
        Barcode.FORMAT_UPC_A,
        Barcode.FORMAT_UPC_E,
        Barcode.FORMAT_PDF417,
        Barcode.FORMAT_AZTEC,
        Barcode.FORMAT_ALL_FORMATS
    )
    
    fun initialize(context: Context, config: BarcodeScannerConfig) {
        val options = BarcodeScannerOptions.Builder()
            .setBarcodeFormats(*industrialFormats)
            .enableAllPotentialBarcodes() // 启用所有潜在条码检测
            .setExecutor(Executors.newSingleThreadExecutor { 
                Thread(it, "Barcode-Processor").apply {
                    priority = Thread.MAX_PRIORITY
                }
            })
            
        // 性能与精度权衡配置
        when (config.scanMode) {
            ScanMode.HIGH_SPEED -> {
                options
                    .setPerformanceMode(BarcodeScannerOptions.PERFORMANCE_MODE_FAST)
                    .setBarcodeImageMode(BarcodeScannerOptions.BARCODE_IMAGE_MODE_SINGLE_IMAGE)
            }
            ScanMode.HIGH_ACCURACY -> {
                options
                    .setPerformanceMode(BarcodeScannerOptions.PERFORMANCE_MODE_ACCURATE)
                    .setBarcodeImageMode(BarcodeScannerOptions.BARCODE_IMAGE_MODE_CENTER_CROP)
            }
            ScanMode.LOW_LIGHT -> {
                options
                    .setPerformanceMode(BarcodeScannerOptions.PERFORMANCE_MODE_FAST)
                    .enableEnhancedScan() // 启用增强扫描(需要额外依赖)
            }
        }
        
        // 设置识别区域(ROI)
        if (config.scanArea != null) {
            options.setScanArea(config.scanArea)
        }
        
        // 置信度阈值
        options.setConfidenceThreshold(config.confidenceThreshold)
        
        barcodeScanner = BarcodeScanning.getClient(options.build())
    }
    
    /**
     * 批量识别:处理多码同框场景
     */
    fun processBatch(
        images: List<ImageProxy>,
        callback: (List<BarcodeResult>) -> Unit
    ) {
        val tasks = images.map { image ->
            BarcodeTask(
                image = image,
                timestamp = System.currentTimeMillis(),
                priority = calculatePriority(image)
            )
        }
        
        processingQueue.addAll(tasks)
        processNext(callback)
    }
    
    private fun processNext(callback: (List<BarcodeResult>) -> Unit) {
        if (isProcessing.compareAndSet(false, true)) {
            val task = processingQueue.poll()
            if (task != null) {
                processSingleImage(task.image)
                    .addOnSuccessListener { barcodes ->
                        val results = barcodes.map { barcode ->
                            BarcodeResult(
                                barcode = barcode,
                                imageTimestamp = task.timestamp,
                                processingLatency = System.currentTimeMillis() - task.timestamp,
                                confidence = calculateBarcodeConfidence(barcode)
                            )
                        }
                        
                        callback(results)
                        isProcessing.set(false)
                        
                        // 处理下一个
                        if (!processingQueue.isEmpty()) {
                            processNext(callback)
                        }
                    }
                    .addOnFailureListener { e ->
                        Log.e("BarcodeScanner", "识别失败", e)
                        isProcessing.set(false)
                        processNext(callback)
                    }
            } else {
                isProcessing.set(false)
            }
        }
    }
    
    /**
     * 增强识别:对低质量条码进行AI增强
     */
    fun enhancedScan(image: ImageProxy): ListenableFuture<EnhancedBarcodeResult> {
        val future = SettableFuture.create<EnhancedBarcodeResult>()
        
        // 步骤1:原始识别
        barcodeScanner.process(image.toInputImage())
            .addOnSuccessListener { barcodes ->
                if (barcodes.isNotEmpty()) {
                    val primaryBarcode = barcodes[0]
                    
                    // 步骤2:质量评估
                    val qualityScore = evaluateBarcodeQuality(primaryBarcode, image)
                    
                    if (qualityScore < 0.6f) {
                        // 质量不足,进行AI增强
                        performAIEnhancement(image, primaryBarcode)
                            .addOnSuccessListener { enhanced ->
                                future.set(EnhancedBarcodeResult(
                                    original = primaryBarcode,
                                    enhanced = enhanced,
                                    qualityImprovement = enhanced.confidence - primaryBarcode.confidence,
                                    processingTime = System.currentTimeMillis() - image.imageInfo.timestamp
                                ))
                            }
                    } else {
                        future.set(EnhancedBarcodeResult(
                            original = primaryBarcode,
                            enhanced = primaryBarcode,
                            qualityImprovement = 0f,
                            processingTime = System.currentTimeMillis() - image.imageInfo.timestamp
                        ))
                    }
                } else {
                    future.setException(NoBarcodeFoundException())
                }
            }
            .addOnFailureListener { e ->
                future.setException(e)
            }
        
        return future
    }
    
    private fun performAIEnhancement(
        image: ImageProxy,
        barcode: Barcode
    ): Task<Barcode> {
        return Tasks.call(Executors.newSingleThreadExecutor()) {
            // 提取条码区域
            val barcodeRegion = extractBarcodeRegion(image, barcode.boundingBox)
            
            // 应用图像增强
            val enhancedRegion = applyImageEnhancement(barcodeRegion, listOf(
                EnhancementOperation.CONTRAST_STRETCHING,
                EnhancementOperation.NOISE_REDUCTION,
                EnhancementOperation.SHARPENING,
                EnhancementOperation.PERSPECTIVE_CORRECTION
            ))
            
            // 重新识别
            val result = barcodeScanner.process(enhancedRegion.toInputImage()).result
            result?.firstOrNull() ?: throw EnhancementFailedException()
        }
    }
    
    /**
     * 条码质量评估体系
     */
    private fun evaluateBarcodeQuality(barcode: Barcode, image: ImageProxy): Float {
        var totalScore = 0f
        
        // 1. 对比度得分
        val contrastScore = calculateContrastScore(barcode, image)
        totalScore += contrastScore * 0.3f
        
        // 2. 清晰度得分(边缘锐度)
        val sharpnessScore = calculateSharpnessScore(barcode, image)
        totalScore += sharpnessScore * 0.3f
        
        // 3. 完整性得分(条码是否完整)
        val completenessScore = calculateCompletenessScore(barcode)
        totalScore += completenessScore * 0.2f
        
        // 4. 角度得分(倾斜角度)
        val angleScore = calculateAngleScore(barcode)
        totalScore += angleScore * 0.1f
        
        // 5. 大小得分(在图像中的占比)
        val sizeScore = calculateSizeScore(barcode, image.width, image.height)
        totalScore += sizeScore * 0.1f
        
        return totalScore.coerceIn(0f, 1f)
    }
}

3.2 多码识别与优先级处理

class MultiBarcodeProcessor {
    
    data class BarcodeCluster(
        val barcodes: List<Barcode>,
        val clusterCenter: Point,
        val timestamp: Long
    )
    
    /**
     * 多码同框识别与去重
     */
    fun processMultipleBarcodes(
        detectedBarcodes: List<Barcode>,
        frameTimestamp: Long
    ): ProcessedBarcodeResult {
        if (detectedBarcodes.isEmpty()) {
            return ProcessedBarcodeResult.empty()
        }
        
        // 步骤1:条码聚类(防止同一条码多次识别)
        val clusters = clusterBarcodes(detectedBarcodes)
        
        // 步骤2:选择主要条码(基于业务规则)
        val primaryBarcode = selectPrimaryBarcode(clusters)
        
        // 步骤3:验证条码有效性
        val validBarcodes = validateBarcodes(clusters)
        
        // 步骤4:格式化结果
        val formattedResults = formatBarcodeResults(validBarcodes)
        
        return ProcessedBarcodeResult(
            primary = primaryBarcode,
            secondary = validBarcodes.filter { it != primaryBarcode },
            totalCount = validBarcodes.size,
            timestamp = frameTimestamp,
            clusterInfo = clusters
        )
    }
    
    private fun clusterBarcodes(barcodes: List<Barcode>): List<BarcodeCluster> {
        val clusters = mutableListOf<BarcodeCluster>()
        val visited = BooleanArray(barcodes.size)
        
        for (i in barcodes.indices) {
            if (!visited[i]) {
                val cluster = mutableListOf(barcodes[i])
                visited[i] = true
                
                // 寻找相邻条码(基于位置和内容)
                for (j in i + 1 until barcodes.size) {
                    if (!visited[j] && areBarcodesAdjacent(barcodes[i], barcodes[j])) {
                        cluster.add(barcodes[j])
                        visited[j] = true
                    }
                }
                
                // 计算聚类中心
                val center = calculateClusterCenter(cluster)
                clusters.add(BarcodeCluster(cluster, center, System.currentTimeMillis()))
            }
        }
        
        return clusters
    }
    
    private fun selectPrimaryBarcode(clusters: List<BarcodeCluster>): Barcode? {
        if (clusters.isEmpty()) return null
        
        // 业务规则:选择优先级最高的条码
        return clusters.flatMap { it.barcodes }
            .maxByOrNull { calculateBarcodePriority(it) }
    }
    
    private fun calculateBarcodePriority(barcode: Barcode): Float {
        var priority = 0f
        
        // 1. 格式优先级(QR Code > Code128 > ...)
        priority += getFormatPriority(barcode.format) * 0.3f
        
        // 2. 位置优先级(中心区域优先)
        priority += getPositionPriority(barcode.boundingBox) * 0.3f
        
        // 3. 大小优先级(大小适中优先)
        priority += getSizePriority(barcode.boundingBox) * 0.2f
        
        // 4. 置信度优先级
        priority += (barcode.confidence ?: 0.5f) * 0.2f
        
        return priority
    }
    
    /**
     * 条码追踪:连续帧中的条码跟踪
     */
    class BarcodeTracker {
        private val trackedBarcodes = mutableMapOf<String, TrackedBarcode>()
        private val maxTrackingAge = 1000L // 1秒
        
        data class TrackedBarcode(
            val barcode: Barcode,
            val firstSeen: Long,
            var lastSeen: Long,
            var positionHistory: MutableList<Point> = mutableListOf(),
            var confidenceHistory: MutableList<Float> = mutableListOf()
        )
        
        fun update(frameBarcodes: List<Barcode>, timestamp: Long): List<TrackedBarcode> {
            // 清理过期的追踪
            cleanupExpiredTracks(timestamp)
            
            // 关联现有追踪
            val matched = matchTracks(frameBarcodes, timestamp)
            
            // 创建新追踪
            createNewTracks(frameBarcodes, timestamp, matched)
            
            return trackedBarcodes.values.toList()
        }
        
        private fun matchTracks(
            frameBarcodes: List<Barcode>, 
            timestamp: Long
        ): Set<String> {
            val matchedIds = mutableSetOf<String>()
            
            for ((id, track) in trackedBarcodes) {
                // 预测当前位置(基于运动模型)
                val predictedPosition = predictNextPosition(track)
                
                // 寻找最近的条码
                val nearestBarcode = findNearestBarcode(
                    frameBarcodes, 
                    predictedPosition,
                    track.barcode.format
                )
                
                if (nearestBarcode != null) {
                    // 更新追踪
                    track.barcode = nearestBarcode
                    track.lastSeen = timestamp
                    track.positionHistory.add(calculateCenter(nearestBarcode.boundingBox))
                    track.confidenceHistory.add(nearestBarcode.confidence ?: 0.5f)
                    
                    matchedIds.add(id)
                }
            }
            
            return matchedIds
        }
        
        private fun predictNextPosition(track: TrackedBarcode): Point {
            if (track.positionHistory.size < 2) {
                return calculateCenter(track.barcode.boundingBox)
            }
            
            // 简单线性预测
            val lastPos = track.positionHistory.last()
            val secondLastPos = track.positionHistory[track.positionHistory.size - 2]
            
            val dx = lastPos.x - secondLastPos.x
            val dy = lastPos.y - secondLastPos.y
            
            return Point(lastPos.x + dx, lastPos.y + dy)
        }
    }
}

第四章:图像预处理管道 - 工业级增强

4.1 实时图像增强流水线

class IndustrialImageEnhancementPipeline {
    
    private val enhancementStages = mutableListOf<EnhancementStage>()
    private val gpuProcessor: GPUImageProcessor? = null
    
    init {
        // 构建增强流水线
        buildEnhancementPipeline()
    }
    
    private fun buildEnhancementPipeline() {
        // 阶段1:噪声抑制
        enhancementStages.add(EnhancementStage(
            name = "NoiseReduction",
            processor = { image -> applyBilateralFilter(image, 3.0, 25.0) },
            enabled = true,
            priority = 10
        ))
        
        // 阶段2:对比度增强
        enhancementStages.add(EnhancementStage(
            name = "ContrastEnhancement",
            processor = { image -> applyCLAHE(image, 2.0, Size(8, 8)) },
            enabled = true,
            priority = 20
        ))
        
        // 阶段3:锐化
        enhancementStages.add(EnhancementStage(
            name = "Sharpening",
            processor = { image -> applyUnsharpMask(image, 1.5, 1.0, 10) },
            enabled = true,
            priority = 30
        ))
        
        // 阶段4:透视校正
        enhancementStages.add(EnhancementStage(
            name = "PerspectiveCorrection",
            processor = { image -> applyPerspectiveCorrection(image) },
            enabled = false, // 按需启用
            priority = 40
        ))
        
        // 阶段5:条码区域提取
        enhancementStages.add(EnhancementStage(
            name = "ROIExtraction",
            processor = { image -> extractROI(image, scanArea) },
            enabled = true,
            priority = 50
        ))
    }
    
    fun processImage(
        image: ImageProxy,
        metadata: FrameMetadata
    ): EnhancedImageResult {
        val startTime = System.nanoTime()
        var processedImage = image
        
        // 按优先级排序并处理
        val enabledStages = enhancementStages
            .filter { it.enabled }
            .sortedBy { it.priority }
        
        val stageResults = mutableListOf<StageResult>()
        
        for (stage in enabledStages) {
            val stageStart = System.nanoTime()
            
            try {
                processedImage = stage.processor(processedImage)
                
                stageResults.add(StageResult(
                    stageName = stage.name,
                    processingTime = (System.nanoTime() - stageStart) / 1_000_000.0,
                    success = true
                ))
            } catch (e: Exception) {
                stageResults.add(StageResult(
                    stageName = stage.name,
                    processingTime = (System.nanoTime() - stageStart) / 1_000_000.0,
                    success = false,
                    error = e.message
                ))
                
                // 失败时跳过后续阶段
                break
            }
        }
        
        val totalTime = (System.nanoTime() - startTime) / 1_000_000.0
        
        return EnhancedImageResult(
            image = processedImage,
            originalImage = image,
            processingTime = totalTime,
            stageResults = stageResults,
            qualityMetrics = calculateQualityMetrics(processedImage)
        )
    }
    
    /**
     * 自适应增强:根据条码特征调整参数
     */
    fun adaptiveEnhance(
        image: ImageProxy,
        detectedBarcodes: List<Barcode>
    ): ImageProxy {
        if (detectedBarcodes.isEmpty()) {
            // 没有检测到条码,应用标准增强
            return processImage(image, FrameMetadata()).image
        }
        
        // 分析条码特征
        val barcodeFeatures = analyzeBarcodeFeatures(detectedBarcodes)
        
        // 动态调整增强参数
        adjustEnhancementParameters(barcodeFeatures)
        
        // 应用增强
        return processImage(image, FrameMetadata(
            barcodeCount = detectedBarcodes.size,
            averageConfidence = detectedBarcodes.map { it.confidence ?: 0f }.average()
        )).image
    }
    
    private fun analyzeBarcodeFeatures(barcodes: List<Barcode>): BarcodeFeatures {
        return BarcodeFeatures(
            formatDistribution = barcodes.groupBy { it.format }.mapValues { it.value.size },
            averageSize = barcodes.mapNotNull { it.boundingBox?.width()?.times(it.boundingBox.height()) }.average(),
            positionSpread = calculatePositionSpread(barcodes),
            confidenceStats = ConfidenceStats(
                min = barcodes.minOf { it.confidence ?: 0f },
                max = barcodes.maxOf { it.confidence ?: 0f },
                average = barcodes.map { it.confidence ?: 0f }.average()
            )
        )
    }
    
    private fun adjustEnhancementParameters(features: BarcodeFeatures) {
        // 根据条码特征调整增强参数
        
        // 1. 调整噪声抑制强度
        val noiseStage = enhancementStages.find { it.name == "NoiseReduction" }
        noiseStage?.let { stage ->
            // 低置信度条码需要更强的噪声抑制
            if (features.confidenceStats.average < 0.6) {
                stage.parameters["sigmaColor"] = 35.0
                stage.parameters["sigmaSpace"] = 5.0
            } else {
                stage.parameters["sigmaColor"] = 25.0
                stage.parameters["sigmaSpace"] = 3.0
            }
        }
        
        // 2. 调整对比度增强
        val contrastStage = enhancementStages.find { it.name == "ContrastEnhancement" }
        contrastStage?.let { stage ->
            // 小条码需要更强的对比度
            if (features.averageSize < 1000) {
                stage.parameters["clipLimit"] = 3.0
            } else {
                stage.parameters["clipLimit"] = 2.0
            }
        }
        
        // 3. 启用/禁用透视校正
        val perspectiveStage = enhancementStages.find { it.name == "PerspectiveCorrection" }
        perspectiveStage?.enabled = features.positionSpread > 0.3
    }
}

4.2 GPU加速图像处理

class GPUAcceleratedEnhancer(context: Context) {
    
    private val eglCore: EGLCore
    private val shaderPrograms = mutableMapOf<String, Int>()
    
    init {
        // 初始化OpenGL ES环境
        eglCore = EGLCore(null, EGLCore.FLAG_RECORDABLE)
        
        // 编译着色器程序
        compileShaders()
    }
    
    private fun compileShaders() {
        // 噪声抑制着色器
        shaderPrograms["bilateral"] = compileProgram(
            vertexShader = BILATERAL_VERTEX_SHADER,
            fragmentShader = BILATERAL_FRAGMENT_SHADER
        )
        
        // 对比度增强着色器
        shaderPrograms["contrast"] = compileProgram(
            vertexShader = CONTRAST_VERTEX_SHADER,
            fragmentShader = CONTRAST_FRAGMENT_SHADER
        )
        
        // 锐化着色器
        shaderPrograms["sharpen"] = compileProgram(
            vertexShader = SHARPEN_VERTEX_SHADER,
            fragmentShader = SHARPEN_FRAGMENT_SHADER
        )
    }
    
    /**
     * GPU双边滤波
     */
    fun gpuBilateralFilter(
        inputTexture: Int,
        width: Int,
        height: Int,
        sigmaColor: Float = 25f,
        sigmaSpace: Float = 3f
    ): Int {
        GLES30.glUseProgram(shaderPrograms["bilateral"])
        
        // 设置参数
        val sigmaColorLoc = GLES30.glGetUniformLocation(shaderPrograms["bilateral"], "u_SigmaColor")
        val sigmaSpaceLoc = GLES30.glGetUniformLocation(shaderPrograms["bilateral"], "u_SigmaSpace")
        val texSizeLoc = GLES30.glGetUniformLocation(shaderPrograms["bilateral"], "u_TexSize")
        
        GLES30.glUniform1f(sigmaColorLoc, sigmaColor)
        GLES30.glUniform1f(sigmaSpaceLoc, sigmaSpace)
        GLES30.glUniform2f(texSizeLoc, width.toFloat(), height.toFloat())
        
        // 创建输出纹理
        val outputTexture = createTexture(width, height)
        
        // 绑定FBO并渲染
        val fbo = createFBO(outputTexture)
        GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, fbo)
        
        GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, inputTexture)
        
        // 绘制全屏四边形
        drawFullScreenQuad()
        
        GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0)
        GLES30.glDeleteFramebuffers(1, intArrayOf(fbo), 0)
        
        return outputTexture
    }
    
    /**
     * 实时条码增强流水线(GPU版本)
     */
    fun realtimeEnhancementPipeline(
        yuvImage: ImageProxy,
        barcodeRegions: List<Rect>
    ): EnhancedFrame {
        val startTime = System.nanoTime()
        
        // 1. YUV转RGB(GPU)
        val rgbTexture = convertYuvToRgbTexture(yuvImage)
        
        // 2. 应用增强流水线
        var enhancedTexture = rgbTexture
        
        // 只对条码区域进行增强,减少计算量
        for (region in barcodeRegions) {
            val regionTexture = extractTextureRegion(enhancedTexture, region)
            
            // 增强该区域
            val enhancedRegion = applyRegionEnhancement(regionTexture)
            
            // 合并回原图
            enhancedTexture = blendTexture(enhancedTexture, enhancedRegion, region)
        }
        
        // 3. 转换回ImageProxy格式(如果需要)
        val resultImage = textureToImageProxy(enhancedTexture, yuvImage.format)
        
        val processingTime = (System.nanoTime() - startTime) / 1_000_000.0
        
        return EnhancedFrame(
            image = resultImage,
            processingTime = processingTime,
            originalFormat = yuvImage.format,
            enhancedRegions = barcodeRegions.size
        )
    }
    
    companion object {
        // 双边滤波着色器
        private const val BILATERAL_FRAGMENT_SHADER = """
            #version 300 es
            precision highp float;
            
            uniform sampler2D u_Texture;
            uniform float u_SigmaColor;
            uniform float u_SigmaSpace;
            uniform vec2 u_TexSize;
            
            in vec2 v_TexCoord;
            out vec4 outColor;
            
            void main() {
                vec2 texelSize = 1.0 / u_TexSize;
                vec4 centerColor = texture(u_Texture, v_TexCoord);
                vec4 sum = vec4(0.0);
                float totalWeight = 0.0;
                
                int kernelRadius = 2;
                float twoSigmaSpace2 = 2.0 * u_SigmaSpace * u_SigmaSpace;
                float twoSigmaColor2 = 2.0 * u_SigmaColor * u_SigmaColor;
                
                for (int i = -kernelRadius; i <= kernelRadius; i++) {
                    for (int j = -kernelRadius; j <= kernelRadius; j++) {
                        vec2 offset = vec2(float(i), float(j)) * texelSize;
                        vec4 sampleColor = texture(u_Texture, v_TexCoord + offset);
                        
                        // 空间权重
                        float spatialWeight = exp(-float(i*i + j*j) / twoSigmaSpace2);
                        
                        // 颜色权重
                        float colorDiff = distance(centerColor.rgb, sampleColor.rgb);
                        float colorWeight = exp(-colorDiff * colorDiff / twoSigmaColor2);
                        
                        float weight = spatialWeight * colorWeight;
                        sum += sampleColor * weight;
                        totalWeight += weight;
                    }
                }
                
                outColor = sum / totalWeight;
            }
        """
        
        // 对比度增强着色器
        private const val CONTRAST_FRAGMENT_SHADER = """
            #version 300 es
            precision highp float;
            
            uniform sampler2D u_Texture;
            uniform float u_ClipLimit;
            uniform vec2 u_TexSize;
            
            in vec2 v_TexCoord;
            out vec4 outColor;
            
            void main() {
                vec4 color = texture(u_Texture, v_TexCoord);
                
                // CLAHE实现(简化版)
                vec3 luminance = vec3(0.299, 0.587, 0.114);
                float luma = dot(color.rgb, luminance);
                
                // 局部直方图均衡化
                float enhancedLuma = applyCLAHE(luma, u_TexCoord, u_TexSize, u_ClipLimit);
                
                // 保持色度不变,增强亮度
                vec3 enhancedColor = color.rgb * (enhancedLuma / max(luma, 0.001));
                
                outColor = vec4(clamp(enhancedColor, 0.0, 1.0), color.a);
            }
        """
    }
}

第五章:运动补偿与防抖算法

5.1 基于陀螺仪的运动补偿

class MotionCompensationProcessor(
    private val sensorManager: SensorManager
) {
    
    private var gyroSensor: Sensor? = null
    private val gyroData = CircularBuffer<GyroSample>(50)
    private var lastGyroTime = 0L
    private var motionFilter = KalmanFilter(6) // 6维状态:位置+速度
    
    init {
        gyroSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)
        gyroSensor?.let {
            sensorManager.registerListener(
                gyroListener,
                it,
                SensorManager.SENSOR_DELAY_FASTEST
            )
        }
    }
    
    private val gyroListener = object : SensorEventListener {
        override fun onSensorChanged(event: SensorEvent) {
            if (event.sensor.type == Sensor.TYPE_GYROSCOPE) {
                val currentTime = System.nanoTime()
                val dt = (currentTime - lastGyroTime) / 1_000_000_000.0
                lastGyroTime = currentTime
                
                val sample = GyroSample(
                    timestamp = currentTime,
                    angularVelocity = floatArrayOf(
                        event.values[0],
                        event.values[1],
                        event.values[2]
                    ),
                    deltaTime = dt.toFloat()
                )
                
                gyroData.add(sample)
                
                // 更新运动模型
                updateMotionModel(sample)
            }
        }
        
        override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
            // 精度变化处理
        }
    }
    
    /**
     * 运动补偿:修正相机抖动
     */
    fun compensateMotion(
        frame: ImageProxy,
        frameTimestamp: Long
    ): MotionCompensatedFrame {
        // 获取对应时间的陀螺仪数据
        val relevantSamples = gyroData.getSamplesAround(frameTimestamp, 20)
        
        if (relevantSamples.isEmpty()) {
            return MotionCompensatedFrame(
                image = frame,
                compensationApplied = false,
                motionVector = MotionVector.ZERO
            )
        }
        
        // 计算运动向量
        val motionVector = calculateMotionVector(relevantSamples)
        
        // 应用运动补偿
        val compensatedImage = applyMotionCompensation(frame, motionVector)
        
        return MotionCompensatedFrame(
            image = compensatedImage,
            compensationApplied = true,
            motionVector = motionVector,
            gyroSamples = relevantSamples.size
        )
    }
    
    private fun calculateMotionVector(samples: List<GyroSample>): MotionVector {
        var totalRotationX = 0f
        var totalRotationY = 0f
        var totalRotationZ = 0f
        
        for (sample in samples) {
            // 积分角速度得到角度变化
            totalRotationX += sample.angularVelocity[0] * sample.deltaTime
            totalRotationY += sample.angularVelocity[1] * sample.deltaTime
            totalRotationZ += sample.angularVelocity[2] * sample.deltaTime
        }
        
        // 转换为像素位移(基于焦距和传感器尺寸)
        val pixelShiftX = angularToPixelShift(totalRotationY) // 注意:X旋转对应Y位移
        val pixelShiftY = angularToPixelShift(totalRotationX)
        
        return MotionVector(
            dx = pixelShiftX,
            dy = pixelShiftY,
            rotation = totalRotationZ
        )
    }
    
    private fun applyMotionCompensation(
        image: ImageProxy,
        motionVector: MotionVector
    ): ImageProxy {
        // 创建变换矩阵
        val transformMatrix = Matrix()
        
        // 平移补偿
        transformMatrix.postTranslate(-motionVector.dx, -motionVector.dy)
        
        // 旋转补偿(如果需要)
        if (abs(motionVector.rotation) > 0.01) {
            transformMatrix.postRotate(
                -motionVector.rotation,
                image.width / 2f,
                image.height / 2f
            )
        }
        
        // 应用变换
        return applyAffineTransform(image, transformMatrix)
    }
    
    /**
     * 运动预测:预判条码位置
     */
    fun predictBarcodePosition(
        currentPosition: Rect,
        predictionTime: Long // 预测未来多少毫秒
    ): Rect {
        // 获取当前运动状态
        val currentMotion = motionFilter.getCurrentState()
        
        // 预测未来位置
        val predictedMotion = motionFilter.predict(predictionTime)
        
        // 计算位移
        val dx = (predictedMotion[0] - currentMotion[0]).toFloat()
        val dy = (predictedMotion[1] - currentMotion[1]).toFloat()
        
        // 应用到位移
        return Rect(
            currentPosition.left + dx.toInt(),
            currentPosition.top + dy.toInt(),
            currentPosition.right + dx.toInt(),
            currentPosition.bottom + dy.toInt()
        )
    }
}

5.2 光学防抖与电子防抖协同

class HybridImageStabilizer {
    
    private enum class StabilizationMode {
        DISABLED,      // 无防抖
        EIS_ONLY,      // 仅电子防抖
        OIS_ONLY,      // 仅光学防抖
        HYBRID         // 混合防抖
    }
    
    private var currentMode = StabilizationMode.HYBRID
    private val eisProcessor = ElectronicImageStabilizer()
    private var oisSupported = false
    
    /**
     * 混合防抖处理流水线
     */
    fun stabilizeFrame(
        frame: ImageProxy,
        metadata: FrameMetadata,
        gyroData: List<GyroSample>
    ): StabilizedFrame {
        val startTime = System.nanoTime()
        
        // 步骤1:检测运动类型
        val motionType = detectMotionType(gyroData)
        
        // 步骤2:选择防抖策略
        val strategy = selectStabilizationStrategy(motionType, metadata)
        
        // 步骤3:应用防抖
        val stabilizedImage = when (strategy.mode) {
            StabilizationMode.EIS_ONLY -> applyEIS(frame, gyroData, strategy)
            StabilizationMode.OIS_ONLY -> applyOIS(frame, strategy)
            StabilizationMode.HYBRID -> applyHybridStabilization(frame, gyroData, strategy)
            else -> frame // 无防抖
        }
        
        val processingTime = (System.nanoTime() - startTime) / 1_000_000.0
        
        return StabilizedFrame(
            image = stabilizedImage,
            originalImage = frame,
            mode = strategy.mode,
            motionType = motionType,
            cropRatio = strategy.cropRatio,
            processingTime = processingTime
        )
    }
    
    private fun applyHybridStabilization(
        frame: ImageProxy,
        gyroData: List<GyroSample>,
        strategy: StabilizationStrategy
    ): ImageProxy {
        // 第一阶段:OIS补偿高频抖动
        val oisCompensated = if (oisSupported && strategy.useOIS) {
            applyOpticalStabilization(frame, gyroData)
        } else {
            frame
        }
        
        // 第二阶段:EIS补偿低频运动和残差
        val eisCompensated = applyElectronicStabilization(
            oisCompensated, 
            gyroData,
            strategy.eisStrength
        )
        
        // 第三阶段:运动自适应裁剪
        return applyMotionAdaptiveCrop(eisCompensated, strategy.cropRatio)
    }
    
    /**
     * 运动类型检测
     */
    private fun detectMotionType(gyroData: List<GyroSample>): MotionType {
        if (gyroData.size < 5) {
            return MotionType.STATIC
        }
        
        // 计算运动统计量
        val frequencies = calculateMotionFrequency(gyroData)
        val amplitudes = calculateMotionAmplitude(gyroData)
        
        return when {
            // 高频低幅:手抖
            frequencies.average > 10f && amplitudes.max < 0.5f -> 
                MotionType.HAND_SHAKE
            
            // 低频高幅:平移运动
            frequencies.average < 2f && amplitudes.max > 2f -> 
                MotionType.PAN_MOTION
            
            // 中频中幅:行走
            frequencies.average in 2f..5f && amplitudes.max in 0.5f..2f -> 
                MotionType.WALKING
            
            // 随机运动
            frequencies.stdDev > 3f -> 
                MotionType.RANDOM_MOTION
            
            else -> MotionType.STATIC
        }
    }
    
    /**
     * 防抖策略选择
     */
    private fun selectStabilizationStrategy(
        motionType: MotionType,
        metadata: FrameMetadata
    ): StabilizationStrategy {
        return when (motionType) {
            MotionType.HAND_SHAKE -> {
                // 手抖:使用OIS+轻度EIS
                StabilizationStrategy(
                    mode = StabilizationMode.HYBRID,
                    useOIS = true,
                    eisStrength = 0.3f,
                    cropRatio = 0.95f,
                    maxCompensation = 15f // 像素
                )
            }
            
            MotionType.PAN_MOTION -> {
                // 平移运动:主要使用EIS
                StabilizationStrategy(
                    mode = StabilizationMode.EIS_ONLY,
                    useOIS = false,
                    eisStrength = 0.7f,
                    cropRatio = 0.85f,
                    maxCompensation = 30f
                )
            }
            
            MotionType.WALKING -> {
                // 行走:混合防抖
                StabilizationStrategy(
                    mode = StabilizationMode.HYBRID,
                    useOIS = true,
                    eisStrength = 0.5f,
                    cropRatio = 0.9f,
                    maxCompensation = 20f
                )
            }
            
            MotionType.RANDOM_MOTION -> {
                // 随机运动:强EIS
                StabilizationStrategy(
                    mode = StabilizationMode.EIS_ONLY,
                    useOIS = false,
                    eisStrength = 0.8f,
                    cropRatio = 0.8f,
                    maxCompensation = 40f
                )
            }
            
            else -> {
                // 静态:轻度防抖或关闭
                StabilizationStrategy(
                    mode = if (metadata.lowLight) 
                        StabilizationMode.OIS_ONLY else StabilizationMode.DISABLED,
                    useOIS = metadata.lowLight,
                    eisStrength = 0f,
                    cropRatio = 1f,
                    maxCompensation = 0f
                )
            }
        }
    }
}

第六章:工业级错误处理与恢复

6.1 故障诊断与自愈系统

class IndustrialBarcodeDiagnostic {
    
    data class DiagnosticResult(
        val issue: ScanIssue,
        val confidence: Float,
        val suggestedAction: RecoveryAction,
        val estimatedRecoveryTime: Long // ms
    )
    
    enum class ScanIssue {
        NO_BARCODE_DETECTED,
        LOW_CONFIDENCE,
        MOTION_BLUR,
        LOW_LIGHT,
        OUT_OF_FOCUS,
        PERSPECTIVE_DISTORTION,
        PARTIAL_BARCODE,
        REFLECTION_GLARE,
        BARCODE_DAMAGED,
        MULTIPLE_BARCODES_CONFLICT
    }
    
    enum class RecoveryAction {
        ADJUST_FOCUS,
        INCREASE_LIGHT,
        DECREASE_LIGHT,
        ADJUST_ZOOM,
        CHANGE_ANGLE,
        CLEAN_LENS,
        RETRY_SCAN,
        USE_FLASH,
        SWITCH_CAMERA,
        MANUAL_INTERVENTION
    }
    
    /**
     * 诊断扫描问题并建议恢复方案
     */
    fun diagnoseScanFailure(
        frame: ImageProxy,
        scanResults: List<BarcodeScanResult>,
        sensorData: SensorData
    ): DiagnosticResult {
        // 收集所有诊断指标
        val metrics = collectDiagnosticMetrics(frame, scanResults, sensorData)
        
        // 分析问题
        val issues = analyzeIssues(metrics)
        
        // 选择主要问题
        val primaryIssue = selectPrimaryIssue(issues)
        
        // 生成恢复方案
        val recoveryAction = generateRecoveryAction(primaryIssue, metrics)
        
        return DiagnosticResult(
            issue = primaryIssue,
            confidence = calculateIssueConfidence(primaryIssue, metrics),
            suggestedAction = recoveryAction,
            estimatedRecoveryTime = estimateRecoveryTime(recoveryAction)
        )
    }
    
    private fun collectDiagnosticMetrics(
        frame: ImageProxy,
        scanResults: List<BarcodeScanResult>,
        sensorData: SensorData
    ): DiagnosticMetrics {
        return DiagnosticMetrics(
            // 图像质量指标
            imageQuality = ImageQualityMetrics(
                brightness = calculateBrightness(frame),
                contrast = calculateContrast(frame),
                sharpness = calculateSharpness(frame),
                noiseLevel = estimateNoiseLevel(frame)
            ),
            
            // 条码检测指标
            barcodeMetrics = BarcodeMetrics(
                count = scanResults.size,
                confidences = scanResults.map { it.confidence },
                formats = scanResults.map { it.format },
                sizes = scanResults.mapNotNull { it.boundingBox?.let { box -> box.width() * box.height() } },
                positions = scanResults.mapNotNull { it.boundingBox?.center() }
            ),
            
            // 环境指标
            environment = EnvironmentMetrics(
                lightLevel = sensorData.lightLevel,
                motionLevel = sensorData.motionLevel,
                distanceEstimate = sensorData.distanceEstimate,
                temperature = sensorData.temperature
            ),
            
            // 系统状态指标
            system = SystemMetrics(
                processingLatency = scanResults.maxOfOrNull { it.processingTime } ?: 0L,
                memoryUsage = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(),
                cpuUsage = getProcessCpuUsage(),
                thermalState = getThermalState()
            )
        )
    }
    
    private fun analyzeIssues(metrics: DiagnosticMetrics): Map<ScanIssue, Float> {
        val issueScores = mutableMapOf<ScanIssue, Float>()
        
        // 1. 检查无条码检测
        if (metrics.barcodeMetrics.count == 0) {
            var score = 0f
            
            // 低亮度
            if (metrics.imageQuality.brightness < 50) {
                score += 0.4f
                issueScores[ScanIssue.LOW_LIGHT] = 0.8f
            }
            
            // 低对比度
            if (metrics.imageQuality.contrast < 0.3) {
                score += 0.3f
            }
            
            // 失焦
            if (metrics.imageQuality.sharpness < 0.2) {
                score += 0.3f
                issueScores[ScanIssue.OUT_OF_FOCUS] = 0.7f
            }
            
            issueScores[ScanIssue.NO_BARCODE_DETECTED] = score.coerceIn(0f, 1f)
        }
        
        // 2. 检查低置信度
        val avgConfidence = metrics.barcodeMetrics.confidences.average()
        if (avgConfidence < 0.6 && metrics.barcodeMetrics.count > 0) {
            var score = 1.0f - avgConfidence
            
            // 运动模糊
            if (metrics.environment.motionLevel > 0.7) {
                score = max(score, 0.8f)
                issueScores[ScanIssue.MOTION_BLUR] = 0.9f
            }
            
            // 反光/眩光
            if (metrics.imageQuality.brightness > 200 && 
                metrics.imageQuality.contrast > 0.8) {
                score = max(score, 0.7f)
                issueScores[ScanIssue.REFLECTION_GLARE] = 0.7f
            }
            
            issueScores[ScanIssue.LOW_CONFIDENCE] = score
        }
        
        // 3. 检查条码损坏
        if (metrics.barcodeMetrics.count > 0) {
            val completenessScores = metrics.barcodeMetrics.sizes.map { size ->
                // 条码大小异常检测
                val expectedSize = estimateExpectedBarcodeSize(
                    metrics.environment.distanceEstimate,
                    metrics.barcodeMetrics.formats.first()
                )
                
                val sizeRatio = size.toFloat() / expectedSize
                if (sizeRatio < 0.3) {
                    issueScores[ScanIssue.PARTIAL_BARCODE] = 1.0f - sizeRatio
                }
            }
        }
        
        return issueScores
    }
    
    /**
     * 自动恢复系统
     */
    class AutoRecoverySystem(
        private val cameraControl: CameraControl,
        private val lightingControl: LightingController?
    ) {
        
        private val recoveryHistory = mutableListOf<RecoveryAttempt>()
        private var consecutiveFailures = 0
        
        fun attemptRecovery(action: RecoveryAction): RecoveryResult {
            val startTime = System.currentTimeMillis()
            var success = false
            
            try {
                when (action) {
                    RecoveryAction.ADJUST_FOCUS -> {
                        success = performFocusRecovery()
                    }
                    
                    RecoveryAction.INCREASE_LIGHT -> {
                        success = lightingControl?.increaseLight(1.5f) ?: false
                    }
                    
                    RecoveryAction.DECREASE_LIGHT -> {
                        success = lightingControl?.decreaseLight(0.7f) ?: false
                    }
                    
                    RecoveryAction.ADJUST_ZOOM -> {
                        success = performZoomRecovery()
                    }
                    
                    RecoveryAction.USE_FLASH -> {
                        success = cameraControl.enableTorch(true)
                    }
                    
                    RecoveryAction.SWITCH_CAMERA -> {
                        success = switchToAlternateCamera()
                    }
                    
                    else -> {
                        // 需要人工干预的动作
                        success = false
                    }
                }
            } catch (e: Exception) {
                Log.e("AutoRecovery", "恢复失败", e)
                success = false
            }
            
            val recoveryTime = System.currentTimeMillis() - startTime
            
            val attempt = RecoveryAttempt(
                action = action,
                timestamp = startTime,
                duration = recoveryTime,
                success = success
            )
            
            recoveryHistory.add(attempt)
            
            if (success) {
                consecutiveFailures = 0
            } else {
                consecutiveFailures++
            }
            
            return RecoveryResult(
                attempt = attempt,
                consecutiveFailures = consecutiveFailures,
                nextSuggestedAction = if (!success) suggestNextAction() else null
            )
        }
        
        private fun performFocusRecovery(): Boolean {
            // 执行对焦搜索
            val focusRange = 0.1f..10f
            val steps = listOf(0.1f, 0.5f, 1.0f, 2.0f, 5.0f, 10.0f)
            
            for (focusDistance in steps) {
                cameraControl.setFocusDistance(focusDistance)
                Thread.sleep(100) // 等待对焦稳定
                
                // 检查对焦质量
                if (checkFocusQuality() > 0.7) {
                    return true
                }
            }
            
            return false
        }
        
        private fun performZoomRecovery(): Boolean {
            // 尝试不同的变焦级别
            val zoomLevels = listOf(1.0f, 1.5f, 2.0f, 2.5f, 3.0f)
            
            for (zoom in zoomLevels) {
                cameraControl.setZoomRatio(zoom)
                Thread.sleep(200) // 等待变焦稳定
                
                // 检查识别质量
                if (checkRecognitionQuality() > 0.6) {
                    return true
                }
            }
            
            return false
        }
        
        private fun suggestNextAction(): RecoveryAction {
            // 基于历史选择下一个恢复动作
            val recentAttempts = recoveryHistory.takeLast(3)
            
            return when {
                // 尝试过对焦但失败,尝试调整光线
                recentAttempts.any { it.action == RecoveryAction.ADJUST_FOCUS && !it.success } -> 
                    if (lightingControl != null) RecoveryAction.INCREASE_LIGHT 
                    else RecoveryAction.ADJUST_ZOOM
                
                // 尝试过光线调整但失败,尝试变焦
                recentAttempts.any { it.action in listOf(
                    RecoveryAction.INCREASE_LIGHT, 
                    RecoveryAction.DECREASE_LIGHT
                ) && !it.success } -> 
                    RecoveryAction.ADJUST_ZOOM
                
                // 尝试过变焦但失败,尝试闪光灯
                recentAttempts.any { it.action == RecoveryAction.ADJUST_ZOOM && !it.success } -> 
                    RecoveryAction.USE_FLASH
                
                // 所有自动恢复失败,需要人工干预
                consecutiveFailures >= 5 -> 
                    RecoveryAction.MANUAL_INTERVENTION
                
                // 默认尝试对焦
                else -> RecoveryAction.ADJUST_FOCUS
            }
        }
    }
}

第七章:性能优化与资源管理

7.1 智能帧选择策略

class IntelligentFrameSelector {
    
    private val frameQualityHistory = CircularBuffer<FrameQuality>(10)
    private var lastProcessedFrameTime = 0L
    private var targetFrameInterval = 100L // 目标处理间隔 100ms = 10fps
    
    data class FrameQuality(
        val timestamp: Long,
        val qualityScore: Float,
        val motionScore: Float,
        val sharpnessScore: Float,
        val hasBarcode: Boolean,
        val processingTime: Long
    )
    
    /**
     * 智能帧选择:只处理高质量的帧
     */
    fun shouldProcessFrame(
        frame: ImageProxy,
        predictedBarcodePosition: Rect? = null
    ): Boolean {
        val currentTime = System.currentTimeMillis()
        
        // 1. 时间间隔检查
        val timeSinceLastProcess = currentTime - lastProcessedFrameTime
        if (timeSinceLastProcess < targetFrameInterval) {
            return false // 处理频率限制
        }
        
        // 2. 帧质量评估
        val quality = evaluateFrameQuality(frame, predictedBarcodePosition)
        frameQualityHistory.add(quality)
        
        // 3. 动态调整阈值
        val qualityThreshold = calculateDynamicThreshold()
        
        // 4. 决策
        val shouldProcess = quality.qualityScore > qualityThreshold &&
                           quality.motionScore < 0.5f &&
                           quality.sharpnessScore > 0.3f
        
        if (shouldProcess) {
            lastProcessedFrameTime = currentTime
        }
        
        return shouldProcess
    }
    
    private fun evaluateFrameQuality(
        frame: ImageProxy,
        predictedPosition: Rect?
    ): FrameQuality {
        val startTime = System.nanoTime()
        
        // 快速质量评估(避免完整处理)
        val motionScore = estimateMotionBlur(frame)
        val sharpnessScore = estimateSharpness(frame)
        val contrastScore = estimateContrast(frame)
        
        // 快速条码检测(仅在预测区域)
        val hasBarcode = if (predictedPosition != null) {
            quickBarcodeCheck(frame, predictedPosition)
        } else {
            false
        }
        
        val processingTime = (System.nanoTime() - startTime) / 1_000_000
        
        // 综合质量评分
        val qualityScore = calculateQualityScore(
            motionScore, sharpnessScore, contrastScore, hasBarcode
        )
        
        return FrameQuality(
            timestamp = System.currentTimeMillis(),
            qualityScore = qualityScore,
            motionScore = motionScore,
            sharpnessScore = sharpnessScore,
            hasBarcode = hasBarcode,
            processingTime = processingTime
        )
    }
    
    private fun calculateDynamicThreshold(): Float {
        if (frameQualityHistory.isEmpty()) {
            return 0.5f // 默认阈值
        }
        
        // 计算历史质量统计
        val recentScores = frameQualityHistory.takeLast(5).map { it.qualityScore }
        val avgScore = recentScores.average().toFloat()
        val stdDev = calculateStdDev(recentScores)
        
        // 动态调整阈值:质量稳定时提高阈值,波动时降低阈值
        return when {
            stdDev < 0.1 -> avgScore + 0.1f // 质量稳定,提高要求
            stdDev > 0.3 -> avgScore - 0.1f // 质量波动,降低要求
            else -> avgScore
        }.coerceIn(0.2f, 0.8f)
    }
    
    /**
     * 自适应帧率调整
     */
    fun adjustFrameRateBasedOnWorkload(
        currentProcessingTime: Long,
        systemLoad: SystemLoad
    ) {
        // 计算目标帧率
        val targetFps = when {
            // 处理时间过长,降低帧率
            currentProcessingTime > 100 -> {
                5 // 5fps
            }
            
            // 系统负载高,适当降低帧率
            systemLoad.cpuUsage > 0.7 || systemLoad.memoryUsage > 0.8 -> {
                10 // 10fps
            }
            
            // 电池温度高,降低帧率
            systemLoad.thermalState == ThermalState.HOT -> {
                15 // 15fps
            }
            
            // 正常情况,使用最佳帧率
            else -> {
                30 // 30fps
            }
        }
        
        targetFrameInterval = 1000L / targetFps
    }
}

7.2 内存与资源管理

class IndustrialResourceManager {
    
    private val imagePool = ImageProxyPool()
    private val texturePool = TexturePool()
    private val bufferPool = ByteBufferPool()
    
    // 资源使用监控
    private val resourceMonitor = ResourceMonitor()
    
    /**
     * 图像池:重用ImageProxy对象
     */
    class ImageProxyPool {
        private val availableImages = ConcurrentLinkedQueue<ImageProxy>()
        private val inUseImages = ConcurrentHashMap<Int, ImageProxy>()
        private val maxPoolSize = 10
        
        fun acquireImage(width: Int, height: Int, format: Int): ImageProxy {
            // 查找可重用的图像
            val reusable = availableImages.poll { 
                it.width == width && it.height == height && it.format == format 
            }
            
            return if (reusable != null) {
                inUseImages[reusable.hashCode()] = reusable
                reusable
            } else {
                // 创建新图像
                val newImage = createImageProxy(width, height, format)
                inUseImages[newImage.hashCode()] = newImage
                newImage
            }
        }
        
        fun releaseImage(image: ImageProxy) {
            val hash = image.hashCode()
            inUseImages.remove(hash)
            
            // 如果池未满,回收重用
            if (availableImages.size < maxPoolSize) {
                // 重置图像状态
                resetImageProxy(image)
                availableImages.offer(image)
            } else {
                // 释放资源
                image.close()
            }
        }
        
        fun trimPool() {
            // 释放超过限制的图像
            while (availableImages.size > maxPoolSize) {
                availableImages.poll()?.close()
            }
        }
    }
    
    /**
     * 纹理池:重用OpenGL纹理
     */
    class TexturePool {
        private val availableTextures = ConcurrentLinkedQueue<TextureInfo>()
        private val maxPoolSize = 5
        
        data class TextureInfo(
            val id: Int,
            val width: Int,
            val height: Int,
            val format: Int,
            val lastUsed: Long
        )
        
        fun acquireTexture(width: Int, height: Int): TextureInfo {
            // 查找合适纹理
            val now = System.currentTimeMillis()
            val iterator = availableTextures.iterator()
            
            while (iterator.hasNext()) {
                val texture = iterator.next()
                if (texture.width == width && texture.height == height) {
                    iterator.remove()
                    return texture.copy(lastUsed = now)
                }
            }
            
            // 创建新纹理
            return TextureInfo(
                id = createGLTexture(width, height),
                width = width,
                height = height,
                format = GLES30.GL_RGBA,
                lastUsed = now
            )
        }
        
        fun releaseTexture(texture: TextureInfo) {
            val now = System.currentTimeMillis()
            
            // 如果纹理最近使用过,回收重用
            if (now - texture.lastUsed < 5000) { // 5秒内使用过
                if (availableTextures.size < maxPoolSize) {
                    availableTextures.offer(texture.copy(lastUsed = now))
                } else {
                    // 释放最久未使用的纹理
                    val oldest = availableTextures.minByOrNull { it.lastUsed }
                    oldest?.let {
                        availableTextures.remove(it)
                        deleteGLTexture(it.id)
                    }
                    availableTextures.offer(texture.copy(lastUsed = now))
                }
            } else {
                // 纹理太久未用,直接释放
                deleteGLTexture(texture.id)
            }
        }
    }
    
    /**
     * 内存预警与自动清理
     */
    class MemoryGuardian(
        private val context: Context
    ) {
        private val memoryThresholds = mapOf(
            MemoryLevel.CRITICAL to 0.9,  // 90% 内存使用
            MemoryLevel.HIGH to 0.8,      // 80% 内存使用
            MemoryLevel.MODERATE to 0.7,  // 70% 内存使用
            MemoryLevel.LOW to 0.6        // 60% 内存使用
        )
        
        fun checkMemoryLevel(): MemoryLevel {
            val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
            val memoryInfo = ActivityManager.MemoryInfo()
            activityManager.getMemoryInfo(memoryInfo)
            
            val usedMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()
            val totalMemory = Runtime.getRuntime().maxMemory()
            val memoryUsage = usedMemory.toDouble() / totalMemory.toDouble()
            
            return when {
                memoryUsage >= memoryThresholds[MemoryLevel.CRITICAL]!! -> MemoryLevel.CRITICAL
                memoryUsage >= memoryThresholds[MemoryLevel.HIGH]!! -> MemoryLevel.HIGH
                memoryUsage >= memoryThresholds[MemoryLevel.MODERATE]!! -> MemoryLevel.MODERATE
                else -> MemoryLevel.LOW
            }
        }
        
        fun performMemoryCleanup(level: MemoryLevel) {
            when (level) {
                MemoryLevel.CRITICAL -> {
                    // 紧急清理
                    System.gc()
                    clearAllCaches()
                    reduceProcessingQuality(0.5f)
                    Log.w("MemoryGuardian", "执行紧急内存清理")
                }
                
                MemoryLevel.HIGH -> {
                    // 积极清理
                    clearOldCaches(30000) // 清理30秒前的缓存
                    reduceProcessingQuality(0.7f)
                    trimResourcePools()
                }
                
                MemoryLevel.MODERATE -> {
                    // 温和清理
                    clearOldCaches(60000) // 清理60秒前的缓存
                    trimResourcePools()
                }
                
                MemoryLevel.LOW -> {
                    // 正常操作
                    trimResourcePools()
                }
            }
        }
        
        private fun reduceProcessingQuality(factor: Float) {
            // 降低处理质量以减少内存使用
            // 例如:降低分辨率、减少增强步骤、降低识别精度等
        }
    }
}

第八章:工业级测试与验证

8.1 自动化测试框架

class IndustrialBarcodeTestSuite {
    
    /**
     * 综合性能测试
     */
    data class PerformanceTestResult(
        val recognitionRate: RecognitionRate,
        val processingLatency: LatencyStats,
        val resourceUsage: ResourceUsage,
        val environmentalRobustness: EnvironmentalScore
    )
    
    fun runComprehensiveTest(): TestReport {
        val startTime = System.currentTimeMillis()
        
        // 1. 基础识别率测试
        val recognitionTest = testRecognitionRate()
        
        // 2. 性能基准测试
        val performanceTest = testProcessingPerformance()
        
        // 3. 环境鲁棒性测试
        val environmentTest = testEnvironmentalRobustness()
        
        // 4. 压力测试
        val stressTest = testStressConditions()
        
        // 5. 兼容性测试
        val compatibilityTest = testDeviceCompatibility()
        
        val totalTime = System.currentTimeMillis() - startTime
        
        return TestReport(
            recognitionRate = recognitionTest,
            performance = performanceTest,
            environmentalRobustness = environmentTest,
            stressTest = stressTest,
            compatibility = compatibilityTest,
            totalTestTime = totalTime,
            overallScore = calculateOverallScore(
                recognitionTest, performanceTest, environmentTest
            )
        )
    }
    
    private fun testRecognitionRate(): RecognitionRate {
        val testCases = loadTestCases("recognition_cases.json")
        var totalCases = 0
        var successfulCases = 0
        
        testCases.forEach { testCase ->
            totalCases++
            
            // 加载测试图像
            val testImage = loadTestImage(testCase.imagePath)
            
            // 运行识别
            val result = barcodeScanner.process(testImage)
            
            // 验证结果
            if (verifyResult(result, testCase.expected)) {
                successfulCases++
            }
        }
        
        return RecognitionRate(
            successRate = successfulCases.toFloat() / totalCases.toFloat(),
            totalCases = totalCases,
            successfulCases = successfulCases,
            failedCases = totalCases - successfulCases
        )
    }
    
    private fun testEnvironmentalRobustness(): EnvironmentalScore {
        val environmentalConditions = listOf(
            EnvironmentCondition("低光照", lightLevel = 10),
            EnvironmentCondition("高光照", lightLevel = 500),
            EnvironmentCondition("运动模糊", motionLevel = 0.8),
            EnvironmentCondition("角度倾斜", tiltAngle = 45),
            EnvironmentCondition("部分遮挡", occlusionLevel = 0.3),
            EnvironmentCondition("反光", glareLevel = 0.7),
            EnvironmentCondition("远距离", distance = 200), // cm
            EnvironmentCondition("曲面", surfaceCurvature = 0.2)
        )
        
        val scores = mutableMapOf<String, Float>()
        
        environmentalConditions.forEach { condition ->
            // 模拟环境条件
            val simulatedImage = simulateEnvironmentalCondition(
                baseImage = loadStandardTestImage(),
                condition = condition
            )
            
            // 测试识别
            val result = barcodeScanner.process(simulatedImage)
            val successRate = calculateSuccessRate(result)
            
            scores[condition.name] = successRate
        }
        
        return EnvironmentalScore(
            conditionScores = scores,
            averageScore = scores.values.average().toFloat(),
            weakestCondition = scores.minByOrNull { it.value }?.key ?: "N/A",
            strongestCondition = scores.maxByOrNull { it.value }?.key ?: "N/A"
        )
    }
    
    /**
     * 实时监控测试
     */
    class RealTimeMonitor {
        private val performanceMetrics = mutableListOf<PerformanceMetric>()
        private val errorLog = ConcurrentLinkedQueue<ErrorEvent>()
        private val startTime = System.currentTimeMillis()
        
        fun recordMetric(metric: PerformanceMetric) {
            performanceMetrics.add(metric)
            
            // 实时分析性能趋势
            analyzePerformanceTrend()
            
            // 检测异常
            detectAnomalies(metric)
        }
        
        private fun analyzePerformanceTrend() {
            if (performanceMetrics.size < 10) return
            
            val recentMetrics = performanceMetrics.takeLast(10)
            
            // 计算移动平均
            val latencyMA = calculateMovingAverage(recentMetrics.map { it.processingLatency })
            val memoryMA = calculateMovingAverage(recentMetrics.map { it.memoryUsage })
            val successRateMA = calculateMovingAverage(recentMetrics.map { it.successRate })
            
            // 检测趋势变化
            val latencyTrend = detectTrendChange(latencyMA)
            val memoryTrend = detectTrendChange(memoryMA)
            val successTrend = detectTrendChange(successRateMA)
            
            // 生成警报
            if (latencyTrend == Trend.INCREASING && latencyMA.last() > 100) {
                generateAlert(AlertType.PERFORMANCE_DEGRADATION, "处理延迟增加")
            }
            
            if (memoryTrend == Trend.INCREASING && memoryMA.last() > 0.8) {
                generateAlert(AlertType.HIGH_MEMORY_USAGE, "内存使用率过高")
            }
            
            if (successTrend == Trend.DECREASING && successRateMA.last() < 0.7) {
                generateAlert(AlertType.LOW_SUCCESS_RATE, "识别成功率下降")
            }
        }
        
        fun generateTestReport(): MonitorReport {
            val duration = System.currentTimeMillis() - startTime
            
            return MonitorReport(
                duration = duration,
                totalFrames = performanceMetrics.size,
                averageLatency = performanceMetrics.map { it.processingLatency }.average(),
                averageSuccessRate = performanceMetrics.map { it.successRate }.average(),
                peakMemoryUsage = performanceMetrics.maxOfOrNull { it.memoryUsage } ?: 0.0,
                errorCount = errorLog.size,
                performanceTrend = calculateOverallTrend(),
                recommendations = generateRecommendations()
            )
        }
    }
}

8.2 条码质量评估标准

class BarcodeQualityStandard {
    
    /**
     * ISO/IEC 15416 条码质量评估标准实现
     */
    data class ISO15416Assessment(
        val symbolContrast: Grade,        // 符号对比度
        val minimumReflectance: Grade,    // 最小反射率
        val minimumEdgeContrast: Grade,   // 最小边缘对比度
        val modulation: Grade,            // 调制
        val defects: Grade,              // 缺陷
        val decodability: Grade,         // 可译码度
        val decodeGrade: Grade,          // 译码等级
        val overallGrade: Grade          // 总体等级
    )
    
    enum class Grade(val value: Int, val description: String) {
        A(4, "优秀 - 适用于所有应用"),
        B(3, "良好 - 适用于大多数应用"),
        C(2, "一般 - 需要良好阅读器"),
        D(1, "较差 - 仅限于特定应用"),
        F(0, "失败 - 不可读")
    }
    
    fun assessBarcodeQuality(
        barcode: Barcode,
        image: ImageProxy
    ): ISO15416Assessment {
        // 1. 提取条码扫描线
        val scanLines = extractScanLines(barcode, image, 10)
        
        // 2. 计算各项指标
        val symbolContrast = calculateSymbolContrast(scanLines)
        val minimumReflectance = calculateMinimumReflectance(scanLines)
        val minimumEdgeContrast = calculateMinimumEdgeContrast(scanLines)
        val modulation = calculateModulation(scanLines)
        val defects = calculateDefects(scanLines, barcode.format)
        val decodability = calculateDecodability(barcode)
        
        // 3. 计算各项等级
        val symbolContrastGrade = gradeSymbolContrast(symbolContrast)
        val minimumReflectanceGrade = gradeMinimumReflectance(minimumReflectance)
        val minimumEdgeContrastGrade = gradeMinimumEdgeContrast(minimumEdgeContrast)
        val modulationGrade = gradeModulation(modulation)
        val defectsGrade = gradeDefects(defects)
        val decodabilityGrade = gradeDecodability(decodability)
        
        // 4. 计算译码等级(最差的一项)
        val decodeGrade = listOf(
            symbolContrastGrade, minimumReflectanceGrade,
            minimumEdgeContrastGrade, modulationGrade,
            defectsGrade
        ).minByOrNull { it.value } ?: Grade.F
        
        // 5. 计算总体等级
        val overallGrade = calculateOverallGrade(
            decodeGrade, decodabilityGrade
        )
        
        return ISO15416Assessment(
            symbolContrast = symbolContrastGrade,
            minimumReflectance = minimumReflectanceGrade,
            minimumEdgeContrast = minimumEdgeContrastGrade,
            modulation = modulationGrade,
            defects = defectsGrade,
            decodability = decodabilityGrade,
            decodeGrade = decodeGrade,
            overallGrade = overallGrade
        )
    }
    
    /**
     * 生成质量报告
     */
    fun generateQualityReport(
        assessment: ISO15416Assessment,
        barcode: Barcode
    ): QualityReport {
        return QualityReport(
            barcodeFormat = barcode.format,
            barcodeValue = barcode.rawValue ?: "N/A",
            assessment = assessment,
            isAcceptable = assessment.overallGrade.value >= 2, // C级以上可接受
            recommendations = generateRecommendations(assessment),
            
            // 详细指标
            detailedMetrics = DetailedMetrics(
                contrastScore = assessment.symbolContrast.value / 4.0,
                edgeScore = assessment.minimumEdgeContrast.value / 4.0,
                modulationScore = assessment.modulation.value / 4.0,
                defectScore = assessment.defects.value / 4.0,
                decodabilityScore = assessment.decodability.value / 4.0
            ),
            
            // 改进建议
            improvementSuggestions = when (assessment.overallGrade) {
                Grade.A -> listOf("质量优秀,无需改进")
                Grade.B -> listOf("可考虑优化光照条件")
                Grade.C -> listOf("建议重新打印条码", "优化扫描角度")
                Grade.D -> listOf("条码质量较差", "建议使用更高质量的打印机")
                Grade.F -> listOf("条码不可读", "必须重新生成条码")
            }
        )
    }
    
    /**
     * 批量质量检测
     */
    class BatchQualityInspector {
        fun inspectBatch(
            barcodes: List<Barcode>,
            images: List<ImageProxy>
        ): BatchInspectionResult {
            val inspections = barcodes.mapIndexed { index, barcode ->
                val image = images.getOrNull(index)
                if (image != null) {
                    val assessment = assessBarcodeQuality(barcode, image)
                    val report = generateQualityReport(assessment, barcode)
                    SingleInspection(barcode, report)
                } else {
                    null
                }
            }.filterNotNull()
            
            return BatchInspectionResult(
                totalInspected = inspections.size,
                acceptableCount = inspections.count { it.report.isAcceptable },
                unacceptableCount = inspections.count { !it.report.isAcceptable },
                averageGrade = inspections.map { it.report.assessment.overallGrade.value }.average(),
                gradeDistribution = inspections.groupBy { it.report.assessment.overallGrade }
                    .mapValues { it.value.size },
                
                // 统计信息
                statistics = InspectionStatistics(
                    bestBarcode = inspections.maxByOrNull { 
                        it.report.assessment.overallGrade.value 
                    },
                    worstBarcode = inspections.minByOrNull { 
                        it.report.assessment.overallGrade.value 
                    },
                    commonIssues = analyzeCommonIssues(inspections),
                    improvementSummary = generateImprovementSummary(inspections)
                )
            )
        }
    }
}

第九章:部署与运维

9.1 配置管理与远程更新

class IndustrialBarcodeConfigManager {
    
    private val localConfig: LocalConfig
    private var remoteConfig: RemoteConfig? = null
    private val configListeners = mutableListOf<ConfigChangeListener>()
    
    data class IndustrialConfig(
        // 相机配置
        val cameraConfig: CameraConfig = CameraConfig(),
        
        // 识别配置
        val recognitionConfig: RecognitionConfig = RecognitionConfig(),
        
        // 性能配置
        val performanceConfig: PerformanceConfig = PerformanceConfig(),
        
        // 业务规则
        val businessRules: BusinessRules = BusinessRules(),
        
        // 环境适配
        val environmentAdaptation: EnvironmentAdaptation = EnvironmentAdaptation()
    )
    
    /**
     * 动态配置更新
     */
    fun updateConfig(newConfig: IndustrialConfig) {
        val oldConfig = localConfig.currentConfig
        
        // 检查配置变更
        val changes = detectConfigChanges(oldConfig, newConfig)
        
        // 应用配置变更
        applyConfigChanges(changes)
        
        // 保存新配置
        localConfig.save(newConfig)
        
        // 通知监听器
        notifyConfigChange(changes)
    }
    
    /**
     * 环境自适应配置
     */
    fun adaptConfigForEnvironment(environment: EnvironmentInfo): IndustrialConfig {
        val baseConfig = localConfig.currentConfig
        
        return when (environment.scenario) {
            EnvironmentScenario.WAREHOUSE -> {
                baseConfig.copy(
                    cameraConfig = baseConfig.cameraConfig.copy(
                        focusMode = FocusMode.CONTINUOUS,
                        exposureCompensation = 1.0f,
                        scanArea = RectF(0.2f, 0.2f, 0.8f, 0.8f)
                    ),
                    recognitionConfig = baseConfig.recognitionConfig.copy(
                        formats = listOf(Barcode.FORMAT_CODE_128, Barcode.FORMAT_DATA_MATRIX),
                        confidenceThreshold = 0.7f,
                        enableBulkScan = true
                    )
                )
            }
            
            EnvironmentScenario.RETAIL -> {
                baseConfig.copy(
                    cameraConfig = baseConfig.cameraConfig.copy(
                        focusMode = FocusMode.AUTO,
                        exposureCompensation = 0.0f,
                        flashMode = FlashMode.AUTO
                    ),
                    recognitionConfig = baseConfig.recognitionConfig.copy(
                        formats = listOf(Barcode.FORMAT_EAN_13, Barcode.FORMAT_UPC_A),
                        confidenceThreshold = 0.8f,
                        enableMultipleScan = false
                    ),
                    businessRules = baseConfig.businessRules.copy(
                        validationRules = listOf(
                            ValidationRule.CHECKSUM,
                            ValidationRule.LENGTH
                        )
                    )
                )
            }
            
            EnvironmentScenario.LOGISTICS -> {
                baseConfig.copy(
                    cameraConfig = baseConfig.cameraConfig.copy(
                        focusMode = FocusMode.MANUAL,
                        zoomRatio = 2.0f,
                        scanArea = RectF(0.1f, 0.1f, 0.9f, 0.9f)
                    ),
                    performanceConfig = baseConfig.performanceConfig.copy(
                        maxProcessingTime = 100L,
                        targetFrameRate = 15
                    )
                )
            }
            
            else -> baseConfig
        }
    }
    
    /**
     * A/B测试配置
     */
    class ABTestManager {
        private val experimentConfigs = mutableMapOf<String, Experiment>()
        
        data class Experiment(
            val name: String,
            val variants: List<Variant>,
            val distribution: Map<String, Float>, // 变体分配比例
            val startTime: Long,
            val endTime: Long,
            val metrics: List<String> // 监控指标
        )
        
        data class Variant(
            val id: String,
            val config: IndustrialConfig,
            val description: String
        )
        
        fun getConfigForDevice(deviceId: String): IndustrialConfig {
            // 获取设备分配的实验
            val assignedExperiments = getAssignedExperiments(deviceId)
            
            // 合并实验配置
            var mergedConfig = localConfig.currentConfig
            
            assignedExperiments.forEach { experiment ->
                val variant = getAssignedVariant(deviceId, experiment.name)
                mergedConfig = mergeConfigs(mergedConfig, variant.config)
            }
            
            return mergedConfig
        }
        
        fun recordExperimentMetrics(
            experimentName: String,
            variantId: String,
            metrics: Map<String, Any>
        ) {
            // 记录实验数据
            val experimentData = ExperimentData(
                experimentName = experimentName,
                variantId = variantId,
                timestamp = System.currentTimeMillis(),
                metrics = metrics,
                deviceInfo = getDeviceInfo()
            )
            
            // 上传到分析平台
            uploadExperimentData(experimentData)
        }
    }
}

9.2 监控与日志系统

class IndustrialMonitoringSystem {
    
    private val performanceMonitor = PerformanceMonitor()
    private val errorTracker = ErrorTracker()
    private val usageAnalytics = UsageAnalytics()
    private val logCollector = LogCollector()
    
    /**
     * 性能监控看板
     */
    class PerformanceDashboard {
        private val metricsBuffer = CircularBuffer<PerformanceMetric>(1000)
        private val alertRules = mutableListOf<AlertRule>()
        
        fun recordMetric(metric: PerformanceMetric) {
            metricsBuffer.add(metric)
            
            // 实时计算统计
            val stats = calculateRealTimeStats()
            
            // 检查警报规则
            checkAlertRules(stats)
            
            // 更新仪表板
            updateDashboard(stats)
        }
        
        private fun calculateRealTimeStats(): RealTimeStats {
            val recentMetrics = metricsBuffer.takeLast(100)
            
            return RealTimeStats(
                currentFps = calculateCurrentFps(recentMetrics),
                averageLatency = recentMetrics.map { it.processingLatency }.average(),
                successRate = recentMetrics.map { it.successRate }.average(),
                memoryUsage = recentMetrics.map { it.memoryUsage }.average(),
                cpuUsage = recentMetrics.map { it.cpuUsage }.average(),
                
                // 趋势分析
                latencyTrend = analyzeTrend(recentMetrics.map { it.processingLatency }),
                successTrend = analyzeTrend(recentMetrics.map { it.successRate }),
                
                // 异常检测
                anomalies = detectAnomalies(recentMetrics)
            )
        }
        
        fun generateReport(timeRange: TimeRange): PerformanceReport {
            val metricsInRange = metricsBuffer.filter { 
                it.timestamp in timeRange.start..timeRange.end 
            }
            
            return PerformanceReport(
                timeRange = timeRange,
                totalScans = metricsInRange.size,
                averagePerformance = calculateAveragePerformance(metricsInRange),
                percentile95 = calculatePercentile95(metricsInRange),
                performanceDistribution = calculateDistribution(metricsInRange),
                bottleneckAnalysis = analyzeBottlenecks(metricsInRange),
                recommendations = generateRecommendations(metricsInRange)
            )
        }
    }
    
    /**
     * 错误追踪与根因分析
     */
    class ErrorTracker {
        private val errorLog = ConcurrentLinkedQueue<ErrorEvent>()
        private val errorPatterns = mutableMapOf<String, ErrorPattern>()
        
        fun trackError(error: ErrorEvent) {
            errorLog.add(error)
            
            // 分析错误模式
            analyzeErrorPattern(error)
            
            // 根因分析
            val rootCause = analyzeRootCause(error)
            
            // 自动修复尝试
            if (rootCause != null) {
                attemptAutoFix(rootCause)
            }
            
            // 生成错误报告
            if (error.severity >= ErrorSeverity.HIGH) {
                generateErrorReport(error, rootCause)
            }
        }
        
        private fun analyzeErrorPattern(error: ErrorEvent) {
            val patternKey = "${error.type}-${error.context}"
            
            errorPatterns[patternKey] = errorPatterns.getOrDefault(patternKey, ErrorPattern()).apply {
                count++
                firstOccurrence = min(firstOccurrence, error.timestamp)
                lastOccurrence = max(lastOccurrence, error.timestamp)
                
                // 计算发生频率
                val duration = (lastOccurrence - firstOccurrence) / 1000.0 // 秒
                frequency = count.toDouble() / max(1.0, duration)
                
                // 关联的设备/环境信息
                associatedDevices.add(error.deviceId)
                associatedEnvironments.addAll(error.environmentalConditions)
            }
        }
        
        fun generateErrorReport(): ErrorAnalysisReport {
            return ErrorAnalysisReport(
                totalErrors = errorLog.size,
                errorDistribution = errorLog.groupBy { it.type }
                    .mapValues { it.value.size },
                
                frequentErrors = errorPatterns.values
                    .filter { it.frequency > 0.1 } // 频率大于0.1次/秒
                    .sortedByDescending { it.frequency },
                
                timeDistribution = analyzeTimeDistribution(errorLog),
                deviceDistribution = analyzeDeviceDistribution(errorLog),
                
                // 建议
                recommendations = generateErrorRecommendations(),
                
                // 趋势
                errorTrend = analyzeErrorTrend(errorLog)
            )
        }
    }
    
    /**
     * 远程日志收集
     */
    class RemoteLogCollector {
        private val logBuffer = CircularBuffer<LogEntry>(10000)
        private var uploadScheduler: ScheduledExecutorService? = null
        
        fun initialize() {
            uploadScheduler = Executors.newScheduledThreadPool(1)
            
            // 每5分钟上传一次日志
            uploadScheduler?.scheduleAtFixedRate({
                uploadLogs()
            }, 5, 5, TimeUnit.MINUTES)
        }
        
        fun log(level: LogLevel, tag: String, message: String, metadata: Map<String, Any> = emptyMap()) {
            val entry = LogEntry(
                timestamp = System.currentTimeMillis(),
                level = level,
                tag = tag,
                message = message,
                metadata = metadata,
                deviceId = getDeviceId(),
                appVersion = getAppVersion(),
                sessionId = getSessionId()
            )
            
            logBuffer.add(entry)
            
            // 重要日志立即上传
            if (level >= LogLevel.ERROR) {
                uploadCriticalLog(entry)
            }
        }
        
        private fun uploadLogs() {
            if (logBuffer.isEmpty()) return
            
            val logsToUpload = logBuffer.take(1000).toList()
            
            // 压缩日志
            val compressedLogs = compressLogs(logsToUpload)
            
            // 上传到服务器
            uploadToServer(compressedLogs).addOnSuccessListener {
                // 上传成功,清除已上传的日志
                logBuffer.removeFirst(logsToUpload.size)
            }.addOnFailureListener { e ->
                Log.e("LogCollector", "日志上传失败", e)
            }
        }
        
        fun generateLogReport(): LogReport {
            val recentLogs = logBuffer.takeLast(1000)
            
            return LogReport(
                totalLogs = logBuffer.size,
                logLevelDistribution = recentLogs.groupBy { it.level }
                    .mapValues { it.value.size },
                frequentTags = recentLogs.groupBy { it.tag }
                    .mapValues { it.value.size }
                    .entries.sortedByDescending { it.value }
                    .take(10)
                    .toMap(),
                errorRate = recentLogs.count { it.level >= LogLevel.ERROR } / recentLogs.size.toFloat(),
                recentErrors = recentLogs
                    .filter { it.level >= LogLevel.ERROR }
                    .takeLast(20)
            )
        }
    }
}

第十章:完整实现示例

10.1 工业扫码服务完整实现

class IndustrialBarcodeScanningService : Service() {
    
    private lateinit var cameraManager: IndustrialCameraManager
    private lateinit var barcodeScanner: IndustrialBarcodeScanner
    private lateinit var imageProcessor: IndustrialImageProcessor
    private lateinit var motionCompensator: MotionCompensationProcessor
    private lateinit var resourceManager: IndustrialResourceManager
    private lateinit var monitoringSystem: IndustrialMonitoringSystem
    
    private var isScanning = false
    private val scanResults = mutableListOf<ScanResult>()
    private val eventListeners = mutableListOf<ScanEventListener>()
    
    // 绑定接口
    private val binder = LocalBinder()
    
    inner class LocalBinder : Binder() {
        fun getService(): IndustrialBarcodeScanningService = this@IndustrialBarcodeScanningService
    }
    
    override fun onCreate() {
        super.onCreate()
        
        // 初始化各组件
        initializeComponents()
        
        // 加载配置
        loadConfiguration()
        
        // 启动监控
        startMonitoring()
        
        Log.i("ScanService", "工业扫码服务已启动")
    }
    
    private fun initializeComponents() {
        // 1. 相机管理
        cameraManager = IndustrialCameraManager(this).apply {
            setCameraEventListener(cameraEventListener)
            setErrorHandler(cameraErrorHandler)
        }
        
        // 2. 条码扫描器
        barcodeScanner = IndustrialBarcodeScanner().apply {
            initialize(this@IndustrialBarcodeScanningService, 
                BarcodeScannerConfig(
                    scanMode = ScanMode.HIGH_ACCURACY,
                    formats = industrialFormats,
                    confidenceThreshold = 0.7f,
                    enableEnhancedScan = true
                )
            )
            setResultCallback(barcodeResultCallback)
        }
        
        // 3. 图像处理器
        imageProcessor = IndustrialImageProcessor().apply {
            setEnhancementPipeline(createEnhancementPipeline())
            setQualityThreshold(0.6f)
        }
        
        // 4. 运动补偿
        motionCompensator = MotionCompensationProcessor(
            getSystemService(Context.SENSOR_SERVICE) as SensorManager
        )
        
        // 5. 资源管理
        resourceManager = IndustrialResourceManager().apply {
            setMemoryLimit(1024 * 1024 * 100) // 100MB
            setCleanupStrategy(CleanupStrategy.AGGRESSIVE)
        }
        
        // 6. 监控系统
        monitoringSystem = IndustrialMonitoringSystem().apply {
            enableRealTimeMonitoring(true)
            setAlertHandler(alertHandler)
        }
    }
    
    /**
     * 开始扫码会话
     */
    fun startScanningSession(config: ScanSessionConfig): ScanSession {
        if (isScanning) {
            throw IllegalStateException("扫码会话已在进行中")
        }
        
        val sessionId = generateSessionId()
        isScanning = true
        
        // 配置相机
        cameraManager.configureCamera(config.cameraMode)
        
        // 启动相机
        cameraManager.startCamera()
        
        // 开始图像分析
        cameraManager.startImageAnalysis { image ->
            processImageFrame(image, sessionId, config)
        }
        
        Log.i("ScanService", "扫码会话开始: $sessionId")
        
        return ScanSession(
            id = sessionId,
            startTime = System.currentTimeMillis(),
            config = config,
            status = SessionStatus.ACTIVE
        )
    }
    
    private fun processImageFrame(
        image: ImageProxy,
        sessionId: String,
        config: ScanSessionConfig
    ) {
        val frameStartTime = System.nanoTime()
        
        try {
            // 1. 运动补偿
            val compensatedFrame = motionCompensator.compensateMotion(image)
            
            // 2. 图像增强
            val enhancedFrame = imageProcessor.enhanceImage(compensatedFrame.image)
            
            // 3. 条码识别
            val scanResult = barcodeScanner.scan(enhancedFrame.image)
            
            // 4. 结果处理
            if (scanResult.barcodes.isNotEmpty()) {
                handleScanResult(scanResult, sessionId, config)
            }
            
            // 5. 性能监控
            val processingTime = (System.nanoTime() - frameStartTime) / 1_000_000.0
            monitoringSystem.recordMetric(
                PerformanceMetric(
                    timestamp = System.currentTimeMillis(),
                    processingLatency = processingTime,
                    successRate = if (scanResult.barcodes.isNotEmpty()) 1.0 else 0.0,
                    memoryUsage = resourceManager.getMemoryUsage(),
                    cpuUsage = getProcessCpuUsage()
                )
            )
            
        } catch (e: Exception) {
            Log.e("ScanService", "帧处理失败", e)
            monitoringSystem.trackError(
                ErrorEvent(
                    type = ErrorType.FRAME_PROCESSING_ERROR,
                    severity = ErrorSeverity.MEDIUM,
                    message = e.message ?: "Unknown error",
                    timestamp = System.currentTimeMillis()
                )
            )
        } finally {
            // 释放资源
            image.close()
        }
    }
    
    private fun handleScanResult(
        result: BarcodeScanResult,
        sessionId: String,
        config: ScanSessionConfig
    ) {
        val processedResult = processScanResult(result, config)
        
        // 验证结果(根据业务规则)
        val validationResult = validateResult(processedResult, config.businessRules)
        
        if (validationResult.isValid) {
            // 添加到结果集
            scanResults.add(processedResult)
            
            // 通知监听器
            eventListeners.forEach { listener ->
                listener.onBarcodeScanned(processedResult)
            }
            
            // 批量处理
            if (config.batchSize > 0 && scanResults.size >= config.batchSize) {
                handleBatchComplete(sessionId, config)
            }
            
            // 单次扫描模式
            if (config.scanMode == ScanMode.SINGLE && scanResults.isNotEmpty()) {
                stopScanningSession(sessionId, StopReason.COMPLETED)
            }
        } else {
            // 无效结果处理
            handleInvalidResult(processedResult, validationResult)
        }
    }
    
    /**
     * 停止扫码会话
     */
    fun stopScanningSession(sessionId: String, reason: StopReason): ScanSessionResult {
        if (!isScanning) {
            throw IllegalStateException("没有活跃的扫码会话")
        }
        
        // 停止相机
        cameraManager.stopCamera()
        
        // 停止图像分析
        cameraManager.stopImageAnalysis()
        
        isScanning = false
        
        // 生成会话结果
        val result = ScanSessionResult(
            sessionId = sessionId,
            startTime = getSessionStartTime(sessionId),
            endTime = System.currentTimeMillis(),
            totalScans = scanResults.size,
            validScans = scanResults.count { it.isValid },
            scanResults = scanResults.toList(),
            stopReason = reason,
            performanceStats = monitoringSystem.getSessionStats(sessionId)
        )
        
        // 清除会话数据
        clearSessionData(sessionId)
        
        Log.i("ScanService", "扫码会话结束: $sessionId, 原因: $reason")
        
        return result
    }
    
    /**
     * 批量扫描处理
     */
    private fun handleBatchComplete(sessionId: String, config: ScanSessionConfig) {
        val batchResults = scanResults.takeLast(config.batchSize)
        
        // 批量验证
        val batchValidation = validateBatch(batchResults, config.batchRules)
        
        if (batchValidation.isValid) {
            // 通知批量完成
            eventListeners.forEach { listener ->
                listener.onBatchCompleted(batchResults, sessionId)
            }
            
            // 上传结果(如果配置了)
            if (config.uploadEnabled) {
                uploadBatchResults(batchResults, sessionId)
            }
            
            // 清空已处理的批次
            scanResults.removeAll(batchResults)
        } else {
            // 批量验证失败处理
            handleBatchFailure(batchValidation)
        }
    }
    
    /**
     * 服务生命周期管理
     */
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        when (intent?.action) {
            ACTION_START_SCANNING -> {
                val config = intent.getParcelableExtra<ScanSessionConfig>(EXTRA_CONFIG)
                if (config != null) {
                    try {
                        val session = startScanningSession(config)
                        
                        // 返回会话信息
                        val resultIntent = Intent(ACTION_SCAN_SESSION_STARTED)
                        resultIntent.putExtra(EXTRA_SESSION_ID, session.id)
                        LocalBroadcastManager.getInstance(this).sendBroadcast(resultIntent)
                        
                    } catch (e: Exception) {
                        Log.e("ScanService", "启动扫码失败", e)
                        sendErrorBroadcast(ErrorType.SESSION_START_FAILED, e.message)
                    }
                }
            }
            
            ACTION_STOP_SCANNING -> {
                val sessionId = intent.getStringExtra(EXTRA_SESSION_ID)
                val reason = intent.getSerializableExtra(EXTRA_STOP_REASON) as? StopReason
                    ?: StopReason.USER_REQUESTED
                
                if (sessionId != null) {
                    try {
                        val result = stopScanningSession(sessionId, reason)
                        
                        // 返回结果
                        val resultIntent = Intent(ACTION_SCAN_SESSION_COMPLETED)
                        resultIntent.putExtra(EXTRA_SESSION_RESULT, result)
                        LocalBroadcastManager.getInstance(this).sendBroadcast(resultIntent)
                        
                    } catch (e: Exception) {
                        Log.e("ScanService", "停止扫码失败", e)
                        sendErrorBroadcast(ErrorType.SESSION_STOP_FAILED, e.message)
                    }
                }
            }
            
            ACTION_CONFIGURE -> {
                val config = intent.getParcelableExtra<IndustrialConfig>(EXTRA_CONFIG)
                if (config != null) {
                    configManager.updateConfig(config)
                }
            }
        }
        
        return START_STICKY
    }
    
    override fun onBind(intent: Intent?): IBinder {
        return binder
    }
    
    override fun onDestroy() {
        // 清理资源
        cleanupResources()
        
        // 停止监控
        monitoringSystem.shutdown()
        
        Log.i("ScanService", "工业扫码服务已停止")
        super.onDestroy()
    }
    
    companion object {
        // 服务动作
        const val ACTION_START_SCANNING = "com.example.action.START_SCANNING"
        const val ACTION_STOP_SCANNING = "com.example.action.STOP_SCANNING"
        const val ACTION_CONFIGURE = "com.example.action.CONFIGURE"
        const val ACTION_SCAN_SESSION_STARTED = "com.example.action.SCAN_SESSION_STARTED"
        const val ACTION_SCAN_SESSION_COMPLETED = "com.example.action.SCAN_SESSION_COMPLETED"
        
        // 额外数据键
        const val EXTRA_CONFIG = "config"
        const val EXTRA_SESSION_ID = "session_id"
        const val EXTRA_STOP_REASON = "stop_reason"
        const val EXTRA_SESSION_RESULT = "session_result"
        
        /**
         * 快速启动扫码(简化API)
         */
        fun quickScan(context: Context, callback: (ScanResult) -> Unit) {
            val intent = Intent(context, IndustrialBarcodeScanningService::class.java)
            intent.action = ACTION_START_SCANNING
            intent.putExtra(EXTRA_CONFIG, ScanSessionConfig(
                scanMode = ScanMode.SINGLE,
                cameraMode = CameraMode.AUTO,
                formats = listOf(Barcode.FORMAT_ALL_FORMATS)
            ))
            
            context.startService(intent)
            
            // 注册结果接收器
            val receiver = object : BroadcastReceiver() {
                override fun onReceive(context: Context, intent: Intent) {
                    when (intent.action) {
                        ACTION_SCAN_SESSION_COMPLETED -> {
                            val result = intent.getParcelableExtra<ScanSessionResult>(EXTRA_SESSION_RESULT)
                            result?.scanResults?.firstOrNull()?.let { callback(it) }
                            LocalBroadcastManager.getInstance(context).unregisterReceiver(this)
                        }
                    }
                }
            }
            
            LocalBroadcastManager.getInstance(context).registerReceiver(
                receiver,
                IntentFilter(ACTION_SCAN_SESSION_COMPLETED)
            )
        }
    }
}

10.2 AndroidManifest配置示例

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.industrialbarcode">

    <!-- 必要权限 -->
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    
    <!-- 可选权限(增强功能) -->
    <uses-permission android:name="android.permission.FLASHLIGHT" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="28" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    
    <!-- 硬件特性 -->
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />
    <uses-feature android:name="android.hardware.camera.flash" android:required="false" />
    <uses-feature android:name="android.hardware.sensor.gyroscope" android:required="false" />
    <uses-feature android:name="android.hardware.sensor.accelerometer" android:required="false" />
    
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.IndustrialBarcode"
        android:largeHeap="true"> <!-- 允许大堆内存,适用于工业应用 -->
        
        <!-- 工业扫码服务 -->
        <service
            android:name=".service.IndustrialBarcodeScanningService"
            android:enabled="true"
            android:exported="true"
            android:foregroundServiceType="camera"
            android:permission="android.permission.BIND_JOB_SERVICE">
            
            <intent-filter>
                <action android:name="com.example.action.START_SCANNING" />
                <action android:name="com.example.action.STOP_SCANNING" />
                <action android:name="com.example.action.CONFIGURE" />
            </intent-filter>
        </service>
        
        <!-- 扫码活动 -->
        <activity
            android:name=".ui.ScanActivity"
            android:configChanges="orientation|screenSize|keyboardHidden"
            android:screenOrientation="portrait"
            android:theme="@style/Theme.IndustrialBarcode.Fullscreen">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <!-- 批量处理活动 -->
        <activity
            android:name=".ui.BatchScanActivity"
            android:configChanges="orientation|screenSize"
            android:screenOrientation="landscape"
            android:theme="@style/Theme.IndustrialBarcode.NoActionBar" />
        
        <!-- 配置活动 -->
        <activity
            android:name=".ui.ConfigurationActivity"
            android:theme="@style/Theme.IndustrialBarcode.Dialog" />
        
        <!-- 结果查看活动 -->
        <activity
            android:name=".ui.ResultReviewActivity"
            android:theme="@style/Theme.IndustrialBarcode" />
        
        <!-- 文件提供者(用于分享结果) -->
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>
        
        <!-- ML Kit自动初始化 -->
        <meta-data
            android:name="com.google.mlkit.vision.DEPENDENCIES"
            android:value="barcode" />
            
        <!-- CameraX扩展库 -->
        <meta-data
            android:name="androidx.camera.extensions.impl.LensFacingAvailability"
            android:value="back,front" />
            
        <!-- 应用性能监控 -->
        <meta-data
            android:name="firebase_performance_collection_enabled"
            android:value="true" />
            
        <!-- 崩溃报告 -->
        <meta-data
            android:name="com.google.firebase.messaging.default_notification_channel_id"
            android:value="@string/default_notification_channel_id" />
            
    </application>

</manifest>

总结与最佳实践

11.1 工业级扫码的关键成功因素

  1. 多技术融合:CameraX + ML Kit + 传感器融合 + 图像处理
  2. 环境适应性:针对不同工业场景的动态配置
  3. 错误恢复能力:自动诊断与自愈机制
  4. 性能优化:智能帧选择 + 资源管理 + GPU加速
  5. 监控运维:全面的性能监控 + 错误追踪 + 远程配置

11.2 部署建议

1. 硬件选择:

  • 优先选择支持Camera2 API Level 3的设备
  • 确保有足够的RAM(≥4GB)和存储空间
  • 考虑工业级加固设备(防尘、防水、防摔)

2. 网络环境:

  • 工业Wi-Fi或5G网络确保实时数据同步
  • 部署边缘计算节点减少云端依赖

3. 维护策略:

  • 定期校准相机和传感器
  • 更新条码数据库和识别算法
  • 监控系统性能指标

11.3 持续改进方向

  1. AI增强:使用深度学习改进低质量条码识别
  2. 3D扫描:支持曲面和扭曲条码识别
  3. 多模态融合:结合RFID、NFC等其他识别技术
  4. 边缘AI:在设备端部署更复杂的AI模型

通过本文的实现方案,您可以构建出一个达到工业级标准的二维码/条码扫描系统,满足各种严苛的工业环境需求。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐