_id: artworks description: Image generation, mask extraction, etc. readme: The first version is ready title: en=ArtWorks AI;ru=Узлы ArtWorks AI url: https://huggingface.co/PiperMy/Node-Packages/resolve/main/artworks.yaml version: 2 nodes: inpaint_image_artworks: _id: inpaint_image_artworks arrange: x: 440 y: 60 category: id: generate_images title: en=Generate images;ru=Генерация изображений groups: inputs: mask: order: 2 title: en=Mask;ru=Маска SDXL: order: 4 title: SDXL checkpoints description: Only for SDXL checkpoints base: order: 1 title: en=Base;ru=Базовые параметры special: order: 3 title: en=Special;ru=Специальные возможности inputs: image: order: 1 title: en=Image;ru=Изображение group: base type: image required: true extensions: - id: draw-mask params: mask: mask prompt: order: 2 title: en=Prompt;ru=Подсказка group: base type: string required: true multiline: true negativePrompt: order: 4 title: en=Negative prompt;ru=Негативная подсказка group: base type: string multiline: true checkpoint: order: 3 title: en=Checkpoint;ru=Модель group: base type: string required: true default: juggernautXL_v9Rundiffusionphoto2.safetensors enum: - raemuXL_v40.safetensors|Raemu XL - aamXLAnimeMix_v10.safetensors|AAM XL (Anime Mix) - dreamweaverPony25D.1erv.safetensors|DreamWeaver - Pony 2.5D Mix - mixGEMAdam8witQegoow.NeWz.safetensors|MyMIX-G/Jem - mfcgPDXL_v10.safetensors|MFCG PDXL - aniku_0.2.fp16.safetensors|Anime Desire - flux1DevHyperNF4Flux1DevBNB_flux1DevHyperNF4.safetensors|Hyper NF4 Flux 1 - STOIQONewrealityFLUXSD_F1DPreAlpha.safetensors|New Reality Flux - juggernautXL_v9Rundiffusionphoto2.safetensors|Juggernaut XL - animaPencilXL_v260.safetensors|Anima Pencil XL - bluePencilXL_v401.safetensors|Blue Pencil XL - pixelArtDiffusionXL_spriteShaper.safetensors|Pixel Art Diffusion XL - albedobaseXL_v20.safetensors|AlbedoBase XL - leosamsHelloworldXL_helloworldXL50GPT4V.safetensors|Helloworld XL - dynavisionXLAllInOneStylized_releaseV0610Bakedvae.safetensors|DynaVision XL All In One - photon_v1.safetensors|Photon - afroditexlNudePeople_20Bkdvae.safetensors|Nude People - nosft-float8-e4m3fn.safetensors|Flux Nude People - asdf_0.4a_lorapov_0.2_lust_0.4.fp16.safetensors|Real Porn - Sexy_Aesthetic_SDXL_0.4x0.2.fp16.safetensors|Sexy & Beauty - aniku_0.2.fp16.safetensors|Anime Desire - anikurender_0.4b.fp16.safetensors|Hardcore Fantasy denoisingStrength: order: 6 title: en=Denoising strength;ru=Степень изменения group: base type: float required: true min: 0.1 max: 1 step: 0.05 default: 0.5 cfgScale: order: 7 title: en=CFG scale;ru=Креативность group: base type: integer required: true min: 1 max: 20 step: 1 default: 7 imageSize: order: 5 title: en=Image size;ru=Размер изображения group: base type: string placeholder: auto:auto default: auto:auto enum: - auto:1024 - 1024:auto - auto:auto performance: order: 8 title: en=Performance;ru=Производительность group: base type: string default: speed enum: - express|⚡ Express - speed|🚅 Speed - quality|💎 Quality controlNets: order: 1 title: en=Control nets;ru=Контрольные сети group: special type: json schema: id: control-nets seed: order: 10 title: en=Seed;ru=Начальный шум group: base type: integer batchSize: order: 9 title: en=Batch size;ru=Кол-во group: base type: integer min: 1 max: 4 step: 1 default: 1 mask: order: 1 title: en=Mask;ru=Маска group: mask type: image required: true invertMask: order: 1 title: en=Invert mask;ru=Инвертировать маску group: SDXL type: boolean default: false maskMargin: order: 2 title: en=Mask margin;ru=Отступ от маски group: mask type: integer default: 10 outputs: image1: title: en=Image 1;ru=Изображение 1 type: image images: title: en=Images;ru=Изображения type: image[] image2: title: en=Image 2;ru=Изображение 2 type: image image3: title: en=Image 3;ru=Изображение 3 type: image image4: title: en=Image 4;ru=Изображение 4 type: image package: artworks script: | const CHECK_TASK_INTERVAL = 3000; const MAX_ATTEMPTS = 100; export async function run({ inputs, state }) { const { FatalError, TimeoutError, RepeatNode, NextNode } = DEFINITIONS; const { ArtWorks, fitSize, FatalError: ArtWorksError } = require('artworks'); const sharp = require('sharp/lib/index.js'); const PAAS_BASE_URL = env.variables.get('PAAS_BASE_URL'); if (!PAAS_BASE_URL) { throw new FatalError('Please, set PAAS_BASE_URL in environment'); } const OPEN_PAAS_USER = env.variables.get('OPEN_PAAS_USER'); if (!OPEN_PAAS_USER) { throw new FatalError('Please, set OPEN_PAAS_USER in environment'); } const OPEN_PAAS_PASSWORD = env.variables.get('OPEN_PAAS_PASSWORD'); if (!OPEN_PAAS_PASSWORD) { throw new FatalError('Please, set OPEN_PAAS_PASSWORD in environment'); } const artworks = new ArtWorks({ baseUrl: PAAS_BASE_URL, username: OPEN_PAAS_USER, password: OPEN_PAAS_PASSWORD }); if (!state) { const { image, prompt, checkpoint, negativePrompt, imageSize, denoisingStrength, cfgScale, performance, batchSize, seed, // mask mask, maskMargin, // special controlNets, // SDXL invertMask, } = inputs; const payload = { type: "inpaint-on-image", isFast: true, payload: { base64: false, image, prompt, checkpoint, negativePrompt, ...(!!imageSize ? await (async () => { const { data } = await download(image); const buffer = sharp(data); const { width, height } = await buffer.metadata(); if (imageSize !== "auto:auto") { const { width: w, height: h } = fitSize(imageSize, height / width); return { size: `${w}x${h}` }; } return {}; })() : {}), denoisingStrength, cfgScale, performance, ...(batchSize > 1 ? { batchSize } : {}), seed, // mask mask, maskMargin, // special controlNets, // SDXL invertMask }, }; try { const task = await artworks.createTask(payload); console.log(`Task created ${task}`); return RepeatNode.from({ state: { payload, task, attempt: 0, startedAt: new Date() }, progress: { total: MAX_ATTEMPTS, processed: 0 }, delay: 2000 }); } catch (e) { if (e instanceof ArtWorksError) { throw new FatalError(e.message); } throw e; } } else { const { payload, task, attempt, startedAt } = state; if (attempt > MAX_ATTEMPTS) { try { await artworks.cancelTask(task); } catch (e) { } const now = new Date(); const time = (now - new Date(startedAt)) / 1000; throw new TimeoutError(`PaaS task for text to image ${task} timeout in ${time} sec`); } console.log(`Check task ${attempt} ${task}`); try { const results = await artworks.checkState(task); if (!results) { return RepeatNode.from({ delay: CHECK_TASK_INTERVAL, state: { payload, task, attempt: attempt + 1, startedAt, }, progress: { total: MAX_ATTEMPTS, processed: attempt }, }); } let images = results.images.map((i) => i.url); const [image1, image2, image3, image4] = images; return NextNode.from({ outputs: { images, image1, image2, image3, image4 } }); } catch (e) { if (e instanceof ArtWorksError) { throw new FatalError(e.message); } throw e; } } } source: catalog title: en=Inpaint on image;ru=Улучшить изображение version: 1 environment: OPEN_PAAS_USER: title: PaaS user type: string scope: global OPEN_PAAS_PASSWORD: title: PaaS password type: string scope: global PAAS_BASE_URL: title: PaaS base url type: string scope: global face_swap_on_image: _id: face_swap_on_image arrange: x: 760 y: 180 category: id: deep_swap title: en=Deep swap;ru=Глубокая замена environment: OPEN_PAAS_USER: title: PaaS user type: string scope: global OPEN_PAAS_PASSWORD: title: PaaS password type: string scope: global PAAS_BASE_URL: title: PaaS base url type: string scope: global inputs: face: order: 1 title: en=Face;ru=Лицо type: image required: true image: order: 2 title: en=Image;ru=Изображение type: image required: true outputs: image: title: en=Image;ru=Изображение type: image package: artworks script: | const CHECK_TASK_INTERVAL = 3000; const MAX_ATTEMPTS = 20; export async function run({ inputs, state }) { const { FatalError, TimeoutError, RepeatNode, NextNode } = DEFINITIONS; const { ArtWorks, FatalError: ArtWorksError } = require('artworks'); const PAAS_BASE_URL = env.variables.get('PAAS_BASE_URL'); if (!PAAS_BASE_URL) { throw new FatalError('Please, set PAAS_BASE_URL in environment'); } const OPEN_PAAS_USER = env.variables.get('OPEN_PAAS_USER'); if (!OPEN_PAAS_USER) { throw new FatalError('Please, set OPEN_PAAS_USER in environment'); } const OPEN_PAAS_PASSWORD = env.variables.get('OPEN_PAAS_PASSWORD'); if (!OPEN_PAAS_PASSWORD) { throw new FatalError('Please, set OPEN_PAAS_PASSWORD in environment'); } const artworks = new ArtWorks({ baseUrl: PAAS_BASE_URL, username: OPEN_PAAS_USER, password: OPEN_PAAS_PASSWORD }); if (!state) { const { face, image } = inputs; const payload = { type: "faceswap-on-image", isFast: true, payload: { base64: false, face, image, } }; try { const task = await artworks.createTask(payload); console.log(`Task created ${task}`); return RepeatNode.from({ state: { payload, task, attempt: 0, startedAt: new Date() }, progress: { total: MAX_ATTEMPTS, processed: 0 }, delay: 2000 }); } catch (e) { if (e instanceof ArtWorksError) { throw new FatalError(e.message); } throw e; } } else { const { payload, task, attempt, startedAt } = state; if (attempt > MAX_ATTEMPTS) { try { await artworks.cancelTask(task); } catch (e) { } const now = new Date(); const time = (now - new Date(startedAt)) / 1000; throw new TimeoutError(`PaaS task for text to image ${task} timeout in ${time} sec`); } console.log(`Check task ${attempt} ${task}`); try { const results = await artworks.checkState(task); if (!results) { return RepeatNode.from({ delay: CHECK_TASK_INTERVAL, state: { payload, task, attempt: attempt + 1, startedAt, }, progress: { total: MAX_ATTEMPTS, processed: attempt }, }); } let { images: [{ url: image }] } = results; return NextNode.from({ outputs: { image } }); } catch (e) { if (e instanceof ArtWorksError) { throw new FatalError(e.message); } throw e; } } } source: catalog title: en=Face swap on image;ru=Замена лица на изображении version: 1 translate_text: _id: translate_text arrange: x: 770 y: 370 category: id: process_text title: en=Process text;ru=Обработка текста inputs: source: order: 1 title: Source language type: string required: true default: auto enum: - auto|Auto - en|English - de|German - ru|Russian - es|Spanish - fr|French - it|Italian - pt|Portuguese - ja|Japanese - ko|Korean - hi|Hindi - tr|Turkish - zh|Chinese Simplified target: order: 2 title: Target description: github://generative-core/piper/main/docs/nodes/translate-text/target.md type: string required: true default: de enum: - en|English - de|German - ru|Russian - es|Spanish - fr|French - it|Italian - pt|Portuguese - ja|Japanese - ko|Korean - hi|Hindi - tr|Turkish - zh|Chinese Simplified text: order: 3 title: Text type: string required: true multiline: true outputs: text: title: Text type: string alternatives: title: Alternatives type: string[] detectedLanguage: title: Detected language type: json schema: detected-languages package: artworks source: catalog title: en=Translate text;ru=Перевести текст version: 1 environment: OPEN_PAAS_USER: title: PaaS user type: string scope: global OPEN_PAAS_PASSWORD: title: PaaS password type: string scope: global PAAS_BASE_URL: title: PaaS base url type: string scope: global script: | const CHECK_TASK_INTERVAL = 3000; const MAX_ATTEMPTS = 10; export async function run({ inputs, state }) { const { FatalError, TimeoutError, RepeatNode, NextNode } = DEFINITIONS; const { ArtWorks, FatalError: ArtWorksError } = require('artworks'); const PAAS_BASE_URL = env.variables.get('PAAS_BASE_URL'); if (!PAAS_BASE_URL) { throw new FatalError('Please, set PAAS_BASE_URL in environment'); } const OPEN_PAAS_USER = env.variables.get('OPEN_PAAS_USER'); if (!OPEN_PAAS_USER) { throw new FatalError('Please, set OPEN_PAAS_USER in environment'); } const OPEN_PAAS_PASSWORD = env.variables.get('OPEN_PAAS_PASSWORD'); if (!OPEN_PAAS_PASSWORD) { throw new FatalError('Please, set OPEN_PAAS_PASSWORD in environment'); } const artworks = new ArtWorks({ baseUrl: PAAS_BASE_URL, username: OPEN_PAAS_USER, password: OPEN_PAAS_PASSWORD }); if (!state) { const { source, target, text } = inputs; const payload = { type: "translate-text", isFast: true, payload: { source, target, text, }, }; try { const task = await artworks.createTask(payload); console.log(`Task created ${task}`); return RepeatNode.from({ state: { payload, task, attempt: 0, startedAt: new Date() }, progress: { total: MAX_ATTEMPTS, processed: 0 }, delay: 2000 }); } catch (e) { if (e instanceof ArtWorksError) { throw new FatalError(e.message); } throw e; } } else { const { payload, task, attempt, startedAt } = state; if (attempt > MAX_ATTEMPTS) { try { await artworks.cancelTask(task); } catch (e) { } const now = new Date(); const time = (now - new Date(startedAt)) / 1000; throw new TimeoutError(`PaaS task for text to image ${task} timeout in ${time} sec`); } console.log(`Check task ${attempt} ${task}`); try { const results = await artworks.checkState(task); if (!results) { return RepeatNode.from({ delay: CHECK_TASK_INTERVAL, state: { payload, task, attempt: attempt + 1, startedAt, }, progress: { total: MAX_ATTEMPTS, processed: attempt }, }); } console.log(results); const { alternatives, detectedLanguage, text } = results; return NextNode.from({ outputs: { alternatives, detectedLanguage, text } }); } catch (e) { if (e instanceof ArtWorksError) { throw new FatalError(e.message); } throw e; } } } upscale_image: _id: upscale_image arrange: x: 100 y: 410 category: id: generate_images title: en=Generate images;ru=Генерация изображений environment: OPEN_PAAS_USER: title: PaaS user type: string scope: global OPEN_PAAS_PASSWORD: title: PaaS password type: string scope: global PAAS_BASE_URL: title: PaaS base url type: string scope: global inputs: image: order: 1 title: Image type: image required: true upscalingResize: order: 2 title: Resize type: float required: true min: 0.1 max: 4 step: 0.1 default: 2 outputs: image: title: Image type: image package: artworks source: catalog title: en=Upscale image;ru=Увеличить изображение version: 1 script: |- const CHECK_TASK_INTERVAL = 3000; const MAX_ATTEMPTS = 20; export async function run({ inputs, state }) { const { FatalError, TimeoutError, RepeatNode, NextNode } = DEFINITIONS; const { ArtWorks, FatalError: ArtWorksError } = require('artworks'); const PAAS_BASE_URL = env.variables.get('PAAS_BASE_URL'); if (!PAAS_BASE_URL) { throw new FatalError('Please, set PAAS_BASE_URL in environment'); } const OPEN_PAAS_USER = env.variables.get('OPEN_PAAS_USER'); if (!OPEN_PAAS_USER) { throw new FatalError('Please, set OPEN_PAAS_USER in environment'); } const OPEN_PAAS_PASSWORD = env.variables.get('OPEN_PAAS_PASSWORD'); if (!OPEN_PAAS_PASSWORD) { throw new FatalError('Please, set OPEN_PAAS_PASSWORD in environment'); } const artworks = new ArtWorks({ baseUrl: PAAS_BASE_URL, username: OPEN_PAAS_USER, password: OPEN_PAAS_PASSWORD }); if (!state) { const { image, upscalingResize, } = inputs; const payload = { type: "upscale-image", isFast: true, payload: { base64: false, image, upscalingResize, }, }; try { const task = await artworks.createTask(payload); console.log(`Task created ${task}`); return RepeatNode.from({ state: { payload, task, attempt: 0, startedAt: new Date() }, progress: { total: MAX_ATTEMPTS, processed: 0 }, delay: 5000 }); } catch (e) { if (e instanceof ArtWorksError) { throw new FatalError(e.message); } throw e; } } else { const { payload, task, attempt, startedAt } = state; if (attempt > MAX_ATTEMPTS) { try { await artworks.cancelTask(task); } catch (e) { } const now = new Date(); const time = (now - new Date(startedAt)) / 1000; throw new TimeoutError(`PaaS task for text to image ${task} timeout in ${time} sec`); } console.log(`Check task ${attempt} ${task}`); try { const results = await artworks.checkState(task); if (!results) { return RepeatNode.from({ delay: CHECK_TASK_INTERVAL, state: { payload, task, attempt: attempt + 1, startedAt, }, progress: { total: MAX_ATTEMPTS, processed: attempt }, }); } let { image: { url: image } } = results; return NextNode.from({ outputs: { image } }); } catch (e) { if (e instanceof ArtWorksError) { throw new FatalError(e.message); } throw e; } } } exctract_mask_on_image: _id: exctract_mask_on_image arrange: x: 900 y: 50 category: id: image_analysis title: en=Image analysis;ru=Анализ изображений environment: OPEN_PAAS_USER: title: PaaS user type: string scope: global OPEN_PAAS_PASSWORD: title: PaaS password type: string scope: global PAAS_BASE_URL: title: PaaS base url type: string scope: global inputs: image: order: 1 title: Image type: image required: true type: order: 2 title: Type type: string required: true default: yolo enum: - yolo|Yolo - default|Prompt prompt: order: 4 title: Prompt type: string required: false multiline: true model: order: 3 title: Yolo model type: string required: false default: deepfashion2_yolov8s-seg.pt enum: - deepfashion2_yolov8s-seg.pt - face_yolov8m.pt - face_yolov8n.pt - face_yolov8s.pt - female_breast_v3.2.pt - hand_yolov8n.pt - hand_yolov8s.pt - penisV2.pt - person_yolov8m-seg.pt - person_yolov8n-seg.pt - person_yolov8s-seg.pt - vagina-v2.6.pt threshold: order: 5 title: Threshold type: float required: true min: 0.1 max: 0.69 step: 0.1 default: 0.5 confidence: order: 6 title: Confidence type: float required: true min: 0.1 max: 0.99 step: 0.1 default: 0.5 applyConvexHull: order: 8 title: Apply convex hull type: boolean default: false outputs: merged: title: Merged type: image masks: title: Masks type: json schema: image-masks package: artworks script: |- const CHECK_TASK_INTERVAL = 3000; const MAX_ATTEMPTS = 20; export async function run({ inputs, state }) { const { FatalError, TimeoutError, RepeatNode, NextNode } = DEFINITIONS; const { ArtWorks, FatalError: ArtWorksError } = require('artworks'); const sharp = require('sharp/lib/index.js'); const PAAS_BASE_URL = env.variables.get('PAAS_BASE_URL'); if (!PAAS_BASE_URL) { throw new FatalError('Please, set PAAS_BASE_URL in environment'); } const OPEN_PAAS_USER = env.variables.get('OPEN_PAAS_USER'); if (!OPEN_PAAS_USER) { throw new FatalError('Please, set OPEN_PAAS_USER in environment'); } const OPEN_PAAS_PASSWORD = env.variables.get('OPEN_PAAS_PASSWORD'); if (!OPEN_PAAS_PASSWORD) { throw new FatalError('Please, set OPEN_PAAS_PASSWORD in environment'); } const artworks = new ArtWorks({ baseUrl: PAAS_BASE_URL, username: OPEN_PAAS_USER, password: OPEN_PAAS_PASSWORD }); if (!state) { const { image, type, model, prompt, threshold, applyConvexHull } = inputs; const payload = { type: "image-to-mask", isFast: true, payload: { base64: false, image, type, model, prompt, threshold, applyConvexHull, }, }; try { const task = await artworks.createTask(payload); console.log(`Task created ${task}`); return RepeatNode.from({ state: { payload, task, attempt: 0, startedAt: new Date() }, progress: { total: MAX_ATTEMPTS, processed: 0 }, delay: 5000 }); } catch (e) { if (e instanceof ArtWorksError) { throw new FatalError(e.message); } throw e; } } else { const { payload, task, attempt, startedAt } = state; if (attempt > MAX_ATTEMPTS) { try { await artworks.cancelTask(task); } catch (e) { } const now = new Date(); const time = (now - new Date(startedAt)) / 1000; throw new TimeoutError(`PaaS task for text to image ${task} timeout in ${time} sec`); } console.log(`Check task ${attempt} ${task}`); try { const results = await artworks.checkState(task); if (!results) { return RepeatNode.from({ delay: CHECK_TASK_INTERVAL, state: { payload, task, attempt: attempt + 1, startedAt, }, progress: { total: MAX_ATTEMPTS, processed: attempt }, }); } const { masks: detected } = results; const { image } = inputs; const { data } = await download(image); const { width, height } = await sharp(data).metadata(); const areas = []; const masks = []; for (const m of detected) { const { mask, confidence, className, coordinates: [left, top], } = m; const buffer = Buffer.from(mask, "base64"); areas.push({ input: buffer, top, left, }); const { width, height } = await sharp(buffer).metadata(); masks.push({ top, left, width, height, className, confidence, }); } let merged = await sharp({ create: { width, height, channels: 3, background: { r: 0, g: 0, b: 0 }, }, }).composite(areas); return NextNode.from({ outputs: { masks, merged: await merged.png().toBuffer() } }); } catch (e) { if (e instanceof ArtWorksError) { throw new FatalError(e.message); } throw e; } } } source: catalog title: en=Extract mask on image;ru=Выделить маску version: 1 classify_image: _id: classify_image arrange: x: 1080 y: 460 category: id: image_analysis title: en=Image analysis;ru=Анализ изображений environment: OPEN_PAAS_USER: title: PaaS user type: string scope: global OPEN_PAAS_PASSWORD: title: PaaS password type: string scope: global PAAS_BASE_URL: title: PaaS base url type: string scope: global inputs: image: order: 1 title: Image type: image required: true labels: order: 2 title: Labels type: json required: true default: '{ "girl": "girl on photo", "male": "male on photo" }' schema: id: image-labels outputs: labels: title: Labels type: json package: artworks script: |- const CHECK_TASK_INTERVAL = 1000; const MAX_ATTEMPTS = 20; export async function run({ inputs, state }) { const { FatalError, TimeoutError, RepeatNode, NextNode } = DEFINITIONS; const { ArtWorks, FatalError: ArtWorksError } = require('artworks'); const PAAS_BASE_URL = env.variables.get('PAAS_BASE_URL'); if (!PAAS_BASE_URL) { throw new FatalError('Please, set PAAS_BASE_URL in environment'); } const OPEN_PAAS_USER = env.variables.get('OPEN_PAAS_USER'); if (!OPEN_PAAS_USER) { throw new FatalError('Please, set OPEN_PAAS_USER in environment'); } const OPEN_PAAS_PASSWORD = env.variables.get('OPEN_PAAS_PASSWORD'); if (!OPEN_PAAS_PASSWORD) { throw new FatalError('Please, set OPEN_PAAS_PASSWORD in environment'); } const artworks = new ArtWorks({ baseUrl: PAAS_BASE_URL, username: OPEN_PAAS_USER, password: OPEN_PAAS_PASSWORD }); if (!state) { const { image, labels } = inputs; const payload = { type: "classify-image", isFast: true, payload: { base64: false, image, labels: Object.values(labels), }, }; try { const task = await artworks.createTask(payload); console.log(`Task created ${task}`); return RepeatNode.from({ state: { payload, task, attempt: 0, startedAt: new Date() }, progress: { total: MAX_ATTEMPTS, processed: 0 }, delay: 2000 }); } catch (e) { if (e instanceof ArtWorksError) { throw new FatalError(e.message); } throw e; } } else { const { payload, task, attempt, startedAt } = state; if (attempt > MAX_ATTEMPTS) { try { await artworks.cancelTask(task); } catch (e) { } const now = new Date(); const time = (now - new Date(startedAt)) / 1000; throw new TimeoutError(`PaaS task for text to image ${task} timeout in ${time} sec`); } console.log(`Check task ${attempt} ${task}`); try { const results = await artworks.checkState(task); if (!results) { return RepeatNode.from({ delay: CHECK_TASK_INTERVAL, state: { payload, task, attempt: attempt + 1, startedAt, }, progress: { total: MAX_ATTEMPTS, processed: attempt }, }); } let { probs } = results; const { labels } = inputs; const tags = {}; for (const key of Object.keys(labels)) { tags[key] = probs[labels[key]]; } return NextNode.from({ outputs: { labels: tags } }); } catch (e) { if (e instanceof ArtWorksError) { throw new FatalError(e.message); } throw e; } } } source: catalog title: en=Classify image;ru=Тегировать изображение version: 1 detect_face_on_image: _id: detect_face_on_image arrange: x: 900 y: 330 category: id: image_analysis title: en=Image analysis;ru=Анализ изображений environment: OPEN_PAAS_USER: title: PaaS user type: string scope: global OPEN_PAAS_PASSWORD: title: PaaS password type: string scope: global PAAS_BASE_URL: title: PaaS base url type: string scope: global inputs: image: order: 1 title: en=Image;ru=Изображение type: image required: true index: order: 2 title: en=Index;ru=Индекс type: integer required: true default: 0 outputs: face: title: en=Face;ru=Лицо type: image features: title: en=Features;ru=Характеристики type: json schema: face-features package: artworks script: | const CHECK_TASK_INTERVAL = 3000; const MAX_ATTEMPTS = 10; const FIT_FACE_SIZE = 512; export async function fit(image, { maxWidth, maxHeight }) { const { width, height } = await image.metadata(); const orientation = width >= height ? "-" : "|"; const sharp = require('sharp/lib/index.js'); switch (orientation) { case "-": if (width > maxWidth) { return sharp(await image.resize({ width: maxWidth }).toBuffer()); } break; case "|": if (height > maxHeight) { return sharp(await image.resize({ height: maxHeight }).toBuffer()); } break; } return image; } export async function crop(source, face) { const sharp = require('sharp/lib/index.js'); const image = await sharp(source); const metadata = await image.metadata(); const UNCROP = 0.6; let { x, y, width, height } = face; const uncropX = width * UNCROP; const uncropY = height * UNCROP; width = Math.round(width + uncropX); height = Math.round(height + uncropY); x = Math.round(x - uncropX / 2); y = Math.round(y - uncropY / 2); const [left, top] = [Math.max(x, 0), Math.max(y, 0)]; [width, height] = [ Math.min(width, metadata.width - left), Math.min(height, metadata.height - top), ]; const size = Math.min(width, height); const crop = { left, top, width: size, height: size, }; const area = await fit(await image.clone().extract(crop).webp(), { maxWidth: FIT_FACE_SIZE, maxHeight: FIT_FACE_SIZE, }); return area.toBuffer(); } export async function run({ inputs, state }) { const { FatalError, TimeoutError, RepeatNode, NextNode } = DEFINITIONS; const { ArtWorks, FatalError: ArtWorksError } = require('artworks'); const PAAS_BASE_URL = env.variables.get('PAAS_BASE_URL'); if (!PAAS_BASE_URL) { throw new FatalError('Please, set PAAS_BASE_URL in environment'); } const OPEN_PAAS_USER = env.variables.get('OPEN_PAAS_USER'); if (!OPEN_PAAS_USER) { throw new FatalError('Please, set OPEN_PAAS_USER in environment'); } const OPEN_PAAS_PASSWORD = env.variables.get('OPEN_PAAS_PASSWORD'); if (!OPEN_PAAS_PASSWORD) { throw new FatalError('Please, set OPEN_PAAS_PASSWORD in environment'); } const artworks = new ArtWorks({ baseUrl: PAAS_BASE_URL, username: OPEN_PAAS_USER, password: OPEN_PAAS_PASSWORD }); if (!state) { const { image, index } = inputs; const payload = { type: "detect-faces", isFast: true, payload: { base64: false, image, features: ["age", "gender", "race", "emotion"], }, }; try { const task = await artworks.createTask(payload); console.log(`Task created ${task}`); return RepeatNode.from({ state: { payload, task, attempt: 0, startedAt: new Date() }, progress: { total: MAX_ATTEMPTS, processed: 0 }, delay: 2000 }); } catch (e) { if (e instanceof ArtWorksError) { throw new FatalError(e.message); } throw e; } } else { const { payload, task, attempt, startedAt } = state; if (attempt > MAX_ATTEMPTS) { try { await artworks.cancelTask(task); } catch (e) { } const now = new Date(); const time = (now - new Date(startedAt)) / 1000; throw new TimeoutError(`PaaS task for text to image ${task} timeout in ${time} sec`); } console.log(`Check task ${attempt} ${task}`); try { const results = await artworks.checkState(task); if (!results) { return RepeatNode.from({ delay: CHECK_TASK_INTERVAL, state: { payload, task, attempt: attempt + 1, startedAt, }, progress: { total: MAX_ATTEMPTS, processed: attempt }, }); } const { faces } = results; const { image, index } = inputs; const face = faces[index]; if (!face) { throw new FatalError("Face with such index was not found"); } const { x, y, width, height, ageFrom, ageTo, gender, race, emotion } = face; const { data } = await download(image); return NextNode.from({ outputs: { face: await crop(data, { x, y, width, height, }), features: { ageFrom, ageTo, gender, race, emotion, }, }, }); } catch (e) { if (e instanceof ArtWorksError) { throw new FatalError(e.message); } throw e; } } } source: catalog title: en=Detect face;ru=Определить лицо version: 1 remove_background: _id: remove_background arrange: x: 750 y: 630 category: id: image_processing title: en=Work with images;ru=Работа с изображениями environment: OPEN_PAAS_USER: title: PaaS user type: string scope: global OPEN_PAAS_PASSWORD: title: PaaS password type: string scope: global PAAS_BASE_URL: title: PaaS base url type: string scope: global inputs: image: order: 1 title: en=Image;ru=Изображение type: image required: true model: order: 2 title: en=Model;ru=Модель type: string required: true default: isnet-general-use enum: - isnet-general-use|IsNet - u2net|U2Net outputs: image: title: en=Image;ru=Изображение type: image package: artworks script: |- const CHECK_TASK_INTERVAL = 3000; const MAX_ATTEMPTS = 20; export async function run({ inputs, state }) { const { FatalError, TimeoutError, RepeatNode, NextNode } = DEFINITIONS; const { ArtWorks, FatalError: ArtWorksError } = require('artworks'); const PAAS_BASE_URL = env.variables.get('PAAS_BASE_URL'); if (!PAAS_BASE_URL) { throw new FatalError('Please, set PAAS_BASE_URL in environment'); } const OPEN_PAAS_USER = env.variables.get('OPEN_PAAS_USER'); if (!OPEN_PAAS_USER) { throw new FatalError('Please, set OPEN_PAAS_USER in environment'); } const OPEN_PAAS_PASSWORD = env.variables.get('OPEN_PAAS_PASSWORD'); if (!OPEN_PAAS_PASSWORD) { throw new FatalError('Please, set OPEN_PAAS_PASSWORD in environment'); } const artworks = new ArtWorks({ baseUrl: PAAS_BASE_URL, username: OPEN_PAAS_USER, password: OPEN_PAAS_PASSWORD }); if (!state) { const { image, model, } = inputs; const payload = { type: "remove-image-background", isFast: true, payload: { base64: false, model, image, }, }; try { const task = await artworks.createTask(payload); console.log(`Task created ${task}`); return RepeatNode.from({ state: { payload, task, attempt: 0, startedAt: new Date() }, progress: { total: MAX_ATTEMPTS, processed: 0 }, delay: 5000 }); } catch (e) { if (e instanceof ArtWorksError) { throw new FatalError(e.message); } throw e; } } else { const { payload, task, attempt, startedAt } = state; if (attempt > MAX_ATTEMPTS) { try { await artworks.cancelTask(task); } catch (e) { } const now = new Date(); const time = (now - new Date(startedAt)) / 1000; throw new TimeoutError(`PaaS task for text to image ${task} timeout in ${time} sec`); } console.log(`Check task ${attempt} ${task}`); try { const results = await artworks.checkState(task); if (!results) { return RepeatNode.from({ delay: CHECK_TASK_INTERVAL, state: { payload, task, attempt: attempt + 1, startedAt, }, progress: { total: MAX_ATTEMPTS, processed: attempt }, }); } let { image: { url: image } } = results; return NextNode.from({ outputs: { image } }); } catch (e) { if (e instanceof ArtWorksError) { throw new FatalError(e.message); } throw e; } } } source: catalog title: en=Remove background;ru=Удалить фон version: 1