mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-07-31 16:12:19 +03:00
Snap points to edges and create object mask from bounding box (#16488)
This commit is contained in:
@@ -37,6 +37,7 @@ import PolygonItem from "@/components/settings/PolygonItem";
|
||||
import { Link } from "react-router-dom";
|
||||
import { isDesktop } from "react-device-detect";
|
||||
import { StatusBarMessagesContext } from "@/context/statusbar-provider";
|
||||
import { useSearchEffect } from "@/hooks/use-overlay-state";
|
||||
|
||||
type MasksAndZoneViewProps = {
|
||||
selectedCamera: string;
|
||||
@@ -62,6 +63,7 @@ export default function MasksAndZonesView({
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
const [editPane, setEditPane] = useState<PolygonType | undefined>(undefined);
|
||||
const [activeLine, setActiveLine] = useState<number | undefined>();
|
||||
const [snapPoints, setSnapPoints] = useState(false);
|
||||
|
||||
const { addMessage } = useContext(StatusBarMessagesContext)!;
|
||||
|
||||
@@ -142,7 +144,7 @@ export default function MasksAndZonesView({
|
||||
}
|
||||
}, [scaledHeight, aspectRatio]);
|
||||
|
||||
const handleNewPolygon = (type: PolygonType) => {
|
||||
const handleNewPolygon = (type: PolygonType, coordinates?: number[][]) => {
|
||||
if (!cameraConfig) {
|
||||
return;
|
||||
}
|
||||
@@ -161,9 +163,9 @@ export default function MasksAndZonesView({
|
||||
setEditingPolygons([
|
||||
...(allPolygons || []),
|
||||
{
|
||||
points: [],
|
||||
points: coordinates ?? [],
|
||||
distances: [],
|
||||
isFinished: false,
|
||||
isFinished: coordinates ? true : false,
|
||||
type,
|
||||
typeIndex: 9999,
|
||||
name: "",
|
||||
@@ -373,6 +375,48 @@ export default function MasksAndZonesView({
|
||||
}
|
||||
}, [selectedCamera]);
|
||||
|
||||
useSearchEffect("object_mask", (coordinates: string) => {
|
||||
if (!scaledWidth || !scaledHeight || isLoading) {
|
||||
return false;
|
||||
}
|
||||
// convert box points string to points array
|
||||
const points = coordinates.split(",").map((p) => parseFloat(p));
|
||||
|
||||
const [x1, y1, w, h] = points;
|
||||
|
||||
// bottom center
|
||||
const centerX = x1 + w / 2;
|
||||
const bottomY = y1 + h;
|
||||
|
||||
const centerXAbs = centerX * scaledWidth;
|
||||
const bottomYAbs = bottomY * scaledHeight;
|
||||
|
||||
// padding and clamp
|
||||
const minPadding = 0.1 * w * scaledWidth;
|
||||
const maxPadding = 0.3 * w * scaledWidth;
|
||||
const padding = Math.min(
|
||||
Math.max(minPadding, 0.15 * w * scaledWidth),
|
||||
maxPadding,
|
||||
);
|
||||
|
||||
const top = Math.max(0, bottomYAbs - padding);
|
||||
const bottom = Math.min(scaledHeight, bottomYAbs + padding);
|
||||
const left = Math.max(0, centerXAbs - padding);
|
||||
const right = Math.min(scaledWidth, centerXAbs + padding);
|
||||
|
||||
const paddedBox = [
|
||||
[left, top],
|
||||
[right, top],
|
||||
[right, bottom],
|
||||
[left, bottom],
|
||||
];
|
||||
|
||||
setEditPane("object_mask");
|
||||
setActivePolygonIndex(undefined);
|
||||
handleNewPolygon("object_mask", paddedBox);
|
||||
return true;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
document.title = "Mask and Zone Editor - Frigate";
|
||||
}, []);
|
||||
@@ -399,6 +443,8 @@ export default function MasksAndZonesView({
|
||||
onCancel={handleCancel}
|
||||
onSave={handleSave}
|
||||
setActiveLine={setActiveLine}
|
||||
snapPoints={snapPoints}
|
||||
setSnapPoints={setSnapPoints}
|
||||
/>
|
||||
)}
|
||||
{editPane == "motion_mask" && (
|
||||
@@ -412,6 +458,8 @@ export default function MasksAndZonesView({
|
||||
setIsLoading={setIsLoading}
|
||||
onCancel={handleCancel}
|
||||
onSave={handleSave}
|
||||
snapPoints={snapPoints}
|
||||
setSnapPoints={setSnapPoints}
|
||||
/>
|
||||
)}
|
||||
{editPane == "object_mask" && (
|
||||
@@ -425,6 +473,8 @@ export default function MasksAndZonesView({
|
||||
setIsLoading={setIsLoading}
|
||||
onCancel={handleCancel}
|
||||
onSave={handleSave}
|
||||
snapPoints={snapPoints}
|
||||
setSnapPoints={setSnapPoints}
|
||||
/>
|
||||
)}
|
||||
{editPane === undefined && (
|
||||
@@ -662,6 +712,7 @@ export default function MasksAndZonesView({
|
||||
hoveredPolygonIndex={hoveredPolygonIndex}
|
||||
selectedZoneMask={selectedZoneMask}
|
||||
activeLine={activeLine}
|
||||
snapPoints={true}
|
||||
/>
|
||||
) : (
|
||||
<Skeleton className="size-full" />
|
||||
|
||||
Reference in New Issue
Block a user