forked from glushenkovIG/Magic-Moment
-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
idea from chatgpt:
import OpenAI from "openai";
import { z } from "zod";
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const CropSchema = z.object({
focalPoint: z.object({ x: z.number(), y: z.number() }) // normalized [0..1]
.describe("Where to center the crop, e.g. main face/action."),
regions: z.array(z.object({
label: z.string(),
confidence: z.number(),
box: z.object({ x: z.number(), y: z.number(), w: z.number(), h: z.number() }) // normalized [0..1]
})).max(5)
});
export async function getSmartCropHints(imageUrl: string) {
const resp = await client.responses.create({
model: "gpt-4o-mini",
input: [
{
role: "user",
content: [
{ type: "input_text", text:
"Find the most interesting subject(s) to preserve in a crop. " +
"Return a normalized focalPoint and up to 5 bounding boxes with labels. " +
"Prefer faces, people, logos, text, hands/tools, or strong action. " +
"If multiple, choose the one that best represents the photo." },
{ type: "input_image", image_url: imageUrl }
]
}
],
// Structured output (JSON Schema) — validated locally with Zod:
response_format: { type: "json_schema", json_schema: { name: "CropHints", schema: CropSchema } }
});
const data = CropSchema.parse(resp.output[0].content[0].json);
return data;
}
// Example: compute a crop rect (in pixels) for a target aspect ratio
export function computeCropRect(
imgW: number, imgH: number,
focal: {x:number;y:number}, // normalized
aspect: number // e.g. 1.0 for square, 16/9, 4/5, etc.
) {
// pick max size that fits image and keeps aspect, centered on focal point
let cropW = imgW, cropH = Math.round(imgW / aspect);
if (cropH > imgH) { cropH = imgH; cropW = Math.round(imgH * aspect); }
let cx = Math.round(focal.x * imgW);
let cy = Math.round(focal.y * imgH);
let x = Math.round(cx - cropW / 2);
let y = Math.round(cy - cropH / 2);
// clamp to image bounds
x = Math.max(0, Math.min(x, imgW - cropW));
y = Math.max(0, Math.min(y, imgH - cropH));
return { x, y, w: cropW, h: cropH };
}
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels