Skip to content

Commit 08258c9

Browse files
committed
implement individual export
1 parent aa66127 commit 08258c9

File tree

4 files changed

+89
-0
lines changed

4 files changed

+89
-0
lines changed

photon-client/src/components/settings/ObjectDetectionCard.vue

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,11 @@ const openExportPrompt = () => {
170170
exportModels.value.click();
171171
};
172172
173+
const exportIndividualModel = ref();
174+
const openExportIndividualModelPrompt = () => {
175+
exportIndividualModel.value.click();
176+
};
177+
173178
const showNukeDialog = ref(false);
174179
const expected = "Delete Models";
175180
const yesDeleteMyModelsText = ref("");
@@ -367,6 +372,17 @@ const nukeModels = () => {
367372
<v-dialog v-model="showInfo.show" width="600">
368373
<v-card color="primary" dark>
369374
<v-card-title>Object Detection Model Info</v-card-title>
375+
<v-btn color="secondary" @click="openExportIndividualModelPrompt">
376+
<v-icon left class="open-icon"> mdi-export </v-icon>
377+
<span class="open-label">Export Models</span>
378+
</v-btn>
379+
<a
380+
ref="exportIndividualModel"
381+
style="color: black; text-decoration: none; display: none"
382+
:href="`http://${address}/api/objectdetection/exportIndividual?modelPath=${showInfo.model.modelPath}`"
383+
:download="`${showInfo.model.nickname}-${showInfo.model.family}-${showInfo.model.version}-${showInfo.model.resolutionWidth}x${showInfo.model.resolutionHeight}.zip`"
384+
target="_blank"
385+
/>
370386
<v-card-text>
371387
<p>Model Path: {{ showInfo.model.modelPath }}</p>
372388
<p>Model Nickname: {{ showInfo.model.nickname }}</p>

photon-core/src/main/java/org/photonvision/common/configuration/NeuralNetworkModelManager.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.photonvision.common.logging.Logger;
4040
import org.photonvision.vision.objects.Model;
4141
import org.photonvision.vision.objects.RknnModel;
42+
import org.zeroturnaround.zip.ZipUtil;
4243

4344
/**
4445
* Manages the loading of neural network models.
@@ -331,4 +332,42 @@ public boolean nukeModels() {
331332
// Delete model info
332333
return ConfigManager.getInstance().getConfig().neuralNetworkPropertyManager().nuke();
333334
}
335+
336+
public File zipModel(String modelPath) {
337+
File modelFile = new File(modelPath);
338+
if (!modelFile.exists()) {
339+
logger.error("Model file does not exist: " + modelFile.getAbsolutePath());
340+
return null;
341+
}
342+
343+
ModelProperties properties =
344+
ConfigManager.getInstance()
345+
.getConfig()
346+
.neuralNetworkPropertyManager()
347+
.getModel(Path.of(modelPath));
348+
349+
String fileName = "";
350+
if (properties != null) {
351+
fileName =
352+
String.format(
353+
"%s-%s-%s-%dx%d",
354+
properties.nickname().replace(" ", ""),
355+
properties.family(),
356+
properties.version(),
357+
properties.resolutionWidth(),
358+
properties.resolutionHeight());
359+
} else {
360+
fileName = new File(modelPath).getName();
361+
}
362+
363+
try {
364+
var out = Files.createTempFile(fileName, ".zip");
365+
ZipUtil.pack(new File(modelPath), out.toFile());
366+
return out.toFile();
367+
} catch (Exception e) {
368+
e.printStackTrace();
369+
logger.error("Failed to zip model file: " + modelFile.getAbsolutePath(), e);
370+
return null;
371+
}
372+
}
334373
}

photon-server/src/main/java/org/photonvision/server/RequestHandler.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,37 @@ public static void onExportObjectDetectionModelRequest(Context ctx) {
682682
}
683683
}
684684

685+
public static void onExportIndividualObjectDetectionModelRequest(Context ctx) {
686+
logger.info("Exporting Object Detection Model to ZIP Archive");
687+
688+
try {
689+
var modelPath = ctx.formParam("modelPath");
690+
691+
if (modelPath == null || modelPath.isEmpty()) {
692+
ctx.status(400);
693+
ctx.result("The provided model path was malformed");
694+
logger.error("The provided model path was malformed");
695+
return;
696+
}
697+
698+
var zip = NeuralNetworkModelManager.getInstance().zipModel(modelPath);
699+
700+
var stream = new FileInputStream(zip);
701+
logger.info("Uploading object detection model with size " + stream.available());
702+
703+
ctx.contentType("application/zip");
704+
ctx.header("Content-Disposition", "attachment; filename=" + zip.getName());
705+
706+
ctx.result(stream);
707+
ctx.status(200);
708+
} catch (IOException e) {
709+
logger.error(
710+
"Unable to export object detection model archive, bad recode from zip to byte, " + e);
711+
ctx.status(500);
712+
ctx.result("There was an error while exporting the object detection model archive");
713+
}
714+
}
715+
685716
public static void onBulkImportObjectDetectionModelRequest(Context ctx) {
686717
var file = ctx.uploadedFile("data");
687718

photon-server/src/main/java/org/photonvision/server/Server.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@ private static void start(int port) {
150150
// Object detection
151151
app.post("/api/objectdetection/import", RequestHandler::onImportObjectDetectionModelRequest);
152152
app.post("/api/objectdetection/export", RequestHandler::onExportObjectDetectionModelRequest);
153+
app.post(
154+
"/api/objectdetection/exportindividual",
155+
RequestHandler::onExportIndividualObjectDetectionModelRequest);
153156
app.post("/api/objectdetection/delete", RequestHandler::onDeleteObjectDetectionModelRequest);
154157
app.post("/api/objectdetection/rename", RequestHandler::onRenameObjectDetectionModelRequest);
155158
app.post("/api/objectdetection/nuke", RequestHandler::onNukeObjectDetectionModelsRequest);

0 commit comments

Comments
 (0)