Spaces:
Running
Running
Arsala Grey
commited on
Commit
·
3529c31
1
Parent(s):
7e2f64e
added loading and sorted detected objects
Browse files- index.html +26 -16
- index.js +35 -9
index.html
CHANGED
@@ -1,34 +1,44 @@
|
|
1 |
-
|
2 |
<!DOCTYPE html>
|
3 |
<html>
|
4 |
<head>
|
5 |
<meta charset="utf-8" />
|
6 |
<meta name="viewport" content="width=device-width" />
|
7 |
<title>Image Object Detection - HuggingFace.js Live Examples</title>
|
8 |
-
<link rel="stylesheet" href="/utils.css" />
|
9 |
<link rel="stylesheet" href="/pico.classless.min.css" />
|
|
|
10 |
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
|
11 |
</head>
|
12 |
<body>
|
13 |
<div id="generate-text-stream-app" class="container">
|
14 |
<h1>Detect Objects In Images</h1>
|
15 |
-
<label for="hf-token">Hugging Face Token</label>
|
16 |
-
<input id="hf-token" v-model="token" placeholder="HF-TOKEN" type="password" />
|
17 |
-
<label for="model-select">Select a model</label>
|
18 |
-
<select id="model-select" v-model="selectedModel" >
|
19 |
-
<option v-for="model in models" :value="model">
|
20 |
-
{{ model }}
|
21 |
-
</option>
|
22 |
-
</select>
|
23 |
-
<label for="current-image">Current Image</label>
|
24 |
-
<div class="image-container">
|
25 |
-
<img :src="imageUrl" id="current-image" />
|
26 |
-
</div>
|
27 |
<div class="grid grid-cols-2 gap-2">
|
28 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
<button class="btn-success" @click="run">DETECT OBJECTS</button>
|
30 |
</div>
|
31 |
-
<h2>
|
|
|
|
|
|
|
|
|
|
|
32 |
</div>
|
33 |
<script type="module" src="./index.js"></script>
|
34 |
</body>
|
|
|
|
|
1 |
<!DOCTYPE html>
|
2 |
<html>
|
3 |
<head>
|
4 |
<meta charset="utf-8" />
|
5 |
<meta name="viewport" content="width=device-width" />
|
6 |
<title>Image Object Detection - HuggingFace.js Live Examples</title>
|
|
|
7 |
<link rel="stylesheet" href="/pico.classless.min.css" />
|
8 |
+
<link rel="stylesheet" href="/main.css" />
|
9 |
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
|
10 |
</head>
|
11 |
<body>
|
12 |
<div id="generate-text-stream-app" class="container">
|
13 |
<h1>Detect Objects In Images</h1>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
<div class="grid grid-cols-2 gap-2">
|
15 |
+
<div>
|
16 |
+
<label for="hf-token">Hugging Face Token</label>
|
17 |
+
<input
|
18 |
+
id="hf-token"
|
19 |
+
v-model="token"
|
20 |
+
placeholder="HF-TOKEN"
|
21 |
+
type="password"
|
22 |
+
/>
|
23 |
+
</div>
|
24 |
+
<div>
|
25 |
+
<label for="model-select">Select a model</label>
|
26 |
+
<select id="model-select" v-model="selectedModel">
|
27 |
+
<option v-for="model in models" :value="model">{{ model }}</option>
|
28 |
+
</select>
|
29 |
+
</div>
|
30 |
+
</div>
|
31 |
+
<div class="grid grid-cols-3 gap-2">
|
32 |
+
<button class="btn-info" @click="shuffle">RANDOM IMAGE</button>
|
33 |
+
<button class="btn-gray" @click="upload">UPLOAD IMAGE</button>
|
34 |
<button class="btn-success" @click="run">DETECT OBJECTS</button>
|
35 |
</div>
|
36 |
+
<h2>{{statusMessage}}</h2>
|
37 |
+
<div class="image-container">
|
38 |
+
<div id="image-wrapper">
|
39 |
+
<img :src="imageUrl" id="current-image" />
|
40 |
+
</div>
|
41 |
+
</div>
|
42 |
</div>
|
43 |
<script type="module" src="./index.js"></script>
|
44 |
</body>
|
index.js
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
-
const { createApp, ref, onMounted } = Vue;
|
2 |
import { HfInference } from "https://cdn.skypack.dev/@huggingface/inference@latest";
|
3 |
|
4 |
const getRandomImageUrl = async () => {
|
5 |
const randomImageRequest = await fetch("https://source.unsplash.com/random/640x480")
|
6 |
return randomImageRequest.url
|
7 |
}
|
8 |
-
const
|
9 |
|
10 |
const getImageBuffer = async (imageUrl) => {
|
11 |
const imageRequest = await fetch(imageUrl)
|
@@ -22,6 +22,8 @@ const drawDetectedObjects = (img, detections) => {
|
|
22 |
container.style.height = `${img.height}px`;
|
23 |
img.parentNode.insertBefore(container, img);
|
24 |
|
|
|
|
|
25 |
detections.forEach(detection => {
|
26 |
const { xmin, ymin, xmax, ymax } = detection.box;
|
27 |
const label = detection.label;
|
@@ -39,18 +41,33 @@ const drawDetectedObjects = (img, detections) => {
|
|
39 |
tooltip.innerText = `${label}: ${confidence}`;
|
40 |
box.appendChild(tooltip);
|
41 |
|
42 |
-
|
43 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
};
|
45 |
const app = createApp({
|
46 |
setup() {
|
47 |
const token = ref(localStorage.getItem("token") || "");
|
48 |
-
const models = ref(
|
49 |
const selectedModel = ref("");
|
50 |
const imageUrl = ref("");
|
51 |
const detectedObjects = ref([]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
|
53 |
const run = async () => {
|
|
|
54 |
try {
|
55 |
const hf = new HfInference(token.value);
|
56 |
const imageData = await getImageBuffer(imageUrl.value);
|
@@ -58,18 +75,25 @@ const app = createApp({
|
|
58 |
data: imageData,
|
59 |
model: selectedModel.value,
|
60 |
});
|
61 |
-
console.log(result);
|
62 |
detectedObjects.value = result
|
63 |
drawDetectedObjects(document.getElementById('current-image'), result)
|
|
|
|
|
64 |
} catch (e) {
|
65 |
-
console.
|
|
|
66 |
}
|
67 |
};
|
68 |
|
69 |
-
const
|
70 |
-
imageUrl.value = await getRandomImageUrl()
|
71 |
document.getElementById('detected-objects-container').remove()
|
72 |
document.getElementsByClassName('bounding-box').forEach(box => box.remove())
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
};
|
74 |
|
75 |
onMounted(async () => {
|
@@ -91,7 +115,9 @@ const app = createApp({
|
|
91 |
shuffle,
|
92 |
models,
|
93 |
selectedModel,
|
94 |
-
imageUrl
|
|
|
|
|
95 |
};
|
96 |
},
|
97 |
});
|
|
|
1 |
+
const { createApp, ref, onMounted, computed } = Vue;
|
2 |
import { HfInference } from "https://cdn.skypack.dev/@huggingface/inference@latest";
|
3 |
|
4 |
const getRandomImageUrl = async () => {
|
5 |
const randomImageRequest = await fetch("https://source.unsplash.com/random/640x480")
|
6 |
return randomImageRequest.url
|
7 |
}
|
8 |
+
const ObjectDetectionModels = ["facebook/detr-resnet-50", "hustvl/yolos-tiny", "facebook/detr-resnet-101"]
|
9 |
|
10 |
const getImageBuffer = async (imageUrl) => {
|
11 |
const imageRequest = await fetch(imageUrl)
|
|
|
22 |
container.style.height = `${img.height}px`;
|
23 |
img.parentNode.insertBefore(container, img);
|
24 |
|
25 |
+
const detectedObjectBoxes = []
|
26 |
+
|
27 |
detections.forEach(detection => {
|
28 |
const { xmin, ymin, xmax, ymax } = detection.box;
|
29 |
const label = detection.label;
|
|
|
41 |
tooltip.innerText = `${label}: ${confidence}`;
|
42 |
box.appendChild(tooltip);
|
43 |
|
44 |
+
detectedObjectBoxes.push(box)
|
45 |
});
|
46 |
+
|
47 |
+
detectedObjectBoxes.sort((a, b) => {
|
48 |
+
const aSize = a.style.width * a.style.height
|
49 |
+
const bSize = b.style.width * b.style.height
|
50 |
+
return aSize - bSize
|
51 |
+
}).forEach(box => container.appendChild(box))
|
52 |
};
|
53 |
const app = createApp({
|
54 |
setup() {
|
55 |
const token = ref(localStorage.getItem("token") || "");
|
56 |
+
const models = ref(ObjectDetectionModels);
|
57 |
const selectedModel = ref("");
|
58 |
const imageUrl = ref("");
|
59 |
const detectedObjects = ref([]);
|
60 |
+
const loading = ref(false);
|
61 |
+
|
62 |
+
const statusMessage = computed(() => {
|
63 |
+
if (loading.value) return "Loading...";
|
64 |
+
if (detectedObjects.value.length === 0) return "No objects detected";
|
65 |
+
if (detectedObjects.value.length === 1) return "1 object detected";
|
66 |
+
return `${detectedObjects.value.length} objects detected`;
|
67 |
+
})
|
68 |
|
69 |
const run = async () => {
|
70 |
+
loading.value = true;
|
71 |
try {
|
72 |
const hf = new HfInference(token.value);
|
73 |
const imageData = await getImageBuffer(imageUrl.value);
|
|
|
75 |
data: imageData,
|
76 |
model: selectedModel.value,
|
77 |
});
|
|
|
78 |
detectedObjects.value = result
|
79 |
drawDetectedObjects(document.getElementById('current-image'), result)
|
80 |
+
console.log(detectedObjects.value)
|
81 |
+
loading.value = false;
|
82 |
} catch (e) {
|
83 |
+
console.error(e);
|
84 |
+
loading.value = false;
|
85 |
}
|
86 |
};
|
87 |
|
88 |
+
const reset = () => {
|
|
|
89 |
document.getElementById('detected-objects-container').remove()
|
90 |
document.getElementsByClassName('bounding-box').forEach(box => box.remove())
|
91 |
+
detectedObjects.value = []
|
92 |
+
}
|
93 |
+
|
94 |
+
const shuffle = async () => {
|
95 |
+
imageUrl.value = await getRandomImageUrl()
|
96 |
+
reset()
|
97 |
};
|
98 |
|
99 |
onMounted(async () => {
|
|
|
115 |
shuffle,
|
116 |
models,
|
117 |
selectedModel,
|
118 |
+
imageUrl,
|
119 |
+
loading,
|
120 |
+
statusMessage
|
121 |
};
|
122 |
},
|
123 |
});
|