mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-12-06 21:44:13 +03:00
Implement rename class api
This commit is contained in:
parent
c3993eec22
commit
31b8357fc2
@ -680,6 +680,97 @@ def delete_classification_dataset_images(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.put(
|
||||||
|
"/classification/{name}/dataset/{old_category}/rename",
|
||||||
|
response_model=GenericResponse,
|
||||||
|
dependencies=[Depends(require_role(["admin"]))],
|
||||||
|
summary="Rename a classification category",
|
||||||
|
description="""Renames a classification category for a given classification model.
|
||||||
|
The old category must exist and the new name must be valid. Returns a success message or an error if the name is invalid.""",
|
||||||
|
)
|
||||||
|
def rename_classification_category(
|
||||||
|
request: Request, name: str, old_category: str, body: dict = None
|
||||||
|
):
|
||||||
|
config: FrigateConfig = request.app.frigate_config
|
||||||
|
|
||||||
|
if name not in config.classification.custom:
|
||||||
|
return JSONResponse(
|
||||||
|
content=(
|
||||||
|
{
|
||||||
|
"success": False,
|
||||||
|
"message": f"{name} is not a known classification model.",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
status_code=404,
|
||||||
|
)
|
||||||
|
|
||||||
|
json: dict[str, Any] = body or {}
|
||||||
|
new_category = sanitize_filename(json.get("new_category", ""))
|
||||||
|
|
||||||
|
if not new_category:
|
||||||
|
return JSONResponse(
|
||||||
|
content=(
|
||||||
|
{
|
||||||
|
"success": False,
|
||||||
|
"message": "New category name is required.",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
status_code=400,
|
||||||
|
)
|
||||||
|
|
||||||
|
old_folder = os.path.join(
|
||||||
|
CLIPS_DIR, sanitize_filename(name), "dataset", sanitize_filename(old_category)
|
||||||
|
)
|
||||||
|
new_folder = os.path.join(
|
||||||
|
CLIPS_DIR, sanitize_filename(name), "dataset", new_category
|
||||||
|
)
|
||||||
|
|
||||||
|
if not os.path.exists(old_folder):
|
||||||
|
return JSONResponse(
|
||||||
|
content=(
|
||||||
|
{
|
||||||
|
"success": False,
|
||||||
|
"message": f"Category {old_category} does not exist.",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
status_code=404,
|
||||||
|
)
|
||||||
|
|
||||||
|
if os.path.exists(new_folder):
|
||||||
|
return JSONResponse(
|
||||||
|
content=(
|
||||||
|
{
|
||||||
|
"success": False,
|
||||||
|
"message": f"Category {new_category} already exists.",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
status_code=400,
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.rename(old_folder, new_folder)
|
||||||
|
return JSONResponse(
|
||||||
|
content=(
|
||||||
|
{
|
||||||
|
"success": True,
|
||||||
|
"message": f"Successfully renamed category to {new_category}.",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
status_code=200,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error renaming category: {e}")
|
||||||
|
return JSONResponse(
|
||||||
|
content=(
|
||||||
|
{
|
||||||
|
"success": False,
|
||||||
|
"message": f"Failed to rename category: {str(e)}",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
status_code=500,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.post(
|
@router.post(
|
||||||
"/classification/{name}/dataset/categorize",
|
"/classification/{name}/dataset/categorize",
|
||||||
response_model=GenericResponse,
|
response_model=GenericResponse,
|
||||||
|
|||||||
@ -22,7 +22,8 @@
|
|||||||
"categorizedImage": "Successfully Classified Image",
|
"categorizedImage": "Successfully Classified Image",
|
||||||
"trainedModel": "Successfully trained model.",
|
"trainedModel": "Successfully trained model.",
|
||||||
"trainingModel": "Successfully started model training.",
|
"trainingModel": "Successfully started model training.",
|
||||||
"updatedModel": "Successfully updated model configuration"
|
"updatedModel": "Successfully updated model configuration",
|
||||||
|
"renamedCategory": "Successfully renamed class to {{name}}"
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"deleteImageFailed": "Failed to delete: {{errorMessage}}",
|
"deleteImageFailed": "Failed to delete: {{errorMessage}}",
|
||||||
@ -30,7 +31,8 @@
|
|||||||
"deleteModelFailed": "Failed to delete model: {{errorMessage}}",
|
"deleteModelFailed": "Failed to delete model: {{errorMessage}}",
|
||||||
"categorizeFailed": "Failed to categorize image: {{errorMessage}}",
|
"categorizeFailed": "Failed to categorize image: {{errorMessage}}",
|
||||||
"trainingFailed": "Failed to start model training: {{errorMessage}}",
|
"trainingFailed": "Failed to start model training: {{errorMessage}}",
|
||||||
"updateModelFailed": "Failed to update model: {{errorMessage}}"
|
"updateModelFailed": "Failed to update model: {{errorMessage}}",
|
||||||
|
"renameCategoryFailed": "Failed to rename class: {{errorMessage}}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deleteCategory": {
|
"deleteCategory": {
|
||||||
|
|||||||
@ -187,6 +187,37 @@ export default function ModelTrainingView({ model }: ModelTrainingViewProps) {
|
|||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const onRename = useCallback(
|
||||||
|
(old_name: string, new_name: string) => {
|
||||||
|
axios
|
||||||
|
.put(`/classification/${model.name}/dataset/${old_name}/rename`, {
|
||||||
|
new_category: new_name,
|
||||||
|
})
|
||||||
|
.then((resp) => {
|
||||||
|
if (resp.status == 200) {
|
||||||
|
toast.success(
|
||||||
|
t("toast.success.renamedCategory", { name: new_name }),
|
||||||
|
{
|
||||||
|
position: "top-center",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
setPageToggle(new_name);
|
||||||
|
refreshDataset();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
const errorMessage =
|
||||||
|
error.response?.data?.message ||
|
||||||
|
error.response?.data?.detail ||
|
||||||
|
"Unknown error";
|
||||||
|
toast.error(t("toast.error.renameCategoryFailed", { errorMessage }), {
|
||||||
|
position: "top-center",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[model, setPageToggle, refreshDataset, t],
|
||||||
|
);
|
||||||
|
|
||||||
const onDelete = useCallback(
|
const onDelete = useCallback(
|
||||||
(ids: string[], isName: boolean = false, category?: string) => {
|
(ids: string[], isName: boolean = false, category?: string) => {
|
||||||
const targetCategory = category || pageToggle;
|
const targetCategory = category || pageToggle;
|
||||||
@ -354,7 +385,7 @@ export default function ModelTrainingView({ model }: ModelTrainingViewProps) {
|
|||||||
trainImages={trainImages || []}
|
trainImages={trainImages || []}
|
||||||
setPageToggle={setPageToggle}
|
setPageToggle={setPageToggle}
|
||||||
onDelete={onDelete}
|
onDelete={onDelete}
|
||||||
onRename={() => {}}
|
onRename={onRename}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user