Skip to content

Commit d889686

Browse files
bilalcodehubbilalcodehub
andauthored
Fix download_from_cvat bug: revised based on the new CVAT API. (#1832)
Signed-off-by: bilalcodehub <[email protected]> Co-authored-by: bilalcodehub <[email protected]>
1 parent e46e962 commit d889686

File tree

1 file changed

+23
-19
lines changed

1 file changed

+23
-19
lines changed

monailabel/datastore/cvat.py

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ def download_from_cvat(self, max_retry_count=5, retry_wait_time=10):
225225
task_id, task_name = self.get_cvat_task_id(project_id, create=False)
226226
logger.info(f"Preparing to download/update final labels from: {project_id} => {task_id} => {task_name}")
227227

228-
# Step 1: Initiate export process
228+
# Step 1: Initiate export process using the new POST endpoint.
229229
export_url = f"{self.api_url}/api/tasks/{task_id}/dataset/export?format=Segmentation+mask+1.1&location=local&save_images=false"
230230
try:
231231
response = requests.post(export_url, auth=self.auth)
@@ -242,67 +242,71 @@ def download_from_cvat(self, max_retry_count=5, retry_wait_time=10):
242242
logger.exception(f"Error while initiating export process: {e}")
243243
return None
244244

245-
# Step 2: Poll export status
245+
# Step 2: Poll export status using the new GET endpoint.
246246
status_url = f"{self.api_url}/api/requests/{rq_id}"
247247
for _ in range(max_retry_count):
248248
try:
249249
status_response = requests.get(status_url, auth=self.auth)
250-
status = status_response.json().get("status")
251-
if status == "finished":
250+
status_data = status_response.json()
251+
current_status = status_data.get("status")
252+
if current_status == "finished":
252253
logger.info("Export process completed successfully.")
253254
break
254-
elif status == "failed":
255-
logger.error(f"Export process failed: {status_response.json()}")
255+
elif current_status == "failed":
256+
logger.error(f"Export process failed: {status_data}")
256257
return None
257258
logger.info(f"Export in progress... Retrying in {retry_wait_time} seconds.")
258259
time.sleep(retry_wait_time)
259260
except Exception as e:
260261
logger.exception(f"Error checking export status: {e}")
261-
time.sleep(retry_wait_time)
262+
time.sleep(retry_wait_time)
262263
else:
263264
logger.error("Export process did not complete within the maximum retries.")
264265
return None
265266

266-
# Step 3: Download the dataset
267-
download_url = f"{self.api_url}/api/tasks/{task_id}/annotations?format=Segmentation+mask+1.1&location=local&save_images=false&action=download"
267+
# Step 3: Retrieve the download URL from the export status.
268+
result_url = status_data.get("result_url")
269+
if not result_url:
270+
logger.error("Export process finished but no result_url was provided.")
271+
return None
272+
273+
# Step 4: Download the ZIP file from the result_url.
268274
tmp_folder = tempfile.TemporaryDirectory().name
269275
os.makedirs(tmp_folder, exist_ok=True)
270276

271277
tmp_zip = tempfile.NamedTemporaryFile(suffix=".zip").name
272278
retry_count = 0
273279
for retry in range(max_retry_count):
274280
try:
275-
logger.info(f"Downloading exported dataset from: {download_url}")
276-
r = requests.get(download_url, allow_redirects=True, auth=self.auth)
277-
281+
logger.info(f"Downloading exported dataset from: {result_url}")
282+
r = requests.get(result_url, allow_redirects=True, auth=self.auth)
278283
with open(tmp_zip, "wb") as fp:
279284
fp.write(r.content)
280285
shutil.unpack_archive(tmp_zip, tmp_folder)
281286

287+
# Process the segmentation files
282288
segmentations_dir = os.path.join(tmp_folder, "SegmentationClass")
283289
final_labels = self._datastore.label_path(DefaultLabelTag.FINAL)
284290
for f in os.listdir(segmentations_dir):
285291
label = os.path.join(segmentations_dir, f)
286292
if os.path.isfile(label) and label.endswith(".png"):
287293
os.makedirs(final_labels, exist_ok=True)
288-
289294
dest = os.path.join(final_labels, f)
290295
if self.normalize_label:
291296
img = np.array(Image.open(label))
292297
mask = np.zeros_like(img)
293-
294298
labelmap = self._load_labelmap_txt(os.path.join(tmp_folder, "labelmap.txt"))
295299
for name, color in labelmap.items():
296300
if name in self.label_map:
297301
idx = self.label_map.get(name)
298302
mask[np.all(img == color, axis=-1)] = idx
299-
Image.fromarray(mask[:, :, 0]).save(dest) # single channel
300-
logger.info(f"Copy Final Label: {label} to {dest}; unique: {np.unique(mask)}")
303+
Image.fromarray(mask[:, :, 0]).save(dest)
304+
logger.info(f"Copied Final Label: {label} to {dest}; unique: {np.unique(mask)}")
301305
else:
302306
Image.open(label).save(dest)
303-
logger.info(f"Copy Final Label: {label} to {dest}")
307+
logger.info(f"Copied Final Label: {label} to {dest}")
304308

305-
# Rename task after consuming/downloading the labels
309+
# Rename the task to indicate that labels have been processed.
306310
patch_url = f"{self.api_url}/api/tasks/{task_id}"
307311
body = {"name": f"{self.done_prefix}_{task_name}"}
308312
requests.patch(patch_url, allow_redirects=True, auth=self.auth, json=body)
@@ -311,7 +315,7 @@ def download_from_cvat(self, max_retry_count=5, retry_wait_time=10):
311315
if retry_count:
312316
logger.exception(e)
313317
logger.error(f"{retry} => Failed to download...")
314-
retry_count = retry_count + 1
318+
retry_count += 1
315319
return None
316320

317321

0 commit comments

Comments
 (0)