mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-18 17:14:26 +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")
|
logger.debug("Model runners not loaded")
|
||||||
return [], [], []
|
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)
|
plate_points = self.detect(image)
|
||||||
if len(plate_points) == 0:
|
if len(plate_points) == 0:
|
||||||
return [], [], []
|
return [], [], []
|
||||||
|
|||||||
@ -32,7 +32,7 @@ import {
|
|||||||
MobilePageTitle,
|
MobilePageTitle,
|
||||||
} from "@/components/mobile/MobilePage";
|
} 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];
|
export type LPRTab = (typeof LPR_TABS)[number];
|
||||||
|
|
||||||
type LPRDetailDialogProps = {
|
type LPRDetailDialogProps = {
|
||||||
@ -146,7 +146,6 @@ export default function LPRDetailDialog({
|
|||||||
{item == "details" && <FaRegListAlt className="size-4" />}
|
{item == "details" && <FaRegListAlt className="size-4" />}
|
||||||
{item == "snapshot" && <FaImage className="size-4" />}
|
{item == "snapshot" && <FaImage className="size-4" />}
|
||||||
{item == "video" && <FaVideo className="size-4" />}
|
{item == "video" && <FaVideo className="size-4" />}
|
||||||
{item == "plate" && <FaImage className="size-4" />}
|
|
||||||
<div className="capitalize">{item}</div>
|
<div className="capitalize">{item}</div>
|
||||||
</ToggleGroupItem>
|
</ToggleGroupItem>
|
||||||
))}
|
))}
|
||||||
@ -163,7 +162,7 @@ export default function LPRDetailDialog({
|
|||||||
{page === "video" && (
|
{page === "video" && (
|
||||||
<VideoTab event={event} />
|
<VideoTab event={event} />
|
||||||
)}
|
)}
|
||||||
{page === "plate" && (
|
{(page === "details" || !event) && (
|
||||||
<PlateTab lprImage={lprImage} />
|
<PlateTab lprImage={lprImage} />
|
||||||
)}
|
)}
|
||||||
</Content>
|
</Content>
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import {
|
|||||||
DropdownMenuLabel,
|
DropdownMenuLabel,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from "@/components/ui/dropdown-menu";
|
} 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 { Toaster } from "@/components/ui/sonner";
|
||||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||||
import { FrigateConfig } from "@/types/frigateConfig";
|
import { FrigateConfig } from "@/types/frigateConfig";
|
||||||
@ -21,13 +21,17 @@ import { useFormattedTimestamp } from "@/hooks/use-date-utils";
|
|||||||
import { LuArrowDownUp, LuTrash2 } from "react-icons/lu";
|
import { LuArrowDownUp, LuTrash2 } from "react-icons/lu";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { toast } from "sonner";
|
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 SortOption = "score_desc" | "score_asc" | "time_desc" | "time_asc";
|
||||||
|
type ViewMode = "detected" | "raw";
|
||||||
|
|
||||||
export default function LPRDebug() {
|
export default function LPRDebug() {
|
||||||
const { data: config } = useSWR<FrigateConfig>("config");
|
const { data: config } = useSWR<FrigateConfig>("config");
|
||||||
const [sortBy, setSortBy] = useState<SortOption>("time_desc");
|
const [sortBy, setSortBy] = useState<SortOption>("time_desc");
|
||||||
const [selectedCameras, setSelectedCameras] = useState<string[] | undefined>();
|
const [selectedCameras, setSelectedCameras] = useState<string[] | undefined>();
|
||||||
|
const [viewMode, setViewMode] = useState<ViewMode>("detected");
|
||||||
|
|
||||||
// title
|
// title
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -105,6 +109,35 @@ export default function LPRDebug() {
|
|||||||
<div className="relative mb-2 flex h-11 w-full items-center justify-between">
|
<div className="relative mb-2 flex h-11 w-full items-center justify-between">
|
||||||
<ScrollArea className="w-full whitespace-nowrap">
|
<ScrollArea className="w-full whitespace-nowrap">
|
||||||
<div className="flex flex-row">
|
<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>
|
</div>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
@ -141,7 +174,13 @@ export default function LPRDebug() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="scrollbar-container flex flex-wrap gap-2 overflow-y-scroll">
|
<div className="scrollbar-container flex flex-wrap gap-2 overflow-y-scroll">
|
||||||
{lprAttempts.map((attempt: string) => (
|
{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>
|
||||||
</div>
|
</div>
|
||||||
@ -152,9 +191,10 @@ type LPRAttemptProps = {
|
|||||||
attempt: string;
|
attempt: string;
|
||||||
config: FrigateConfig;
|
config: FrigateConfig;
|
||||||
onRefresh: () => void;
|
onRefresh: () => void;
|
||||||
|
viewMode: ViewMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
function LPRAttempt({ attempt, config, onRefresh }: LPRAttemptProps) {
|
function LPRAttempt({ attempt, config, onRefresh, viewMode }: LPRAttemptProps) {
|
||||||
const [showDialog, setShowDialog] = useState(false);
|
const [showDialog, setShowDialog] = useState(false);
|
||||||
const data = useMemo(() => {
|
const data = useMemo(() => {
|
||||||
const parts = attempt.split("_");
|
const parts = attempt.split("_");
|
||||||
@ -206,7 +246,7 @@ function LPRAttempt({ attempt, config, onRefresh }: LPRAttemptProps) {
|
|||||||
setOpen={setShowDialog}
|
setOpen={setShowDialog}
|
||||||
event={event}
|
event={event}
|
||||||
config={config}
|
config={config}
|
||||||
lprImage={attempt}
|
lprImage={viewMode === "detected" ? attempt : `raw_${data.eventId}.jpg`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="relative flex flex-col rounded-lg">
|
<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">
|
<div className="aspect-[2/1] flex items-center justify-center bg-black">
|
||||||
<img
|
<img
|
||||||
className="h-40 max-w-none"
|
className="h-40 max-w-none"
|
||||||
src={`${baseUrl}clips/lpr/${attempt}`}
|
src={`${baseUrl}clips/lpr/${viewMode === "detected" ? attempt : `raw_${data.eventId}.jpg`}`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user