azure-cognitive-servicesazure-sdkmicrosoft-custom-visionazure-sdk-js

How to upload a batch of images to Azure Custom Vision using JavaScript


I want to upload a batch of 64 images to Custom Vision using the JavaScript SDK.

const files: ImageFileCreateEntry[] = []
while (i < 64) {
    const data = fs.readFileSync(`${sampleDataRoot}/${tag.name}/${file}`)
    const fileEntry: ImageFileCreateEntry = { name: file, contents: data }
    files.push(fileEntry);
    i++
}
const batch: ImageFileCreateBatch = { images: files, tagIds: [tag.id] }
fileUploadPromises.push(client.createImagesFromFiles(projectId, batch))

But I'm getting the following error:

RestError: No valid image files
    at new RestError (/home/pomatti/projects/personal/azure-customvision-benchmark/node_modules/@azure/ms-rest-js/lib/restError.ts:18:5)
    at /home/pomatti/projects/personal/azure-customvision-benchmark/node_modules/@azure/ms-rest-js/lib/policies/deserializationPolicy.ts:117:27
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async Promise.all (index 5) {
  code: 'BadRequestImageBatch',
  statusCode: 400,
  request: WebResource {
    streamResponseBody: false,
    url: 'https://eastus.api.cognitive.microsoft.com/customvision/v3.3/training/projects/ff4967f9-f772-4473-89a5-41356c471454/images/files',
    method: 'POST',
    headers: HttpHeaders { _headersMap: [Object] },
    body: '{"images":[],"tagIds":["8a2e95b5-2050-403d-95e7-45b08e358d7d"]}',
    query: undefined,
    formData: undefined,
    withCredentials: false,
    abortSignal: undefined,
    timeout: 0,
    onUploadProgress: undefined,
    onDownloadProgress: undefined,
    proxySettings: undefined,
    keepAlive: undefined,
    operationSpec: {
      httpMethod: 'POST',
      path: 'projects/{projectId}/images/files',
      urlParameters: [Array],
      requestBody: [Object],
      responses: [Object],
      serializer: [Serializer]
    }
  },
  response: {
    body: '{"code":"BadRequestImageBatch","message":"No valid image files"}',
    headers: HttpHeaders { _headersMap: [Object] },
    status: 400
  },
  body: { code: 'BadRequestImageBatch', message: 'No valid image files' }
}

Solution

  • I figured out that my implementation was completely messed up.

    This is how I solved it for now:

    const client = getTrainingClient();
    const tags = await client.getTags(projectId);
    
    let fileUploadPromises = [];
    tags.forEach(tag => {
        const imageFiles = fs.readdirSync(`${sampleDataRoot}/${tag.name}`);
        const files: ImageFileCreateEntry[] = []
        const chunk = imageFiles.slice(0, 64)
        chunk.forEach(file => {
            const data = fs.readFileSync(`${sampleDataRoot}/${tag.name}/${file}`)
            const fileEntry: ImageFileCreateEntry = { name: file, contents: data }
            files.push(fileEntry);
        })
        const batch: ImageFileCreateBatch = { images: files, tagIds: [tag.id] }
        fileUploadPromises.push(client.createImagesFromFiles(projectId, batch))
    })