Hello all,
The Imagen docs say that I can upscale an image using a gcsUri [1]. However, repeated attempts at making this work have been met with failure. I am running the following node code (I experience the same error in python). The error I'm getting back from the API is `RecvAsync is cancelled`
Here is my node reproduction:
import { GoogleAuth } from 'google-auth-library';
const url = 'https://us-central1-aiplatform.googleapis.com/v1/projects/gemini-image-generation-454107/locations/us-central1/publishers/google/models/imagegeneration@002:predict';
async function getAccessToken() {
const auth = new GoogleAuth({
keyFile: 'gemini-image-generation-454107-6fb54a12791d.json',
scopes: ['https://www.googleapis.com/auth/cloud-platform'],
});
const client = await auth.getClient();
const headers = await client.getRequestHeaders();
const token = headers['Authorization'].split(' ')[1];
return token;
}
async function upscaleImage(gsUri) {
const token = await getAccessToken();
const headers = {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
};
const payload = {
instances: [
{
image: {
gcsUri: gsUri
}
}
],
parameters: {
sampleCount: 1,
mode: "upscale",
upscaleConfig: {
upscaleFactor: "x2"
}
}
};
const response = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify(payload)
});
if (response.ok) {
console.log("Upscale success!");
return response.json();
} else {
const errorText = await response.text();
console.error(`Failed with status ${response.status}: ${errorText}`);
throw new Error(`Request failed with status ${response.status}: ${errorText}`);
}
}
const result = await upscaleImage('gs://upscaler-photo-upload/apple_2.png');
console.log('Upscale result:', result);
This results in the following failure:
Is this functionality not actually supported?
Thank you,
Lou
[1] See 'gcsUri' in the JSON body here: https://cloud.google.com/vertex-ai/generative-ai/docs/image/upscale-image
So I have some additional findings on this if anyone from the Imagen team is ability to assist:
- Using the `gcsUri` parameter never works, regardless of image size. Making a request with this parameter always results in a 499 with the error `RecvAsync is cancelled`
- If instead I use the `bytesBase64Encoded` param, then the request succeeds for small images, and works really well, completing quickly and with great results. As soon as the image is a medium size (say 3MB), the script will hang for a minute and then respond with:
{
"error": {
"code": 400,
"message": "Image editing failed with the following error: Response size too large. Received at least 31544347 bytes; max is 31457280.",
"status": "FAILED_PRECONDITION"
}
}
FWIW that image was originally 1920 × 2880 (which is not abnormally large) and I tried to upscale it 2x.
Here is the script that I used:
import { readFile } from 'fs/promises';
import { GoogleAuth } from 'google-auth-library';
import { Storage } from '@google-cloud/storage';
import path from 'path';
import fs from 'fs';
import { writeFile } from 'fs/promises';
// URL for the Vertex AI upscale endpoint
const url = 'https://us-central1-aiplatform.googleapis.com/v1/projects/gemini-image-generation-454107/locations/us-central1/publishers/google/models/imagen-3.0-generate-002:predict';
// Convert image file to base64
async function imageToBase64(imagePath) {
const imageData = await readFile(imagePath);
return imageData.toString('base64');
}
// Authenticate using GoogleAuth and get access token explicitly
async function getAccessToken() {
const auth = new GoogleAuth({
keyFile: 'gemini-image-generation-454107-6fb54a12791d.json',
scopes: ['https://www.googleapis.com/auth/cloud-platform'],
});
const client = await auth.getClient();
// Important: Use getRequestHeaders to get a proper auth header
const headers = await client.getRequestHeaders();
const token = headers['Authorization'].split(' ')[1]; // Removes the "Bearer " prefix
return token;
}
// Function to upscale the image
async function upscaleImage(base64Image) {
const token = await getAccessToken();
const headers = {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
};
const payload = {
instances: [
{
// prompt: "",
image: {
// gcsUri: "gs://delete-this-bucket-it-is-public-testing/apple_icon.png",
//gcsUri: "gs://delete-this-bucket-it-is-public-testing/blob.b64",
mimeType: "image/png",
// mimeType: "image/png"
bytesBase64Encoded: base64Image
}
}
],
parameters: {
sampleCount: 1,
mode: "upscale",
upscaleConfig: {
upscaleFactor: "x2"
},
storageUri: "gs://upscaler-photo-upload/output",
}
};
const response = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify(payload)
});
if (response.ok) {
console.log("Upscale success!");
return response.json();
} else {
const errorText = await response.text();
console.error(`Failed with status ${response.status}: ${errorText}`);
throw new Error(`Request failed with status ${response.status}: ${errorText}`);
}
}
// Write the base64 string to blob.b64
async function saveBase64ToFile(base64Data) {
try {
await writeFile('blob.b64', base64Data, 'utf8');
console.log('Saved as blob.b64');
} catch (err) {
console.error('Error saving file:', err);
}
}
// Main function to run the upscale example
async function main() {
try {
const base64 = await imageToBase64('big_pink.png');
//const base64 = await imageToBase64('medium_pink.png');
// await saveBase64ToFile(base64);
const result = await upscaleImage(base64);
console.log('Upscale result:', result);
} catch (error) {
console.error('Error:', error);
}
}
User | Count |
---|---|
2 | |
1 | |
1 | |
1 | |
1 |