@@ -154,115 +154,97 @@ private void loadBirdSpeciesNames(Context context) throws IOException {
154154 public List <BirdDetection > detectBirds (Bitmap bitmap ) {
155155 List <BirdDetection > results = new ArrayList <>();
156156 frameCounter ++;
157-
157+
158158 Tensor yoloInput = null ;
159159 EValue [] yoloOutputs = null ;
160-
160+
161161 try {
162162 // Cleanup old detection history every 30 frames
163163 if (frameCounter % 30 == 0 ) {
164164 cleanupOldDetections ();
165165 }
166-
166+
167167 yoloInput = preprocessForYolo (bitmap );
168168 if (yoloInput == null ) {
169169 return results ;
170170 }
171-
171+
172172 yoloOutputs = yoloModule .forward (EValue .from (yoloInput ));
173173 if (yoloOutputs == null || yoloOutputs .length == 0 ) {
174174 return results ;
175175 }
176-
176+
177177 List <Detection > detections = parseYoloV8OutputOptimized (yoloOutputs , bitmap .getWidth (), bitmap .getHeight ());
178-
178+
179179 if (DEBUG_OUTPUT ) {
180180 Log .d (TAG , "Raw detections before NMS: " + detections .size ());
181181 }
182-
182+
183183 // Apply enhanced NMS
184184 List <Detection > nmsDetections = applyEnhancedNMS (detections );
185-
185+
186186 if (DEBUG_OUTPUT ) {
187187 Log .d (TAG , "Detections after NMS: " + nmsDetections .size ());
188188 }
189-
189+
190190 // Classify each detection
191191 for (Detection detection : nmsDetections ) {
192192 try {
193193 Bitmap croppedBird = cropBitmap (bitmap , detection .boundingBox );
194194 if (croppedBird == null ) continue ;
195-
196- String species = classifyBird (croppedBird );
197-
195+
196+ String [] classificationResult = classifyBird (bitmap , detection .boundingBox );
197+ String species = (classificationResult != null && classificationResult .length > 0 ) ? classificationResult [0 ] : "Unknown Bird" ;
198+
198199 // Recycle the cropped bitmap immediately after classification
199200 if (!croppedBird .isRecycled ()) {
200201 croppedBird .recycle ();
201202 }
202-
203+
203204 // Update detection history
204205 DetectionHistory history = detectionHistory .get (detection .locationKey );
205206 if (history == null ) {
206207 history = new DetectionHistory ();
207208 detectionHistory .put (detection .locationKey , history );
208209 }
209210 history .addConfidence (detection .confidence );
210-
211+
211212 // Apply temporal bonus for stable detections
212213 float finalConfidence = detection .confidence ;
213214 if (history .isStable ()) {
214215 finalConfidence = Math .min (1.0f , detection .confidence + TEMPORAL_BONUS );
215216 }
216-
217+
217218 BirdDetection birdDetection = new BirdDetection (
218- detection .boundingBox ,
219- species ,
220- finalConfidence ,
221- history .isStable ()
219+ detection .boundingBox ,
220+ species ,
221+ finalConfidence ,
222+ history .isStable ()
222223 );
223224 results .add (birdDetection );
224-
225+
225226 if (DEBUG_OUTPUT ) {
226227 Log .d (TAG , String .format ("Bird detected: %s (%.2f) at [%.0f,%.0f,%.0f,%.0f] stable=%b" ,
227- species , finalConfidence ,
228- detection .boundingBox .left , detection .boundingBox .top ,
229- detection .boundingBox .right , detection .boundingBox .bottom ,
230- history .isStable ()));
228+ species , finalConfidence ,
229+ detection .boundingBox .left , detection .boundingBox .top ,
230+ detection .boundingBox .right , detection .boundingBox .bottom ,
231+ history .isStable ()));
231232 }
232233 } catch (Exception e ) {
233234 Log .e (TAG , "Error classifying detection" , e );
234235 }
235236 }
236-
237+
237238 if (DEBUG_OUTPUT ) {
238239 Log .d (TAG , "Final bird detections: " + results .size ());
239240 }
240-
241+
241242 } catch (Exception e ) {
242243 Log .e (TAG , "Error in detectBirds" , e );
243244 } finally {
244- // CRITICAL: Release tensors to prevent memory leak
245- if (yoloInput != null ) {
246- try {
247- yoloInput .close ();
248- } catch (Exception e ) {
249- Log .e (TAG , "Error closing yoloInput" , e );
250- }
251- }
252-
253- if (yoloOutputs != null ) {
254- for (EValue output : yoloOutputs ) {
255- if (output != null ) {
256- try {
257- output .close ();
258- } catch (Exception e ) {
259- Log .e (TAG , "Error closing output" , e );
260- }
261- }
262- }
263- }
245+ // Note: ExecutorTorch handles tensor cleanup automatically via garbage collection
264246 }
265-
247+
266248 return results ;
267249 }
268250
@@ -349,7 +331,7 @@ private void cleanupOldDetections() {
349331 */
350332 public void close () {
351333 Log .d (TAG , "Closing BirdDetectionPipeline and releasing resources" );
352-
334+
353335 try {
354336 if (yoloModule != null ) {
355337 yoloModule .destroy ();
@@ -358,7 +340,7 @@ public void close() {
358340 } catch (Exception e ) {
359341 Log .e (TAG , "Error destroying yoloModule" , e );
360342 }
361-
343+
362344 try {
363345 if (classifierModule != null ) {
364346 classifierModule .destroy ();
@@ -367,12 +349,12 @@ public void close() {
367349 } catch (Exception e ) {
368350 Log .e (TAG , "Error destroying classifierModule" , e );
369351 }
370-
352+
371353 // Clear detection history
372354 if (detectionHistory != null ) {
373355 detectionHistory .clear ();
374356 }
375-
357+
376358 Log .d (TAG , "BirdDetectionPipeline closed successfully" );
377359 }
378360
0 commit comments