Skip to content

Commit 0a3c5e7

Browse files
author
salim laimeche
committed
refactoring some code for re use purpose, gonna refactor with hooks all usage of models
1 parent 5e40646 commit 0a3c5e7

File tree

9 files changed

+248
-188
lines changed

9 files changed

+248
-188
lines changed

components/History.tsx

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,17 @@ export default function History({ user }: IProps) {
3636
from: new Date(actualYear, actualMonth, 1),
3737
to: addDays(new Date(actualYear, actualMonth, 1), 6),
3838
})
39-
const [model, setModel] = useState<ObjectDetection | null>(null)
39+
const [coco, setCoco] = useState<ObjectDetection | null>(null)
40+
const [yolo, setYolo] = useState({
41+
net: null,
42+
inputShape: [1, 0, 0, 3],
43+
}) // init model & input shape of YOLO DETECTION
44+
const [yoloSeg, setYoloSeg] = useState({
45+
net: null,
46+
inputShape: [1, 0, 0, 3],
47+
}) // init model & input shape of YOLO SEGMENTATION
4048
const [pictures, setPictures] = useState<string[]>([])
4149
const [isDeleting, setIsDeleting] = useState<boolean>(false)
42-
const [isDownloading, setIsDownloading] = useState<boolean>(false)
4350
const [modelLoading, setModelLoading] = useState<boolean>(false)
4451
const canvasRefs = useRef<HTMLCanvasElement[]>([])
4552

