| _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 <SDXL> |
| - aamXLAnimeMix_v10.safetensors|AAM XL (Anime Mix) <SDXL> <Fantasy> |
| - dreamweaverPony25D.1erv.safetensors|DreamWeaver - Pony 2.5D Mix <SDXL> |
| - mixGEMAdam8witQegoow.NeWz.safetensors|MyMIX-G/Jem <SDXL> <Realistic> |
| - mfcgPDXL_v10.safetensors|MFCG PDXL <SDXL> |
| - aniku_0.2.fp16.safetensors|Anime Desire <SDXL> <Fantasy> |
| - flux1DevHyperNF4Flux1DevBNB_flux1DevHyperNF4.safetensors|Hyper NF4 Flux 1 <Flux> |
| - STOIQONewrealityFLUXSD_F1DPreAlpha.safetensors|New Reality Flux <Flux> |
| - juggernautXL_v9Rundiffusionphoto2.safetensors|Juggernaut XL <SDXL> |
| - animaPencilXL_v260.safetensors|Anima Pencil XL <SDXL> <Fantasy> |
| - bluePencilXL_v401.safetensors|Blue Pencil XL <SDXL> <Fantasy> |
| - pixelArtDiffusionXL_spriteShaper.safetensors|Pixel Art Diffusion XL <SDXL> <Fantasy> |
| - albedobaseXL_v20.safetensors|AlbedoBase XL <SDXL> |
| - leosamsHelloworldXL_helloworldXL50GPT4V.safetensors|Helloworld XL <SDXL> |
| - dynavisionXLAllInOneStylized_releaseV0610Bakedvae.safetensors|DynaVision XL All In One <SDXL> |
| - photon_v1.safetensors|Photon <SD 1.5> |
| - afroditexlNudePeople_20Bkdvae.safetensors|Nude People <NSFW> |
| - nosft-float8-e4m3fn.safetensors|Flux Nude People <NSFW> |
| - asdf_0.4a_lorapov_0.2_lust_0.4.fp16.safetensors|Real Porn <NSFW> |
| - Sexy_Aesthetic_SDXL_0.4x0.2.fp16.safetensors|Sexy & Beauty <NSFW> |
| - aniku_0.2.fp16.safetensors|Anime Desire <NSFW> |
| - anikurender_0.4b.fp16.safetensors|Hardcore Fantasy <NSFW> |
| 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 |
|
|