Browse Source

fix: correct NUM_DETECTIONS and remove debug code

- Fix NUM_DETECTIONS constant from 8400 to 300 for NMS-enabled ONNX model
- Completely remove DEBUG_DETECTION flag and all shiny debug logging blocks
- Clean up code for production readiness

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

Co-Authored-By: Claude <noreply@anthropic.com>
feature/debug-shiny-pokeball-detection
Quildra 5 months ago
parent
commit
c810254d33
  1. 129
      app/src/main/java/com/quillstudios/pokegoalshelper/YOLOOnnxDetector.kt

129
app/src/main/java/com/quillstudios/pokegoalshelper/YOLOOnnxDetector.kt

@ -21,10 +21,10 @@ class YOLOOnnxDetector(private val context: Context) {
private const val TAG = "YOLOOnnxDetector"
private const val MODEL_FILE = "best.onnx"
private const val INPUT_SIZE = 640
private const val CONFIDENCE_THRESHOLD = 0.25f // Temporarily lowered for shiny icon debugging
private const val CONFIDENCE_THRESHOLD = 0.55f
private const val NMS_THRESHOLD = 0.3f // More aggressive merging of overlapping boxes
private const val NUM_CHANNELS = 3
private const val NUM_DETECTIONS = 8400 // YOLOv8 default
private const val NUM_DETECTIONS = 300 // ONNX model exported with NMS enabled
private const val NUM_CLASSES = 95 // Your class count
// Enhanced accuracy settings for ONNX (fixed input size) - WITH PER-METHOD COORDINATE TRANSFORM
@ -39,8 +39,6 @@ class YOLOOnnxDetector(private val context: Context) {
var DEBUG_CLASS_FILTER: String? = null // Set to class name to show only that class
var SHOW_ALL_CONFIDENCES = false // Show all detections with their confidences
// Debug flag for troubleshooting detection issues (disable in production)
private const val DEBUG_DETECTION = false
fun setCoordinateMode(mode: String) {
COORD_TRANSFORM_MODE = mode
@ -405,121 +403,6 @@ class YOLOOnnxDetector(private val context: Context) {
val outputTensor = result.get(0).value as Array<Array<FloatArray>>
val flatOutput = outputTensor[0].flatMap { it.asIterable() }.toFloatArray()
// Debug: Log raw output statistics when looking for shiny icons
if (DEBUG_DETECTION) {
val maxVal = flatOutput.maxOrNull() ?: 0f
val nonZeroCount = flatOutput.count { it > 0.01f }
Log.w(TAG, "🔬 [RAW OUTPUT] Method: $method, FlatOutput size: ${flatOutput.size}, Max value: %.4f, Non-zero (>0.01): $nonZeroCount".format(maxVal))
// Log actual tensor dimensions to understand the model output format
Log.w(TAG, "🔬 [TENSOR DIMS] OutputTensor shape: ${outputTensor.size} x ${outputTensor[0].size} x ${outputTensor[0][0].size}")
// Handle different model output formats
val dim1 = outputTensor[0].size
val dim2 = outputTensor[0][0].size
if ((dim1 == 300 || dim1 == 500 || dim1 == 1000) && dim2 == 6) {
// NMS-enabled model (1 x N x 6) format where N = max_det
var shinyFound = false
val detectedClasses = mutableSetOf<Int>()
var class50NonZeroCount = 0
var totalClass50Count = 0
var class29Count = 0
for (i in 0 until dim1) {
val detection = outputTensor[0][i]
val confidence = detection[4]
val classId = detection[5].toInt()
// Count ALL class 50 detections, regardless of confidence
if (classId == 50) {
totalClass50Count++
if (confidence > 0.000001f) { // Any non-zero confidence
class50NonZeroCount++
Log.w(TAG, "🔍 [CLASS 50] Index: $i, Confidence: %.6f, Coords: [%.1f,%.1f,%.1f,%.1f]".format(confidence, detection[0], detection[1], detection[2], detection[3]))
}
}
// Also check class 29 for comparison
if (classId == 29) {
class29Count++
if (confidence > 0.01f) { // Much lower threshold for known working class
shinyFound = true
Log.w(TAG, "✨ [CLASS 29] Index: $i, Confidence: %.4f, Coords: [%.1f,%.1f,%.1f,%.1f]".format(confidence, detection[0], detection[1], detection[2], detection[3]))
}
}
if (confidence > 0.1f) {
detectedClasses.add(classId)
}
}
Log.w(TAG, "🔍 [SUMMARY] Class 29: $class29Count total, Class 50: $totalClass50Count total ($class50NonZeroCount non-zero)")
Log.w(TAG, "🔬 [NMS CLASSES] Detected classes: ${detectedClasses.sorted()}")
if (!shinyFound) {
Log.w(TAG, "❌ [NO SHINY] Shiny icon (class 50) not found in NMS output")
}
} else if (dim1 == 100 && dim2 == 8400) {
// Raw no-NMS model (1 x 100 x 8400) format: [x,y,w,h,objectness,class0,class1,...,class94] × 8400 detections
Log.w(TAG, "🔬 [RAW MODEL] Detected raw no-NMS format: checking for shiny icons in 8400 detections")
var shinyFound = false
var maxRawShiny = 0f
var maxSigmoidShiny = 0f
var shinyDetectionCount = 0
val highConfShinyBoxes = mutableListOf<String>()
val topShinyDetections = mutableListOf<Pair<Float, Int>>()
// Class 50 data starts at index 55 (after x,y,w,h,objectness + 50 classes)
val shinyClassRow = 4 + 1 + 50 // row 55
for (detectionIdx in 0 until 8400) {
val rawShinyValue = outputTensor[0][shinyClassRow][detectionIdx]
// Try sigmoid activation to convert logits to probabilities
val shinyConfidence = 1.0f / (1.0f + kotlin.math.exp(-rawShinyValue))
if (rawShinyValue > maxRawShiny) {
maxRawShiny = rawShinyValue
}
if (shinyConfidence > maxSigmoidShiny) {
maxSigmoidShiny = shinyConfidence
}
// Track top detections for debugging
topShinyDetections.add(Pair(shinyConfidence, detectionIdx))
if (shinyConfidence > 0.1f) {
shinyDetectionCount++
shinyFound = true
// Get bounding box coordinates
val x = outputTensor[0][0][detectionIdx]
val y = outputTensor[0][1][detectionIdx]
val w = outputTensor[0][2][detectionIdx]
val h = outputTensor[0][3][detectionIdx]
highConfShinyBoxes.add("Detection $detectionIdx: raw=%.4f, sigmoid=%.4f, box=[%.1f,%.1f,%.1f,%.1f]".format(rawShinyValue, shinyConfidence, x, y, w, h))
}
}
// Show top shiny detections for debugging
val topShiny = topShinyDetections.sortedByDescending { it.first }.take(3)
Log.w(TAG, "🔬 [RAW SHINY] Max raw: %.4f, Max sigmoid: %.4f, Count >0.1: $shinyDetectionCount".format(maxRawShiny, maxSigmoidShiny))
Log.w(TAG, "🔬 [TOP SHINY] Top 3 sigmoid values: ${topShiny.map { "%.4f@${it.second}".format(it.first) }}")
if (shinyFound) {
Log.w(TAG, "✨ [RAW SHINY FOUND] High-confidence shiny detections:")
highConfShinyBoxes.take(5).forEach { Log.w(TAG, " $it") }
} else {
Log.w(TAG, "❌ [RAW NO SHINY] No high-confidence shiny detections in raw 8400 predictions")
}
} else {
Log.w(TAG, "🔬 [UNKNOWN FORMAT] Unexpected tensor shape: ${outputTensor.size}x${dim1}x${dim2}")
}
}
// Post-process results with method-specific coordinate transformation
val detections = postprocessWithMethod(flatOutput, inputMat.cols(), inputMat.rows(), INPUT_SIZE, method)
@ -893,10 +776,6 @@ class YOLOOnnxDetector(private val context: Context) {
Log.d(TAG, "🔍 [DEBUG] Class: $className (ID: $classId), Confidence: %.3f, Original: %.3f".format(mappedConfidence, confidence))
}
// Special debug logging for shiny icon (class 50)
if (DEBUG_DETECTION && (classId == 50 || className == "shiny_icon") && mappedConfidence > 0.05f) {
Log.w(TAG, "✨ [SHINY DEBUG] Found shiny_icon candidate! ClassID: $classId, Confidence: %.4f (mapped: %.4f), Coords: [%.1f,%.1f,%.1f,%.1f]".format(confidence, mappedConfidence, x1, y1, x2, y2))
}
// Apply class filtering if set
val passesClassFilter = DEBUG_CLASS_FILTER == null || DEBUG_CLASS_FILTER == className
@ -1230,10 +1109,6 @@ class YOLOOnnxDetector(private val context: Context) {
Log.d(TAG, "🔍 [DEBUG] Class: $className (ID: $classId), Confidence: %.3f, Original: %.3f".format(mappedConfidence, confidence))
}
// Special debug logging for shiny icon (class 50)
if (DEBUG_DETECTION && (classId == 50 || className == "shiny_icon") && mappedConfidence > 0.05f) {
Log.w(TAG, "✨ [SHINY DEBUG] Found shiny_icon candidate! ClassID: $classId, Confidence: %.4f (mapped: %.4f), Coords: [%.1f,%.1f,%.1f,%.1f]".format(confidence, mappedConfidence, x1, y1, x2, y2))
}
// Apply class filtering if set
val passesClassFilter = DEBUG_CLASS_FILTER == null || DEBUG_CLASS_FILTER == className

Loading…
Cancel
Save