@@ -19,13 +19,12 @@ const {GoogleGenAI} = require('@google/genai');
1919
2020const GOOGLE_CLOUD_PROJECT = process . env . GOOGLE_CLOUD_PROJECT ;
2121const GOOGLE_CLOUD_LOCATION = process . env . GOOGLE_CLOUD_LOCATION || 'global' ;
22-
22+ //todo notworking
2323async 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}
0 commit comments