mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-18 09:04:28 +03:00
Add save and display image before OCR
This commit is contained in:
parent
bd7c10f5f1
commit
2b1afe6073
@ -165,6 +165,14 @@ class LicensePlateRecognition:
|
||||
logger.debug("Model runners not loaded")
|
||||
return [], [], []
|
||||
|
||||
# Save raw image before processing if event_id is provided
|
||||
if event_id:
|
||||
try:
|
||||
raw_filename = f"raw_{event_id}.jpg"
|
||||
cv2.imwrite(os.path.join(self.debug_dir, raw_filename), image)
|
||||
except Exception as e:
|
||||
logger.warning(f"Failed to save raw debug image: {e}")
|
||||
|
||||
plate_points = self.detect(image)
|
||||
if len(plate_points) == 0:
|
||||
return [], [], []
|
||||
|
||||
@ -32,7 +32,7 @@ import {
|
||||
MobilePageTitle,
|
||||
} from "@/components/mobile/MobilePage";
|
||||
|
||||
const LPR_TABS = ["details", "snapshot", "video", "plate"] as const;
|
||||
const LPR_TABS = ["details", "snapshot", "video"] as const;
|
||||
export type LPRTab = (typeof LPR_TABS)[number];
|
||||
|
||||
type LPRDetailDialogProps = {
|
||||
@ -146,7 +146,6 @@ export default function LPRDetailDialog({
|
||||
{item == "details" && <FaRegListAlt className="size-4" />}
|
||||
{item == "snapshot" && <FaImage className="size-4" />}
|
||||
{item == "video" && <FaVideo className="size-4" />}
|
||||
{item == "plate" && <FaImage className="size-4" />}
|
||||
<div className="capitalize">{item}</div>
|
||||
</ToggleGroupItem>
|
||||
))}
|
||||
@ -163,7 +162,7 @@ export default function LPRDetailDialog({
|
||||
{page === "video" && (
|
||||
<VideoTab event={event} />
|
||||
)}
|
||||
{page === "plate" && (
|
||||
{(page === "details" || !event) && (
|
||||
<PlateTab lprImage={lprImage} />
|
||||
)}
|
||||
</Content>
|
||||
|
||||
@ -10,7 +10,7 @@ import {
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area";
|
||||
import { Toaster } from "@/components/ui/sonner";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
import { FrigateConfig } from "@/types/frigateConfig";
|
||||
@ -21,13 +21,17 @@ import { useFormattedTimestamp } from "@/hooks/use-date-utils";
|
||||
import { LuArrowDownUp, LuTrash2 } from "react-icons/lu";
|
||||
import axios from "axios";
|
||||
import { toast } from "sonner";
|
||||
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
type SortOption = "score_desc" | "score_asc" | "time_desc" | "time_asc";
|
||||
type ViewMode = "detected" | "raw";
|
||||
|
||||
export default function LPRDebug() {
|
||||
const { data: config } = useSWR<FrigateConfig>("config");
|
||||
const [sortBy, setSortBy] = useState<SortOption>("time_desc");
|
||||
const [selectedCameras, setSelectedCameras] = useState<string[] | undefined>();
|
||||
const [viewMode, setViewMode] = useState<ViewMode>("detected");
|
||||
|
||||
// title
|
||||
useEffect(() => {
|
||||
@ -105,6 +109,35 @@ export default function LPRDebug() {
|
||||
<div className="relative mb-2 flex h-11 w-full items-center justify-between">
|
||||
<ScrollArea className="w-full whitespace-nowrap">
|
||||
<div className="flex flex-row">
|
||||
<ToggleGroup
|
||||
className="*:rounded-md *:px-3 *:py-4"
|
||||
type="single"
|
||||
size="sm"
|
||||
value={viewMode}
|
||||
onValueChange={(value: ViewMode) => {
|
||||
if (value) {
|
||||
setViewMode(value);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ToggleGroupItem
|
||||
value="detected"
|
||||
className={`flex scroll-mx-10 items-center justify-between gap-2 ${viewMode == "detected" ? "" : "*:text-muted-foreground"}`}
|
||||
data-nav-item="detected"
|
||||
aria-label="Select detected"
|
||||
>
|
||||
<div>Detected</div>
|
||||
</ToggleGroupItem>
|
||||
<ToggleGroupItem
|
||||
value="raw"
|
||||
className={`flex scroll-mx-10 items-center justify-between gap-2 ${viewMode == "raw" ? "" : "*:text-muted-foreground"}`}
|
||||
data-nav-item="raw"
|
||||
aria-label="Select raw"
|
||||
>
|
||||
<div>Raw</div>
|
||||
</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
<ScrollBar orientation="horizontal" className="h-0" />
|
||||
</div>
|
||||
</ScrollArea>
|
||||
<div className="flex gap-2">
|
||||
@ -141,7 +174,13 @@ export default function LPRDebug() {
|
||||
</div>
|
||||
<div className="scrollbar-container flex flex-wrap gap-2 overflow-y-scroll">
|
||||
{lprAttempts.map((attempt: string) => (
|
||||
<LPRAttempt key={attempt} attempt={attempt} config={config} onRefresh={refreshLPR} />
|
||||
<LPRAttempt
|
||||
key={attempt}
|
||||
attempt={attempt}
|
||||
config={config}
|
||||
onRefresh={refreshLPR}
|
||||
viewMode={viewMode}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
@ -152,9 +191,10 @@ type LPRAttemptProps = {
|
||||
attempt: string;
|
||||
config: FrigateConfig;
|
||||
onRefresh: () => void;
|
||||
viewMode: ViewMode;
|
||||
};
|
||||
|
||||
function LPRAttempt({ attempt, config, onRefresh }: LPRAttemptProps) {
|
||||
function LPRAttempt({ attempt, config, onRefresh, viewMode }: LPRAttemptProps) {
|
||||
const [showDialog, setShowDialog] = useState(false);
|
||||
const data = useMemo(() => {
|
||||
const parts = attempt.split("_");
|
||||
@ -206,7 +246,7 @@ function LPRAttempt({ attempt, config, onRefresh }: LPRAttemptProps) {
|
||||
setOpen={setShowDialog}
|
||||
event={event}
|
||||
config={config}
|
||||
lprImage={attempt}
|
||||
lprImage={viewMode === "detected" ? attempt : `raw_${data.eventId}.jpg`}
|
||||
/>
|
||||
|
||||
<div className="relative flex flex-col rounded-lg">
|
||||
@ -217,7 +257,7 @@ function LPRAttempt({ attempt, config, onRefresh }: LPRAttemptProps) {
|
||||
<div className="aspect-[2/1] flex items-center justify-center bg-black">
|
||||
<img
|
||||
className="h-40 max-w-none"
|
||||
src={`${baseUrl}clips/lpr/${attempt}`}
|
||||
src={`${baseUrl}clips/lpr/${viewMode === "detected" ? attempt : `raw_${data.eventId}.jpg`}`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user