pleabargain commited on
Commit
1fed0c1
·
verified ·
1 Parent(s): a88e348

Update index.js

Browse files
Files changed (1) hide show
  1. index.js +160 -74
index.js CHANGED
@@ -1,79 +1,165 @@
1
- import { pipeline, env } from 'https://cdn.jsdelivr.net/npm/@xenova/[email protected]';
2
-
3
- // Since we will download the model from the Hugging Face Hub, we can skip the local model check
4
- env.allowLocalModels = false;
5
-
6
- // Reference the elements that we will need
7
- const status = document.getElementById('status');
8
- const fileUpload = document.getElementById('upload');
9
- const imageContainer = document.getElementById('container');
10
- const example = document.getElementById('example');
11
-
12
- const EXAMPLE_URL = 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/city-streets.jpg';
13
-
14
- // Create a new object detection pipeline
15
- status.textContent = 'Loading model...';
16
- const detector = await pipeline('object-detection', 'Xenova/detr-resnet-50');
17
- status.textContent = 'Ready';
18
-
19
- example.addEventListener('click', (e) => {
20
- e.preventDefault();
21
- detect(EXAMPLE_URL);
22
- });
23
-
24
- fileUpload.addEventListener('change', function (e) {
25
- const file = e.target.files[0];
26
- if (!file) {
27
- return;
28
- }
 
 
 
 
29
 
30
  const reader = new FileReader();
31
-
32
- // Set up a callback when the file is loaded
33
- reader.onload = e2 => detect(e2.target.result);
34
-
35
  reader.readAsDataURL(file);
36
- });
37
-
38
-
39
- // Detect objects in the image
40
- async function detect(img) {
41
- imageContainer.innerHTML = '';
42
- imageContainer.style.backgroundImage = `url(${img})`;
43
-
44
- status.textContent = 'Analysing...';
45
- const output = await detector(img, {
 
 
 
 
46
  threshold: 0.5,
47
  percentage: true,
48
- });
49
- status.textContent = '';
50
- output.forEach(renderBox);
51
- }
52
-
53
- // Render a bounding box and label on the image
54
- function renderBox({ box, label }) {
55
- const { xmax, xmin, ymax, ymin } = box;
56
-
57
- // Generate a random color for the box
58
- const color = '#' + Math.floor(Math.random() * 0xFFFFFF).toString(16).padStart(6, 0);
59
-
60
- // Draw the box
61
- const boxElement = document.createElement('div');
62
- boxElement.className = 'bounding-box';
63
- Object.assign(boxElement.style, {
64
- borderColor: color,
65
- left: 100 * xmin + '%',
66
- top: 100 * ymin + '%',
67
- width: 100 * (xmax - xmin) + '%',
68
- height: 100 * (ymax - ymin) + '%',
69
- })
70
-
71
- // Draw label
72
- const labelElement = document.createElement('span');
73
- labelElement.textContent = label;
74
- labelElement.className = 'bounding-box-label';
75
- labelElement.style.backgroundColor = color;
76
-
77
- boxElement.appendChild(labelElement);
78
- imageContainer.appendChild(boxElement);
79
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState, useEffect } from 'react';
2
+ import { Card } from '@/components/ui/card';
3
+ import { Button } from '@/components/ui/button';
4
+ import { Upload, Image as ImageIcon } from 'lucide-react';
5
+
6
+ const ObjectDetector = () => {
7
+ const [status, setStatus] = useState('Loading model...');
8
+ const [detections, setDetections] = useState([]);
9
+ const [currentImage, setCurrentImage] = useState(null);
10
+ const [detector, setDetector] = useState(null);
11
+
12
+ // Initialize the model
13
+ useEffect(() => {
14
+ const initModel = async () => {
15
+ try {
16
+ const { pipeline, env } = await import('https://cdn.jsdelivr.net/npm/@xenova/[email protected]');
17
+ env.allowLocalModels = false;
18
+ const model = await pipeline('object-detection', 'Xenova/detr-resnet-50');
19
+ setDetector(model);
20
+ setStatus('Ready');
21
+ } catch (error) {
22
+ console.error('Error loading model:', error);
23
+ setStatus('Error loading model');
24
+ }
25
+ };
26
+
27
+ initModel();
28
+ }, []);
29
+
30
+ const handleFileUpload = (event) => {
31
+ const file = event.target.files[0];
32
+ if (!file) return;
33
 
34
  const reader = new FileReader();
35
+ reader.onload = (e) => {
36
+ setCurrentImage(e.target.result);
37
+ detectObjects(e.target.result);
38
+ };
39
  reader.readAsDataURL(file);
40
+ };
41
+
42
+ const handleExampleImage = () => {
43
+ const EXAMPLE_URL = 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/city-streets.jpg';
44
+ setCurrentImage(EXAMPLE_URL);
45
+ detectObjects(EXAMPLE_URL);
46
+ };
47
+
48
+ const detectObjects = async (img) => {
49
+ if (!detector) return;
50
+
51
+ setStatus('Analyzing...');
52
+ try {
53
+ const output = await detector(img, {
54
  threshold: 0.5,
55
  percentage: true,
56
+ });
57
+ setDetections(output.map((det, index) => ({
58
+ ...det,
59
+ id: index + 1
60
+ })));
61
+ setStatus('');
62
+ } catch (error) {
63
+ console.error('Error detecting objects:', error);
64
+ setStatus('Error analyzing image');
65
+ }
66
+ };
67
+
68
+ return (
69
+ <Card className="p-6 max-w-4xl mx-auto">
70
+ <div className="space-y-6">
71
+ <div className="flex gap-4 items-center justify-center">
72
+ <Button
73
+ onClick={() => document.getElementById('fileUpload').click()}
74
+ className="flex items-center gap-2"
75
+ >
76
+ <Upload className="w-4 h-4" />
77
+ Upload Image
78
+ </Button>
79
+ <Button
80
+ onClick={handleExampleImage}
81
+ className="flex items-center gap-2"
82
+ >
83
+ <ImageIcon className="w-4 h-4" />
84
+ Try Example
85
+ </Button>
86
+ <input
87
+ id="fileUpload"
88
+ type="file"
89
+ accept="image/*"
90
+ className="hidden"
91
+ onChange={handleFileUpload}
92
+ />
93
+ </div>
94
+
95
+ {status && (
96
+ <div className="text-center text-sm text-gray-600">
97
+ {status}
98
+ </div>
99
+ )}
100
+
101
+ {currentImage && (
102
+ <div className="relative w-full h-96 bg-gray-100 rounded overflow-hidden">
103
+ <img
104
+ src={currentImage}
105
+ alt="Uploaded"
106
+ className="w-full h-full object-contain"
107
+ />
108
+ {detections.map((detection) => (
109
+ <div
110
+ key={detection.id}
111
+ className="absolute border-2 border-blue-500"
112
+ style={{
113
+ left: `${detection.box.xmin}%`,
114
+ top: `${detection.box.ymin}%`,
115
+ width: `${detection.box.xmax - detection.box.xmin}%`,
116
+ height: `${detection.box.ymax - detection.box.ymin}%`,
117
+ }}
118
+ >
119
+ <span className="absolute top-0 left-0 transform -translate-y-full bg-blue-500 text-white px-1 py-0.5 text-xs rounded">
120
+ {detection.label} ({(detection.score * 100).toFixed(1)}%)
121
+ </span>
122
+ </div>
123
+ ))}
124
+ </div>
125
+ )}
126
+
127
+ {detections.length > 0 && (
128
+ <div className="overflow-x-auto">
129
+ <table className="w-full">
130
+ <thead>
131
+ <tr className="border-b">
132
+ <th className="p-2 text-left font-semibold">Object</th>
133
+ <th className="p-2 text-left font-semibold">Confidence</th>
134
+ <th className="p-2 text-left font-semibold">Location</th>
135
+ </tr>
136
+ </thead>
137
+ <tbody>
138
+ {detections.map((detection) => (
139
+ <tr key={detection.id} className="border-b">
140
+ <td className="p-2">
141
+ <span className="inline-block px-2 py-1 bg-blue-100 text-blue-800 rounded">
142
+ {detection.label}
143
+ </span>
144
+ </td>
145
+ <td className="p-2">
146
+ {(detection.score * 100).toFixed(1)}%
147
+ </td>
148
+ <td className="p-2">
149
+ <div className="text-sm text-gray-600">
150
+ <div>x: {detection.box.xmin.toFixed(1)}% - {detection.box.xmax.toFixed(1)}%</div>
151
+ <div>y: {detection.box.ymin.toFixed(1)}% - {detection.box.ymax.toFixed(1)}%</div>
152
+ </div>
153
+ </td>
154
+ </tr>
155
+ ))}
156
+ </tbody>
157
+ </table>
158
+ </div>
159
+ )}
160
+ </div>
161
+ </Card>
162
+ );
163
+ };
164
+
165
+ export default ObjectDetector;