Skip to content

Commit a5d6333

Browse files
author
Guiners
committed
adding samples, test, lints
1 parent 7aa2a16 commit a5d6333

File tree

3 files changed

+83
-11
lines changed

3 files changed

+83
-11
lines changed

genai/bounding-box/boundingbox-with-txt-img.js

Lines changed: 79 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,12 @@ const {GoogleGenAI} = require('@google/genai');
1919

2020
const GOOGLE_CLOUD_PROJECT = process.env.GOOGLE_CLOUD_PROJECT;
2121
const GOOGLE_CLOUD_LOCATION = process.env.GOOGLE_CLOUD_LOCATION || 'global';
22-
22+
//todo notworking
2323
async function generateContent(
2424
projectId = GOOGLE_CLOUD_PROJECT,
2525
location = GOOGLE_CLOUD_LOCATION
2626
) {
2727

28-
2928
/**
3029
* Represents a bounding box with its 2D coordinates and associated label.
3130
*/
@@ -47,24 +46,94 @@ async function generateContent(
4746
}
4847
}
4948

49+
/**
50+
* Helper function to plot bounding boxes on an image
51+
* @param {string} imageUri
52+
* @param {BoundingBox[]} boundingBoxes
53+
*/
54+
async function plotBoundingBoxes(imageUri, boundingBoxes) {
55+
const image = await loadImage(imageUri);
56+
const width = image.width;
57+
const height = image.height;
58+
59+
const canvas = createCanvas(width, height);
60+
const ctx = canvas.getContext('2d');
61+
62+
ctx.drawImage(image, 0, 0, width, height);
63+
64+
const colors = ['red', 'green', 'blue', 'orange', 'purple', 'yellow', 'cyan', 'magenta', 'lime', 'pink'];
65+
66+
boundingBoxes.forEach((bbox, i) => {
67+
const absYMin = Math.floor((bbox.box2d[0] / 1000) * height);
68+
const absXMin = Math.floor((bbox.box2d[1] / 1000) * width);
69+
const absYMax = Math.floor((bbox.box2d[2] / 1000) * height);
70+
const absXMax = Math.floor((bbox.box2d[3] / 1000) * width);
71+
72+
const color = colors[i % colors.length];
73+
74+
ctx.strokeStyle = color;
75+
ctx.lineWidth = 4;
76+
ctx.strokeRect(absXMin, absYMin, absXMax - absXMin, absYMax - absYMin);
77+
78+
if (bbox.label) {
79+
ctx.fillStyle = color;
80+
ctx.font = '20px Arial';
81+
ctx.fillText(bbox.label, absXMin + 8, absYMin + 20);
82+
}
83+
});
84+
85+
// Save or return buffer
86+
return canvas.toBuffer('image/png');
87+
}
88+
5089
const ai = new GoogleGenAI({
5190
vertexai: true,
5291
project: projectId,
5392
location: location,
5493
});
5594

95+
const systemInstructions = 'Return bounding boxes as an array with labels.\n' +
96+
' Never return masks. Limit to 25 objects.\n' +
97+
' If an object is present multiple times, give each object a unique label\n' +
98+
' according to its distinct characteristics (colors, size, position, etc..).'
99+
100+
const imageUri = "https://storage.googleapis.com/generativeai-downloads/images/socks.jpg";
101+
102+
const prompt = [
103+
{ file_uri: imageUri, mime_type: 'image/jpeg' }, // zamiast Part.fromUri
104+
"Output the positions of the socks with a face. Label according to position in the image."
105+
];
106+
107+
const config = {
108+
systemInstructions: systemInstructions,
109+
temperature: 0.5,
110+
safetySettings: [
111+
{
112+
category: 'HARM_CATEGORY_DANGEROUS_CONTENT',
113+
threshold: 'BLOCK_ONLY_HIGH',
114+
},
115+
],
116+
responseMimeType: 'application/json'
117+
};
56118

57-
const response = await ai.models.embedContent({
58-
model: 'gemini-embedding-001',
119+
120+
const response = await ai.models.generateContent({
121+
model: 'gemini-2.5-flash',
59122
contents: prompt,
60-
config: {
61-
taskType: 'RETRIEVAL_DOCUMENT', // Optional
62-
outputDimensionality: 3072, // Optional
63-
title: "Driver's License" // Optional
64-
}
123+
config: config
65124
});
66125

67-
console.log(response);
126+
console.log(response.text);
127+
128+
let boundingBoxes = [];
129+
try {
130+
boundingBoxes = JSON.parse(response.text).map(b => new BoundingBox(b.box_2d, b.label));
131+
} catch (err) {
132+
console.error('Failed to parse response:', err);
133+
}
134+
135+
await plotBoundingBoxes(imageUri, boundingBoxes);
136+
68137

69138
return response;
70139
}

genai/test/boundingbox-with-txt-img.test.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ const projectId = process.env.CAIP_PROJECT_ID;
2121
const sample = require('../bounding-box/boundingbox-with-txt-img');
2222

2323
describe('boundingbox-with-txt-img', async () => {
24-
it('should return the total token count for a text prompt', async () => {
24+
it('should return the total token count for a text prompt', async function (){
25+
this.timeout(10000);
2526
const output = await sample.generateContent(projectId);
2627
assert(output > 0);
2728
});

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@
3131
"typescript": "^5.0.4"
3232
},
3333
"dependencies": {
34+
"canvas": "^3.1.2",
3435
"commander": "^12.0.0",
3536
"eslint": "^8.57.0",
37+
"node-fetch": "^3.3.2",
3638
"proxyquire": "^2.1.3"
3739
}
3840
}

0 commit comments

Comments
 (0)