Skip to content

Commit bf4c34c

Browse files
author
Github Executorch
committed
Fixup memory issues
1 parent 9ba3d38 commit bf4c34c

2 files changed

Lines changed: 55 additions & 80 deletions

File tree

Yolo/android/app/src/main/java/com/example/executorchyolodemo/BirdDetectionActivity.java

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -100,25 +100,36 @@ protected void onCreate(Bundle savedInstanceState) {
100100
@Override
101101
protected void onDestroy() {
102102
super.onDestroy();
103-
103+
104104
// Clean up the detection pipeline
105-
if (detectionPipeline != null) {
106-
detectionPipeline.close();
107-
detectionPipeline = null;
105+
if (birdPipeline != null) {
106+
birdPipeline.close();
107+
birdPipeline = null;
108+
}
109+
110+
// Shutdown camera executor
111+
if (cameraExecutor != null) {
112+
cameraExecutor.shutdown();
113+
}
114+
115+
// Clean up session manager
116+
if (sessionManager != null) {
117+
sessionManager.cleanup();
108118
}
109-
119+
110120
Log.d(TAG, "BirdDetectionActivity destroyed");
111121
}
112122

113123
@Override
114124
protected void onPause() {
115125
super.onPause();
116-
117-
// Optional: Release resources when app goes to background
118-
if (detectionPipeline != null) {
119-
detectionPipeline.close();
120-
detectionPipeline = null;
121-
}
126+
Log.d(TAG, "BirdDetectionActivity paused");
127+
}
128+
129+
@Override
130+
protected void onResume() {
131+
super.onResume();
132+
updateSessionUI();
122133
}
123134

124135
private void initializeViews() {
@@ -438,22 +449,4 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis
438449
}
439450
}
440451
}
441-
442-
@Override
443-
protected void onDestroy() {
444-
super.onDestroy();
445-
cameraExecutor.shutdown();
446-
if (birdPipeline != null) {
447-
birdPipeline.cleanup();
448-
}
449-
if (sessionManager != null) {
450-
sessionManager.cleanup();
451-
}
452-
}
453-
454-
@Override
455-
protected void onResume() {
456-
super.onResume();
457-
updateSessionUI();
458-
}
459452
}

Yolo/android/app/src/main/java/com/example/executorchyolodemo/BirdDetectionPipeline.java

Lines changed: 33 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)