This category is for question related to accounts on https://app.roboflow.com/
Please share the following so we may better assist you:
- Project type: Object detection
- OS: Win 10 Pro v10, Browser: Firefox v112.0.2
When I upload image/annotation pairs via the API, they’re added as ‘unassigned’ annotation jobs, instead of being added directly to the dataset as I’d expect them to be, since they’re already annotated.
This is only happening intermittently, about half the time it seems to work perfectly. Here’s the code I’m using for this:
const uploadImage = async (filepath, projectUrl, apiKey, extraOptions) => {
const filename = path.basename(filepath);
// console.log(filename, split)
const formData = new FormData();
formData.append("name", filename);
formData.append("file", fs.createReadStream(filepath));
formData.append("split", extraOptions.split);
try {
const response = await axios({
method: "POST",
url: `https://api.roboflow.com/dataset/${projectUrl}/upload?overwrite=true`,
params: {
api_key: process.env.ROBOFLOW_API_KEY,
},
data: formData,
headers: formData.getHeaders(),
});
console.log(response.data);
return response.data;
} catch (e) {
if (e.response) {
return e.response.data;
}
throw e;
}
};
const uploadAnnotation = async (imageID, annotationFile, projectUrl) => {
return new Promise(async (resolve, reject) => {
// gets the actual file name, given a full path
const filename = path.basename(annotationFile);
// reading the contents of the XML file
const annotationData = fs.readFileSync(annotationFile, "utf-8");
await axios({
method: "POST",
url: `https://api.roboflow.com/dataset/${projectUrl}/annotate/${imageID}?overwrite=true`,
params: {
api_key: process.env.ROBOFLOW_API_KEY,
name: filename,
},
data: annotationData,
headers: {
"Content-Type": "text/plain",
},
})
.then((res) => {
resolve(res.data);
})
.catch((e) => {
console.log("Error uploading annotation: ", e);
reject(e);
});
});
};
const uploadWithAnnotation = async (
fileName,
annotationFilename,
projectUrl,
apiKey,
extraOptions
) => {
const uploadPromise = uploadImage(fileName, projectUrl, apiKey, extraOptions);
// uploadAnnotation requires imageId from uploadImage, so I have to wait for that to complete first
const annotationPromise = await uploadPromise.then(async (uploadResult) => {
const imageId = uploadResult.id;
if (annotationFilename.includes("[filename]")) {
annotationFilename = annotationFilename.replace(
"[filename]",
path.parse(fileName).name
);
}
if (fs.existsSync(annotationFilename)) {
return await uploadAnnotation(
imageId,
annotationFilename,
projectUrl,
apiKey
)
.then((annotationResult) => {
return { uploadResult, annotationResult };
})
.catch((e) => {
console.log(e);
});
}
});
// resolve if both uploadImage and uploadAnnotation succeed, but reject if either fail
return Promise.all([uploadPromise, annotationPromise])
.then(([uploadResult, { annotationResult } = {}]) => {
return { uploadResult, annotationResult };
})
.catch((error) => {
console.error(` Error uploading ${fileName}: `, error);
throw error;
});
};
Images and annotations are saved locally first, then read back into these functions. The images are uploaded first, we await that, and then annotations are uploaded using the image ID received from the image upload.
Any idea what’s going wrong here? Or, if not, might it be possible instead to manually assign/approve all these images using the API, to add them to the dataset immediately?
Thank you,
Jake