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.
npm run import -- "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
}
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;
fs
: File system module for interacting with the file system.path
: Path module for working with file paths.gaxios
: A Google-like HTTP client for making HTTP requests.crypto
: Cryptography module for generating random seeds.sharp
: A high-performance image processing library.OUTPUT_PATH
: A constant representing the output directory path for generated images.doBackgroundMask
image
parameter.rembg
API.image
parameter is a string, it checks if it's a base64-encoded image.rembg
API with the base64-encoded image, specifying the u2net
model and requesting a mask.rembg
API is running on http://127.0.0.1:7860/rembg
.sharp
library to process the images, but it's not clear how the library is being used.