llama vision | stable diffusion request | inpaint mask | Search

The doBackgroundMask function is an asynchronous process that takes an image, extracts its base64 representation, applies a background mask using the rembg API, and writes the masked image to a file. It involves file system operations, image processing, and HTTP requests to the rembg API.

Run example

npm run import -- "mask image"

mask image

const fs = require('fs')
const path = require('path')
const {request} = require('gaxios')
var crypto = require('crypto')
const sharp = require('sharp')

const OUTPUT_PATH = path.join(process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE, 'stable-diffusion-webui/outputs')

async function doBackgroundMask(image) {

  let base64_image
  if(typeof image == 'string') {
    if(image.startsWith('data:image/'))
      image = image.replace(/^data:image\/.*?;base64,/gi, '')
  
    if(image.includes('://')) {
      let result = await request({
        url: image,
        method: 'GET',
      })
      base64_image = Buffer.from(await result.data.arrayBuffer()).toString('base64')
    } else if (!fs.existsSync(image)) {
      base64_image = Buffer.from(image, 'base64').toString('base64')
    } else {
      base64_image = fs.readFileSync(image).toString('base64')
    }  
  } else {
    base64_image = image.toString('base64')
  }

  try {
    let result = await request({
      url: 'http://127.0.0.1:7860/rembg',
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      data: JSON.stringify({
        input_image: base64_image,
        model: 'u2net',
        return_mask: true,
        //"alpha_matting": false,
        //"alpha_matting_foreground_threshold": 240,
        //"alpha_matting_background_threshold": 10,
        //"alpha_matting_erode_size": 10
      })
    })
    let buff = Buffer.from(result.data.image, 'base64')
    let seed = parseInt(crypto.randomBytes(8).toString('hex'), 16).toString()
    let now = new Date()
    let folderName = now.getFullYear() + '-' + String(now.getMonth() + 1).padStart(2, '0') + '-' + String(now.getDate()).padStart(2, '0')
    let stablePath = path.join(OUTPUT_PATH, 'extras-images', folderName)
    if(!fs.existsSync(stablePath)) {
      fs.mkdirSync(stablePath)
    }
    let highestCount = 0
    let images = fs.readdirSync(stablePath)
    for(let i = 0; i < images.length; i++) {
      let index = parseInt(images[i].split(/[\.-]/gi)[0])
      if(!isNaN(index) && index > highestCount) {
        highestCount = index
      }
    }
    let imagePath = path.join('extras-images', folderName, String(highestCount).padStart(5, '0') + '-' + seed + '.png')
    fs.writeFileSync(path.join(OUTPUT_PATH, imagePath), buff)
    let imageObj = await sharp(buff)
    await imageObj.negate().toFile(path.join(OUTPUT_PATH, 'extras-images', folderName, String(highestCount).padStart(5, '0') + '-' + seed + '-negative.png'))
    return {seed, image: buff, imagePath}
  } catch (e) {
    console.error(e)
  }
}

module.exports = {
  doBackgroundMask,
  OUTPUT_PATH
}

What the code could have been:

const fs = require('fs');
const path = require('path');
const axios = require('axios');
const crypto = require('crypto');
const sharp = require('sharp');

const DEFAULT_OUTPUT_PATH = path.join(process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE,'stable-diffusion-webui/outputs');

class BackgroundMaskService {
  /**
   * The path where the output images will be saved.
   * @type {string}
   */
  static get OUTPUT_PATH() {
    return process.env.OUTPUT_PATH || DEFAULT_OUTPUT_PATH;
  }

  /**
   * Creates a background mask image from the given image.
   * @param {Buffer|string} image - The image to apply the background mask to.
   * @returns {Promise<{seed: string, image: Buffer, imagePath: string}>} - The created image with a generated seed and its path.
   */
  static async doBackgroundMask(image) {
    try {
      const { base64Data, filePath } = await BackgroundMaskService.processImage(image);

      const response = await axios.post('http://127.0.0.1:7860/rembg', {
        input_image: base64Data,
        model: 'u2net',
        return_mask: true,
      }, {
        headers: {
          'Content-Type': 'application/json',
        },
      });

      const buff = Buffer.from(response.data.image, 'base64');
      const seed = crypto.randomBytes(8).toString('hex');
      const now = new Date();
      const folderName = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;

      const stablePath = path.join(BackgroundMaskService.OUTPUT_PATH, 'extras-images', folderName);
      if (!fs.existsSync(stablePath)) {
        fs.mkdirSync(stablePath);
      }

      const images = fs.readdirSync(stablePath);
      let highestCount = 0;
      for (let i = 0; i < images.length; i++) {
        const index = parseInt(images[i].split(/[\.-]/gi)[0]);
        if (!isNaN(index) && index > highestCount) {
          highestCount = index;
        }
      }

      const imagePath = path.join('extras-images', folderName, String(highestCount).padStart(5, '0') + '-' + seed + '.png');
      fs.writeFileSync(path.join(BackgroundMaskService.OUTPUT_PATH, imagePath), buff);

      const imageObj = await sharp(buff);
      await imageObj.negate().toFile(path.join(BackgroundMaskService.OUTPUT_PATH, 'extras-images', folderName, String(highestCount).padStart(5, '0') + '-' + seed + '-negative.png'));

      return { seed, image: buff, imagePath };
    } catch (error) {
      console.error(error);
      throw error;
    }
  }

  static async processImage(image) {
    if (typeof image ==='string') {
      if (image.startsWith('data:image/')) {
        image = image.replace(/^data:image\/.*?;base64,/gi, '');
      }

      if (image.includes('://')) {
        const response = await axios.get(image);
        return { base64Data: Buffer.from(await response.data.arrayBuffer()).toString('base64'), filePath: null };
      } else if (!fs.existsSync(image)) {
        throw new Error(`The file ${image} does not exist.`);
      } else {
        return { base64Data: fs.readFileSync(image).toString('base64'), filePath: image };
      }
    } else {
      return { base64Data: image.toString('base64'), filePath: null };
    }
  }
}

module.exports = BackgroundMaskService;

Code Breakdown

Imported Modules

Constants

Function: doBackgroundMask

Image Processing

Background Masking

File System Operations

Notes