@@ -48,7 +55,7 @@ export default function History({ user }: IProps) {
4855
setModelLoading(true)
4956
try {
5057
const loadedModel = await load()
51-
setModel(loadedModel)
58+
setCoco(loadedModel)
5259
toast({
5360
title: "Modèle de reconnaissance chargé",
5461
description:
@@ -84,7 +91,7 @@ export default function History({ user }: IProps) {
8491
}, [date])
8592

8693
useEffect(() => {
87-
if (model && pictures.length > 0) {
94+
if (coco && pictures.length > 0) {
8895
pictures.forEach((picture, index) => {
8996
const img = new window.Image()
9097
img.crossOrigin = "anonymous"
@@ -95,7 +102,7 @@ export default function History({ user }: IProps) {
95102
if (context) {
96103
context.clearRect(0, 0, canvas.width, canvas.height)
97104
context.drawImage(img, 0, 0, canvas.width, canvas.height)
98-
model.detect(canvas).then(predictions => {
105+
coco.detect(canvas).then(predictions => {
99106
predictions.forEach(prediction => {
100107
const [x, y, width, height] = prediction.bbox
101108
const text = `${prediction.class} (${Math.round(
@@ -118,7 +125,7 @@ export default function History({ user }: IProps) {
118125
}
119126
})
120127
}
121-
}, [model, pictures])
128+
}, [coco, pictures])
122129

123130
async function handleDeleteAllSelection() {
124131
const confirmation = window.confirm(
@@ -159,7 +166,6 @@ export default function History({ user }: IProps) {
159166
<strong className="ml-4">
160167
{modelLoading && "Chargement du modèle de reconnaissance"}
161168
{isDeleting && "Suppression des detections en cours"}
162-
{isDownloading && "Téléchargement des detections en cours"}
163169
</strong>
164170
</Badge>
165171
</div>

components/VideoInference.tsx

Lines changed: 22 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,18 @@
33
import "@tensorflow/tfjs-backend-webgl"
44
import * as tf from "@tensorflow/tfjs"
55
import { ObjectDetection, load } from "@tensorflow-models/coco-ssd"
6-
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"
7-
import { Button } from "@/components/ui/button"
8-
import { Input } from "@/components/ui/input"
9-
import {
10-
DropdownMenu,
11-
DropdownMenuTrigger,
12-
DropdownMenuContent,
13-
DropdownMenuItem,
14-
} from "@/components/ui/dropdown-menu"
156
import { UserView } from "@/lib/identity/definition"
16-
import { useEffect, useState, useRef } from "react"
7+
import { useEffect, useState } from "react"
178
import { ModelComputerVision, ModelList, modelList } from "@/models/model-list"
189
import { cocossdVideoInference } from "@/lib/cocossd/detect"
1910
import { detectVideo } from "@/lib/yolov8n/detect"
2011
import ModelLoader from "./model-loader"
2112
import { segmentVideo } from "@/lib/yolov8n-seg/detect"
13+
import ModelSelection from "./model-selection"
14+
import { useModelStore } from "@/lib/store/model-store"
15+
import VideoReader from "./video-reader"
16+
import VideoSelect from "./video-select"
17+
import { useVideoStore } from "@/hooks/use-video-store"
2218

2319
interface IProps {
2420
user: UserView
@@ -34,12 +30,10 @@ export default function VideoInference({ user }: IProps) {
3430
net: null,
3531
inputShape: [1, 0, 0, 3],
3632
}) // init model & input shape of YOLO SEGMENTATION
37-
const [modelName, setModelName] = useState<string>("")
3833
const [loadModel, setLoadModel] = useState<boolean>(false)
39-
const [videoSrc, setVideoSrc] = useState<string | null>(null)
40-
const videoRef = useRef<HTMLVideoElement | null>(null)
41-
const canvasRef = useRef<HTMLCanvasElement | null>(null)
4234
const [percentLoaded, setPercentLoaded] = useState<number>(0)
35+
const { modelName } = useModelStore()
36+
const { canvasRef, videoRef, videoSrc, setVideoSrc } = useVideoStore()
4337

4438
useEffect(() => {
4539
tf.setBackend("webgl")
@@ -152,80 +146,21 @@ export default function VideoInference({ user }: IProps) {
152146
return (
153147
<main className="grid flex-1 items-start gap-4 p-4 sm:px-6 sm:py-0 md:gap-8 lg:grid-cols-3 xl:grid-cols-3 m-10">
154148
<div className="lg:col-span-2">
155-
<Card className="overflow-hidden bg-background">
156-
<CardHeader className="flex flex-row items-start bg-muted/50 ">
157-
<div className="grid gap-0.5">
158-
<CardTitle className="text-lg">Lecteur Vidéo</CardTitle>
159-
</div>
160-
</CardHeader>
161-
<CardContent className="p-6">
162-
<div className="relative w-full max-w-2xl overflow-hidden rounded-lg aspect-video">
163-
<video ref={videoRef} className="w-full" autoPlay controls>
164-
{videoSrc && <source src={videoSrc} type="video/mp4" />}
165-
</video>
166-
<canvas
167-
ref={canvasRef}
168-
className="absolute top-0 left-0 w-full h-full pointer-events-none"
169-
/>
170-
</div>
171-
</CardContent>
172-
</Card>
149+
<VideoReader
150+
videoRef={videoRef}
151+
canvasRef={canvasRef}
152+
videoSrc={videoSrc}
153+
/>
173154
</div>
174155
<div className="grid gap-4">
175-
<Card className="bg-background">
176-
<CardHeader className="flex flex-row items-start bg-muted/50">
177-
<div className="grid gap-0.5">
178-
<CardTitle className="text-lg">Vidéo Sélection</CardTitle>
179-
</div>
180-
</CardHeader>
181-
<CardContent className="p-6">
182-
<div className="grid gap-4">
183-
<Input
184-
type="file"
185-
id="inputFile"
186-
accept="video/*"
187-
placeholder="Choose a video file"
188-
onChange={handleFileChange}
189-
className="cursor-pointer"
190-
/>
191-
<Button
192-
variant="outline"
193-
onClick={handleCreateVideoWithBoundingBox}
194-
disabled={!modelName || !videoSrc}
195-
className="w-full">
196-
Traiter la vidéo
197-
</Button>
198-
<Button
199-
variant="destructive"
200-
className="hover:bg-red-500"
201-
onClick={() => {
202-
setVideoSrc(null)
203-
const inputFile = document.getElementById("inputFile")
204-
if (inputFile) {
205-
inputFile.setAttribute("value", "")
206-
}
207-
if (videoRef.current) {
208-
videoRef.current.load()
209-
}
210-
211-
if (canvasRef.current) {
212-
const context = canvasRef.current.getContext("2d")
213-
if (context) {
214-
context.clearRect(
215-
0,
216-
0,
217-
canvasRef.current.width,
218-
canvasRef.current.height
219-
)
220-
}
221-
}
222-
}}
223-
disabled={!videoSrc}>
224-
Vider le lecteur vidéo
225-
</Button>
226-
</div>
227-
</CardContent>
228-
</Card>
156+
<VideoSelect
157+
handleFileChange={handleFileChange}
158+
handleCreateVideoWithBoundingBox={handleCreateVideoWithBoundingBox}
159+
videoRef={videoRef}
160+
canvasRef={canvasRef}
161+
videoSrc={videoSrc}
162+
setVideoSrc={setVideoSrc}
163+
/>
229164
{loadModel ? (
230165
<ModelLoader
231166
percent={percentLoaded}
@@ -234,95 +169,9 @@ export default function VideoInference({ user }: IProps) {
234169
}
235170
/>
236171
) : (
237-
<Card>
238-
<CardHeader className="flex flex-row items-start bg-muted/50">
239-
<div className="grid gap-0.5">
240-
<CardTitle className="text-lg">Modèle Sélection</CardTitle>
241-
</div>
242-
</CardHeader>
243-
<CardContent className="p-6">
244-
<div className="grid gap-4">
245-
<DropdownMenu>
246-
<DropdownMenuTrigger asChild>
247-
<Button
248-
variant="outline"
249-
className="w-full justify-between">
250-
<span>
251-
{modelName ? modelName : "Choisissez un modèle"}
252-
</span>
253-
<ChevronDownIcon className="h-4 w-4" />
254-
</Button>
255-
</DropdownMenuTrigger>
256-
<DropdownMenuContent>
257-
{Object.keys(ModelComputerVision).map((key, index) => (
258-
<DropdownMenuItem
259-
key={index}
260-
onClick={() => setModelName(ModelComputerVision[key])}>
261-
{ModelComputerVision[key]}
262-
</DropdownMenuItem>
263-
))}
264-
</DropdownMenuContent>
265-
</DropdownMenu>
266-
</div>
267-
</CardContent>
268-
</Card>
172+
<ModelSelection />
269173
)}
270174
</div>
271175
</main>
272176
)
273177
}
274-
275-
function ChevronDownIcon(props) {
276-
return (
277-
<svg
278-
{...props}
279-
xmlns="http://www.w3.org/2000/svg"
280-
width="24"
281-
height="24"
282-
viewBox="0 0 24 24"
283-
fill="none"
284-
stroke="currentColor"
285-
strokeWidth="2"
286-
strokeLinecap="round"
287-
strokeLinejoin="round">
288-
<path d="m6 9 6 6 6-6" />
289-
</svg>
290-
)
291-
}
292-
293-
function PlayIcon(props) {
294-
return (
295-
<svg
296-
{...props}
297-
xmlns="http://www.w3.org/2000/svg"
298-
width="24"
299-
height="24"
300-
viewBox="0 0 24 24"
301-
fill="none"
302-
stroke="currentColor"
303-
strokeWidth="2"
304-
strokeLinecap="round"
305-
strokeLinejoin="round">
306-
<polygon points="6 3 20 12 6 21 6 3" />
307-
</svg>
308-
)
309-
}
310-
311-
function XIcon(props) {
312-
return (
313-
<svg
314-
{...props}
315-
xmlns="http://www.w3.org/2000/svg"
316-
width="24"
317-
height="24"
318-
viewBox="0 0 24 24"
319-
fill="none"
320-
stroke="currentColor"
321-
strokeWidth="2"
322-
strokeLinecap="round"
323-
strokeLinejoin="round">
324-
<path d="M18 6 6 18" />
325-
<path d="m6 6 12 12" />
326-
</svg>
327-
)
328-
}

components/model-selection.tsx

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
"use client"
2+
3+
import { ModelComputerVision } from "@/models/model-list"
4+
import { Button } from "./ui/button"
5+
import { Card, CardContent, CardHeader, CardTitle } from "./ui/card"
6+
import {
7+
DropdownMenu,
8+
DropdownMenuContent,
9+
DropdownMenuItem,
10+
DropdownMenuTrigger,
11+
} from "./ui/dropdown-menu"
12+
import { useModelStore } from "@/lib/store/model-store"
13+
14+
export default function ModelSelection() {
15+
const { modelName, setModel } = useModelStore()
16+
17+
return (
18+
<Card>
19+
<CardHeader className="flex flex-row items-start bg-muted/50">
20+
<div className="grid gap-0.5">
21+
<CardTitle className="text-lg">Modèle Sélection</CardTitle>
22+
</div>
23+
</CardHeader>
24+
<CardContent className="p-6">
25+
<div className="grid gap-4">
26+
<DropdownMenu>
27+
<DropdownMenuTrigger asChild>
28+
<Button variant="outline" className="w-full justify-between">
29+
<span>{modelName ? modelName : "Choisissez un modèle"}</span>
30+
<ChevronDownIcon className="h-4 w-4" />
31+
</Button>
32+
</DropdownMenuTrigger>
33+
<DropdownMenuContent>
34+
{Object.keys(ModelComputerVision).map((key, index) => (
35+
<DropdownMenuItem
36+
key={index}
37+
onClick={() => setModel(ModelComputerVision[key])}>
38+
{ModelComputerVision[key]}
39+
</DropdownMenuItem>
40+
))}
41+
</DropdownMenuContent>
42+
</DropdownMenu>
43+
</div>
44+
</CardContent>
45+
</Card>
46+
)
47+
}
48+
49+
function ChevronDownIcon(props) {
50+
return (
51+
<svg
52+
{...props}
53+
xmlns="http://www.w3.org/2000/svg"
54+
width="24"
55+
height="24"
56+
viewBox="0 0 24 24"
57+
fill="none"
58+
stroke="currentColor"
59+
strokeWidth="2"
60+
strokeLinecap="round"
61+
strokeLinejoin="round">
62+
<path d="m6 9 6 6 6-6" />
63+
</svg>
64+
)
65+
}

components/video-reader.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"use client"
2+
3+
import { Card, CardContent, CardHeader, CardTitle } from "./ui/card"
4+
5+
interface IProps {
6+
videoRef: React.RefObject<HTMLVideoElement>
7+
canvasRef: React.RefObject<HTMLCanvasElement>
8+
videoSrc: string | null
9+
}
10+
11+
export default function VideoReader({ videoRef, canvasRef, videoSrc }: IProps) {
12+
return (
13+
<Card className="overflow-hidden bg-background">
14+
<CardHeader className="flex flex-row items-start bg-muted/50 ">
15+
<div className="grid gap-0.5">
16+
<CardTitle className="text-lg">Lecteur Vidéo</CardTitle>
17+
</div>
18+
</CardHeader>
19+
<CardContent className="p-6">
20+
<div className="relative w-full max-w-2xl overflow-hidden rounded-lg aspect-video">
21+
<video ref={videoRef} className="w-full" autoPlay controls>
22+
{videoSrc && <source src={videoSrc} type="video/mp4" />}
23+
</video>
24+
<canvas
25+
ref={canvasRef}
26+
className="absolute top-0 left-0 w-full h-full pointer-events-none"
27+
/>
28+
</div>
29+
</CardContent>
30+
</Card>
31+
)
32+
}

0 commit comments

Comments
 (0)