Spaces:
Sleeping
Sleeping
Add cp11 wheel for faster colab launch
#9
by
imgprcsng
- opened
- app.py +8 -21
- notebooks/demo.ipynb +14 -55
- requirements.txt +1 -2
app.py
CHANGED
|
@@ -176,27 +176,11 @@ def get_ind_to_filter(text, word_ids, keywords):
|
|
| 176 |
|
| 177 |
return inds_to_filter
|
| 178 |
|
| 179 |
-
def get_xy_from_boxes(image, boxes):
|
| 180 |
-
"""
|
| 181 |
-
Get box centers and return in image coordinates
|
| 182 |
-
"""
|
| 183 |
-
(w, h) = image.size
|
| 184 |
-
x = w * boxes[:, 0]
|
| 185 |
-
y = h * boxes[:, 1]
|
| 186 |
-
|
| 187 |
-
return x, y
|
| 188 |
-
|
| 189 |
def generate_heatmap(image, boxes):
|
| 190 |
# Plot results.
|
| 191 |
(w, h) = image.size
|
| 192 |
det_map = np.zeros((h, w))
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
# Box centers are floating point, convert to int and clip them at edge of box
|
| 196 |
-
x = np.clip(np.around(x).astype(int), 0, w - 1)
|
| 197 |
-
y = np.clip(np.around(y).astype(int), 0, h - 1)
|
| 198 |
-
|
| 199 |
-
det_map[y, x] = 1
|
| 200 |
det_map = ndimage.gaussian_filter(
|
| 201 |
det_map, sigma=(w // 200, w // 200), order=0
|
| 202 |
)
|
|
@@ -245,9 +229,13 @@ def preprocess(transform, image, input_prompts = None):
|
|
| 245 |
return input_image, input_image_exemplar, exemplar
|
| 246 |
|
| 247 |
def get_boxes_from_prediction(model_output, text, keywords = ""):
|
| 248 |
-
|
|
|
|
| 249 |
boxes = model_output["pred_boxes"][0]
|
| 250 |
-
|
|
|
|
|
|
|
|
|
|
| 251 |
boxes = boxes[box_mask, :].cpu().numpy()
|
| 252 |
logits = logits[box_mask, :].cpu().numpy()
|
| 253 |
return boxes, logits
|
|
@@ -426,5 +414,4 @@ if __name__ == '__main__':
|
|
| 426 |
clear_btn_main.add([input_image_main, input_text_main, exemplar_image_main, detected_instances_main, pred_count_main])
|
| 427 |
|
| 428 |
|
| 429 |
-
demo.queue().launch(allowed_paths=['back-icon.jpg', 'paste-icon.jpg', 'upload-icon.jpg', 'button-legend.jpg'])
|
| 430 |
-
#demo.queue().launch(share=True)
|
|
|
|
| 176 |
|
| 177 |
return inds_to_filter
|
| 178 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
def generate_heatmap(image, boxes):
|
| 180 |
# Plot results.
|
| 181 |
(w, h) = image.size
|
| 182 |
det_map = np.zeros((h, w))
|
| 183 |
+
det_map[(h * boxes[:, 1]).astype(int), (w * boxes[:, 0]).astype(int)] = 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 184 |
det_map = ndimage.gaussian_filter(
|
| 185 |
det_map, sigma=(w // 200, w // 200), order=0
|
| 186 |
)
|
|
|
|
| 229 |
return input_image, input_image_exemplar, exemplar
|
| 230 |
|
| 231 |
def get_boxes_from_prediction(model_output, text, keywords = ""):
|
| 232 |
+
ind_to_filter = get_ind_to_filter(text, model_output["token"][0].word_ids, keywords)
|
| 233 |
+
logits = model_output["pred_logits"].sigmoid()[0][:, ind_to_filter]
|
| 234 |
boxes = model_output["pred_boxes"][0]
|
| 235 |
+
if len(keywords.strip()) > 0:
|
| 236 |
+
box_mask = (logits > CONF_THRESH).sum(dim=-1) == len(ind_to_filter)
|
| 237 |
+
else:
|
| 238 |
+
box_mask = logits.max(dim=-1).values > CONF_THRESH
|
| 239 |
boxes = boxes[box_mask, :].cpu().numpy()
|
| 240 |
logits = logits[box_mask, :].cpu().numpy()
|
| 241 |
return boxes, logits
|
|
|
|
| 414 |
clear_btn_main.add([input_image_main, input_text_main, exemplar_image_main, detected_instances_main, pred_count_main])
|
| 415 |
|
| 416 |
|
| 417 |
+
demo.queue().launch(allowed_paths=['back-icon.jpg', 'paste-icon.jpg', 'upload-icon.jpg', 'button-legend.jpg'])
|
|
|
notebooks/demo.ipynb
CHANGED
|
@@ -6,7 +6,7 @@
|
|
| 6 |
"id": "yxig5CdZuHb9"
|
| 7 |
},
|
| 8 |
"source": [
|
| 9 |
-
"# CountGD -
|
| 10 |
"\n"
|
| 11 |
]
|
| 12 |
},
|
|
@@ -89,13 +89,7 @@
|
|
| 89 |
"source": [
|
| 90 |
"### Install Dependencies\n",
|
| 91 |
"\n",
|
| 92 |
-
"The environment will be setup with the code, models and required dependencies
|
| 93 |
-
"\n",
|
| 94 |
-
"*Note for Colab users*\n",
|
| 95 |
-
"\n",
|
| 96 |
-
"To reduce the waiting time, you can use the pre-built wheel file available [here](https://drive.google.com/file/d/1Vl_6DAWfnVU7HFX5y_5TqqbkyTcjONbm/view?usp=sharing) - Visit the link and add it as a shortcut to your \"My Drive\" folder or edit the path accordingly below. (Line 28)\n",
|
| 97 |
-
"\n",
|
| 98 |
-
"Alternatively, if you are unable to use google drive, you can download the file to your machine & upload it to the colab runtime when you connect to it and update the path below to install it from there. (Line 28)"
|
| 99 |
]
|
| 100 |
},
|
| 101 |
{
|
|
@@ -120,10 +114,8 @@
|
|
| 120 |
" git clone \"https://huggingface.co/spaces/nikigoli/countgd\" /content/countgd\n",
|
| 121 |
" fi\n",
|
| 122 |
" cd /content/countgd\n",
|
| 123 |
-
"\n",
|
| 124 |
-
"
|
| 125 |
-
" # git fetch origin refs/pr/10:refs/remotes/origin/pr/10\n",
|
| 126 |
-
" # git checkout pr/10 && git pull\n",
|
| 127 |
"else\n",
|
| 128 |
" # TODO check if cwd is the correct git repo\n",
|
| 129 |
" # If users use vscode, then we set the default start directory to root of the repo\n",
|
|
@@ -136,20 +128,11 @@
|
|
| 136 |
"pip install --upgrade pip setuptools wheel\n",
|
| 137 |
"pip install -r requirements.txt\n",
|
| 138 |
"\n",
|
|
|
|
|
|
|
| 139 |
"cd models/GroundingDINO/ops\n",
|
| 140 |
-
"
|
| 141 |
-
"
|
| 142 |
-
" if ! pip install \"/content/drive/MyDrive/MultiScaleDeformableAttention-1.0-cp311-cp311-linux_x86_64.whl\"\n",
|
| 143 |
-
" then\n",
|
| 144 |
-
" echo \"failed to install wheel, trying to build from source\";\n",
|
| 145 |
-
" python3 setup.py build\n",
|
| 146 |
-
" pip install .\n",
|
| 147 |
-
" fi\n",
|
| 148 |
-
"else\n",
|
| 149 |
-
" # We try to build the module as we dont know what environment we are running on\n",
|
| 150 |
-
" python3 setup.py build\n",
|
| 151 |
-
" pip install .\n",
|
| 152 |
-
"fi\n",
|
| 153 |
"python3 test.py"
|
| 154 |
]
|
| 155 |
},
|
|
@@ -206,7 +189,6 @@
|
|
| 206 |
" get_device,\n",
|
| 207 |
" get_args_parser,\n",
|
| 208 |
" generate_heatmap,\n",
|
| 209 |
-
" get_xy_from_boxes,\n",
|
| 210 |
" predict,\n",
|
| 211 |
")\n",
|
| 212 |
"args = get_args_parser().parse_args([])\n",
|
|
@@ -215,7 +197,7 @@
|
|
| 215 |
"model = model.to(device)\n",
|
| 216 |
"\n",
|
| 217 |
"run = lambda image, text: predict(model, transform, image, text, None, device)\n",
|
| 218 |
-
"get_output = lambda image, boxes: (len(boxes),
|
| 219 |
]
|
| 220 |
},
|
| 221 |
{
|
|
@@ -289,7 +271,7 @@
|
|
| 289 |
},
|
| 290 |
{
|
| 291 |
"cell_type": "code",
|
| 292 |
-
"execution_count":
|
| 293 |
"metadata": {
|
| 294 |
"id": "rFXRk-_uuHb_"
|
| 295 |
},
|
|
@@ -297,17 +279,6 @@
|
|
| 297 |
"source": [
|
| 298 |
"from tqdm import tqdm\n",
|
| 299 |
"import os\n",
|
| 300 |
-
"import json\n",
|
| 301 |
-
"def convert_xy_to_json(xy: tuple):\n",
|
| 302 |
-
" x, y = xy\n",
|
| 303 |
-
" pts = []\n",
|
| 304 |
-
" for _x, _y in zip(x.tolist(), y.tolist()):\n",
|
| 305 |
-
" _x, _y = round(_x, 3), round(_y, 3)\n",
|
| 306 |
-
" pts.append([_x, _y])\n",
|
| 307 |
-
"\n",
|
| 308 |
-
" # List of [x, y] points\n",
|
| 309 |
-
" return pts\n",
|
| 310 |
-
"\n",
|
| 311 |
"def process_zipfile(input_zipfile: Path, text: str):\n",
|
| 312 |
" if not input_zipfile.exists() or not input_zipfile.is_file() or not os.access(input_zipfile, os.R_OK):\n",
|
| 313 |
" logger.error(f'Cannot open / read zipfile: {input_zipfile}. Please check if it exists')\n",
|
|
@@ -319,24 +290,14 @@
|
|
| 319 |
"\n",
|
| 320 |
" output_zipfile = input_zipfile.parent / f'{input_zipfile.stem}_countgd.zip'\n",
|
| 321 |
" output_csvfile = input_zipfile.parent / f'{input_zipfile.stem}.csv'\n",
|
| 322 |
-
" output_xyjson = input_zipfile.parent / f'{input_zipfile.stem}_xy.json'\n",
|
| 323 |
-
"\n",
|
| 324 |
-
" xy_map = {}\n",
|
| 325 |
"\n",
|
| 326 |
" logger.info(f'Writing outputs to {output_zipfile.name} and {output_csvfile.name} in {input_zipfile.parent} folder')\n",
|
| 327 |
" with zipfile_writer(output_zipfile) as add_to_zip, csvfile_writer(output_csvfile) as write_row:\n",
|
| 328 |
" for filename, im in tqdm(images_from_zipfile(input_zipfile)):\n",
|
| 329 |
-
"
|
| 330 |
-
"
|
| 331 |
-
"
|
| 332 |
-
"
|
| 333 |
-
" xy_map[filename] = convert_xy_to_json(xy)\n",
|
| 334 |
-
" write_row({'filename': filename, 'count': count})\n",
|
| 335 |
-
" add_to_zip(heatmap, filename)\n",
|
| 336 |
-
" except Exception:\n",
|
| 337 |
-
" logger.error(f'failed to process {filename}')\n",
|
| 338 |
-
"\n",
|
| 339 |
-
" output_xyjson.write_text(json.dumps(xy_map))"
|
| 340 |
]
|
| 341 |
},
|
| 342 |
{
|
|
@@ -349,8 +310,6 @@
|
|
| 349 |
"\n",
|
| 350 |
"Use the form on colab to set the parameters, providing the zipfile with input images and a promt text representing the object you want to count.\n",
|
| 351 |
"\n",
|
| 352 |
-
"Use the fileupload button to add the zip file to the `countgd` directory or change the path below accordingly.\n",
|
| 353 |
-
"\n",
|
| 354 |
"If you are not running on colab, change the values in the next cell\n",
|
| 355 |
"\n",
|
| 356 |
"Make sure to run the cell once you change the value."
|
|
|
|
| 6 |
"id": "yxig5CdZuHb9"
|
| 7 |
},
|
| 8 |
"source": [
|
| 9 |
+
"# CountGD - Multimodela open-world object counting\n",
|
| 10 |
"\n"
|
| 11 |
]
|
| 12 |
},
|
|
|
|
| 89 |
"source": [
|
| 90 |
"### Install Dependencies\n",
|
| 91 |
"\n",
|
| 92 |
+
"The environment will be setup with the code, models and required dependencies."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
]
|
| 94 |
},
|
| 95 |
{
|
|
|
|
| 114 |
" git clone \"https://huggingface.co/spaces/nikigoli/countgd\" /content/countgd\n",
|
| 115 |
" fi\n",
|
| 116 |
" cd /content/countgd\n",
|
| 117 |
+
" git fetch origin refs/pr/5:refs/remotes/origin/pr/5\n",
|
| 118 |
+
" git checkout pr/5\n",
|
|
|
|
|
|
|
| 119 |
"else\n",
|
| 120 |
" # TODO check if cwd is the correct git repo\n",
|
| 121 |
" # If users use vscode, then we set the default start directory to root of the repo\n",
|
|
|
|
| 128 |
"pip install --upgrade pip setuptools wheel\n",
|
| 129 |
"pip install -r requirements.txt\n",
|
| 130 |
"\n",
|
| 131 |
+
"# Compile modules\n",
|
| 132 |
+
"export CUDA_HOME=/usr/local/cuda/\n",
|
| 133 |
"cd models/GroundingDINO/ops\n",
|
| 134 |
+
"python3 setup.py build\n",
|
| 135 |
+
"pip install .\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 136 |
"python3 test.py"
|
| 137 |
]
|
| 138 |
},
|
|
|
|
| 189 |
" get_device,\n",
|
| 190 |
" get_args_parser,\n",
|
| 191 |
" generate_heatmap,\n",
|
|
|
|
| 192 |
" predict,\n",
|
| 193 |
")\n",
|
| 194 |
"args = get_args_parser().parse_args([])\n",
|
|
|
|
| 197 |
"model = model.to(device)\n",
|
| 198 |
"\n",
|
| 199 |
"run = lambda image, text: predict(model, transform, image, text, None, device)\n",
|
| 200 |
+
"get_output = lambda image, boxes: (len(boxes), generate_heatmap(image, boxes))\n"
|
| 201 |
]
|
| 202 |
},
|
| 203 |
{
|
|
|
|
| 271 |
},
|
| 272 |
{
|
| 273 |
"cell_type": "code",
|
| 274 |
+
"execution_count": 15,
|
| 275 |
"metadata": {
|
| 276 |
"id": "rFXRk-_uuHb_"
|
| 277 |
},
|
|
|
|
| 279 |
"source": [
|
| 280 |
"from tqdm import tqdm\n",
|
| 281 |
"import os\n",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 282 |
"def process_zipfile(input_zipfile: Path, text: str):\n",
|
| 283 |
" if not input_zipfile.exists() or not input_zipfile.is_file() or not os.access(input_zipfile, os.R_OK):\n",
|
| 284 |
" logger.error(f'Cannot open / read zipfile: {input_zipfile}. Please check if it exists')\n",
|
|
|
|
| 290 |
"\n",
|
| 291 |
" output_zipfile = input_zipfile.parent / f'{input_zipfile.stem}_countgd.zip'\n",
|
| 292 |
" output_csvfile = input_zipfile.parent / f'{input_zipfile.stem}.csv'\n",
|
|
|
|
|
|
|
|
|
|
| 293 |
"\n",
|
| 294 |
" logger.info(f'Writing outputs to {output_zipfile.name} and {output_csvfile.name} in {input_zipfile.parent} folder')\n",
|
| 295 |
" with zipfile_writer(output_zipfile) as add_to_zip, csvfile_writer(output_csvfile) as write_row:\n",
|
| 296 |
" for filename, im in tqdm(images_from_zipfile(input_zipfile)):\n",
|
| 297 |
+
" boxes, _ = run(im, text)\n",
|
| 298 |
+
" count, heatmap = get_output(im, boxes)\n",
|
| 299 |
+
" write_row({'filename': filename, 'count': count})\n",
|
| 300 |
+
" add_to_zip(heatmap, filename)"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 301 |
]
|
| 302 |
},
|
| 303 |
{
|
|
|
|
| 310 |
"\n",
|
| 311 |
"Use the form on colab to set the parameters, providing the zipfile with input images and a promt text representing the object you want to count.\n",
|
| 312 |
"\n",
|
|
|
|
|
|
|
| 313 |
"If you are not running on colab, change the values in the next cell\n",
|
| 314 |
"\n",
|
| 315 |
"Make sure to run the cell once you change the value."
|
requirements.txt
CHANGED
|
@@ -17,5 +17,4 @@ tqdm
|
|
| 17 |
--extra-index-url https://download.pytorch.org/whl/cu121
|
| 18 |
torch<2.6
|
| 19 |
torchvision
|
| 20 |
-
transformers
|
| 21 |
-
pydantic==2.10.6
|
|
|
|
| 17 |
--extra-index-url https://download.pytorch.org/whl/cu121
|
| 18 |
torch<2.6
|
| 19 |
torchvision
|
| 20 |
+
transformers
|
|
|