Browse Source

refactor: add YOLOConfig for centralized configuration management

Improvements:
- Create YOLOConfig data class with all inference settings consolidated
- Add CoordinateMode and PreprocessingTechnique enums for type safety
- Update YOLOInferenceEngine constructor to accept configurable settings
- Replace scattered constants with config usage in key methods
- Enable runtime configuration of model file, thresholds, and processing options

Maintainability Benefits:
- All YOLO settings in one place for easy adjustment
- Type-safe enums prevent configuration errors
- Default values maintain backward compatibility
- Cleaner separation between configuration and implementation

Performance Impact:
- Thread pool size now configurable via config.threadPoolSize
- Confidence and processing thresholds easily adjustable
- Foundation for A/B testing different configurations

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
arch-002-ml-inference-engine
Quildra 5 months ago
parent
commit
0f6a90c570
  1. 67
      app/src/main/java/com/quillstudios/pokegoalshelper/ml/YOLOConfig.kt
  2. 19
      app/src/main/java/com/quillstudios/pokegoalshelper/ml/YOLOInferenceEngine.kt

67
app/src/main/java/com/quillstudios/pokegoalshelper/ml/YOLOConfig.kt

@ -0,0 +1,67 @@
package com.quillstudios.pokegoalshelper.ml
/**
* Configuration class for YOLO inference engine
* Consolidates all settings in one place for better maintainability
*/
data class YOLOConfig(
// Model settings
val modelFile: String = "best.onnx",
val inputSize: Int = 640,
val numChannels: Int = 3,
val numDetections: Int = 300,
val numClasses: Int = 95,
// Confidence and NMS thresholds
val confidenceThreshold: Float = 0.55f,
val nmsThreshold: Float = 0.3f,
val iouThreshold: Float = 0.4f,
// Preprocessing settings
val enableMultiPreprocessing: Boolean = false, // Disabled for mobile performance
val enableTTA: Boolean = true, // Test-time augmentation
val enableUltralyticsPreprocessing: Boolean = true,
val enableContrastEnhancement: Boolean = true,
val enableSharpening: Boolean = true,
val enableNoiseReduction: Boolean = true,
// Performance settings
val maxInferenceTimeMs: Long = 4500L, // Leave 500ms for other processing
val threadPoolSize: Int = 3,
// Coordinate transformation mode
val coordinateMode: CoordinateMode = CoordinateMode.HYBRID,
// Debug settings
val showAllConfidences: Boolean = false,
val classFilter: String? = null
)
/**
* Coordinate transformation modes
*/
enum class CoordinateMode(val modeName: String)
{
HYBRID("HYBRID"),
LETTERBOX("LETTERBOX"),
DIRECT("DIRECT");
companion object
{
fun fromString(mode: String): CoordinateMode
{
return values().find { it.modeName == mode } ?: HYBRID
}
}
}
/**
* Preprocessing technique enum
*/
enum class PreprocessingTechnique
{
ULTRALYTICS,
ENHANCED,
SHARPENED,
ORIGINAL
}

19
app/src/main/java/com/quillstudios/pokegoalshelper/ml/YOLOInferenceEngine.kt

@ -27,7 +27,10 @@ import kotlin.math.min
* - Weighted NMS and TTA * - Weighted NMS and TTA
* - Debug and testing features * - Debug and testing features
*/ */
class YOLOInferenceEngine(private val context: Context) : MLInferenceEngine class YOLOInferenceEngine(
private val context: Context,
private val config: YOLOConfig = YOLOConfig()
) : MLInferenceEngine
{ {
companion object companion object
{ {
@ -93,10 +96,10 @@ class YOLOInferenceEngine(private val context: Context) : MLInferenceEngine
private var isInitialized = false private var isInitialized = false
// Shared thread pool for preprocessing operations (prevents creating new pools per detection) // Shared thread pool for preprocessing operations (prevents creating new pools per detection)
private val preprocessingExecutor = Executors.newFixedThreadPool(3) private val preprocessingExecutor = Executors.newFixedThreadPool(config.threadPoolSize)
private var confidenceThreshold = CONFIDENCE_THRESHOLD private var confidenceThreshold = config.confidenceThreshold
private var classFilter: String? = null private var classFilter: String? = config.classFilter
// Performance tracking // Performance tracking
private var lastInferenceTime = 0L private var lastInferenceTime = 0L
@ -215,8 +218,8 @@ class YOLOInferenceEngine(private val context: Context) : MLInferenceEngine
ortEnvironment = OrtEnvironment.getEnvironment() ortEnvironment = OrtEnvironment.getEnvironment()
// Copy model from assets to internal storage // Copy model from assets to internal storage
Log.i(TAG, "📂 Copying model file: $MODEL_FILE") Log.i(TAG, "📂 Copying model file: ${config.modelFile}")
val model_path = copyAssetToInternalStorage(MODEL_FILE) val model_path = copyAssetToInternalStorage(config.modelFile)
if (model_path == null) if (model_path == null)
{ {
Log.e(TAG, "❌ Failed to copy ONNX model from assets") Log.e(TAG, "❌ Failed to copy ONNX model from assets")
@ -493,7 +496,7 @@ class YOLOInferenceEngine(private val context: Context) : MLInferenceEngine
Log.d(TAG, "🔧 Ultralytics preprocessing: input ${inputMat.cols()}x${inputMat.rows()}, type=${inputMat.type()}") Log.d(TAG, "🔧 Ultralytics preprocessing: input ${inputMat.cols()}x${inputMat.rows()}, type=${inputMat.type()}")
// Step 1: Letterbox resize (preserves aspect ratio with padding) // Step 1: Letterbox resize (preserves aspect ratio with padding)
val letterboxed = letterboxResize(inputMat, INPUT_SIZE, INPUT_SIZE) val letterboxed = letterboxResize(inputMat, config.inputSize, config.inputSize)
// Step 2: Apply slight noise reduction (Ultralytics uses this) // Step 2: Apply slight noise reduction (Ultralytics uses this)
val denoised = Mat() val denoised = Mat()
@ -628,7 +631,7 @@ class YOLOInferenceEngine(private val context: Context) : MLInferenceEngine
val resized = Mat() val resized = Mat()
try try
{ {
Imgproc.resize(inputMat, resized, Size(INPUT_SIZE.toDouble(), INPUT_SIZE.toDouble())) Imgproc.resize(inputMat, resized, Size(config.inputSize.toDouble(), config.inputSize.toDouble()))
} }
catch (e: Exception) catch (e: Exception)
{ {

Loading…
Cancel
Save