Get it on Google Play
Tu partner Freelance para tus proyectos IT

Replica de Remove.bg con Python y NodeJS

06-11-2020
Imagen removebg

Imagen removebg

Empezamos serie de vídeos dedicada a crear réplicas de servicios que ya existen ahora mismo funcionando en Internet. En este primer vídeo le ha tocado a Remove.bg, un servicio que nos permite quitar el fondo a las imágenes de nuestras fotos con inteligencia artificial.

Nosotros vamos a poner a funcionar el servicio sobre un servidor Linux/Ubuntu, usando la librería de Python ‘rembg’ que podemos usar en línea de comandos y crearemos el servicio usando Javascript con NodeJS. Una solución simple para crear un servicio como este.

Instalar dependencias del SSOO

Para el proyecto necesitamos solamente tres dependencias(En el vídeo yo acabo instalando una cuarta dependencia que es nano, el editor de textos que uso habitualmente). Las tres dependencias son pip(Gestor de paquestes de python), nodejs y npm(Gestor de paquetes de nodejs):

apt update && apt install -y python3-pip nodejs npm

Instalar la librería de python rembg

Después instalamos la librería de python ‘rembg’ usando el gestor de paquetes pip:

pip3 install rembg

Esta librería de python tiene varias maneras de ejecutarla en línea de comandos, nosotros usaremos la siguiente donde solo le pasaremos por la entrada estándar la imagen de entrada y redireccionaremos la salida al fichero donde queramos que se guarde la salida. Por ejemplo, si tenemos ‘imagen1.jpg’ como imagen a la que queremos quitarle el fondo y queremos que nos ponga la imagen resultante en ‘out.png’ quedaria así:

rembg < imagen1.jpg > out.png

La primera vez siempre tarda mas porque se tiene que descargar los dos modelos de IA que va a utilizar.

Creación del servicio con NodeJS y Javascript

Como siempre empezaremos el proyecto en una carpeta nueva e instalando las dependencias. Para este proyecto solo necesitaremos tres dependencias:

# Inicializar proyecto
npm init

# Instalar dependencias
npm install express body-parser fs-extra

Ahora ya solo nos codificar el proyecto. En nuestro caso, el proyecto tendrá solo tres ficheros, el primero será el backend en el fichero ‘index.js’:

/* Dependencias */
const express = require('express');
const bodyParser = require('body-parser');
const exec = require('child_process').execSync;
const fs = require('fs');

/* Inicializamos aplicación Express */
const app = express();
app.use( express.static('public') );
app.use( bodyParser.urlencoded({ limit: '50mb', extended: true }) );

/* Declaramos API */
app.post('/removebg', function (req, res) {
	/* Leemos fichero y lo guardamos en disco */
	var filename=req.body.filename;
	var content=req.body.content;

	var buff = new Buffer(content, 'base64');
	fs.writeFileSync(filename, buff );

	/* Ejecutamos librería para quitar el fondo */
	result=exec("rembg < "+filename+" > out.png");

	/* Leemos el fichero resultante y lo devolvemos a la web */
	var foto = fs.readFileSync('out.png');
	buff=new Buffer(foto);

           res.end( buff.toString('base64') );
	});

/* Arrancamos el servidor web */
app.listen(3000, function () {
    console.log('Sistema armado en el puerto 3000!');
    });

El siguiente fichero será la hoja de estilos que estará en ‘public/main.css’

body {
	padding: 0px;
	margin: 0px;
	color: #454545;
	}

h1 {
	text-align: center;
	background-image: linear-gradient(to bottom, #ccc , #fff);
	padding: 30px;
	font-weight: bold;
	font-family: sans;
	font-size: 46px;
	}

#file-wrapper {
	text-align: center;
	padding-bottom: 60px;
	}

#main-wrapper {
	text-align: center;
	display: none;
	}

#main-wrapper #drop1, #main-wrapper #img1 {
	display: inline-block;
	width: 44%;
	max-width: 400px; 
	height: 400px;
	background-position: center center;
	background-size: contain;
	background-repeat: no-repeat;
	vertical-align: middle;
	border: 1px dotted #ccc;
	}

#loading {
	margin: calc( 50% - 30px );
	font-size: 42px;
	-webkit-animation:spin 4s linear infinite;
	-moz-animation:spin 4s linear infinite;
	animation:spin 4s linear infinite;
	}

@-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } }
@-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } }
@keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }

Y finalmente el frontend en HTML vainilla que lee la imagen, la envia al backend y la muestra:

<html>
	<head>
		<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous"/>
		<link rel='stylesheet' href='/main.css' type='text/css' media='all' />
	</head>
	<body>
		<h1>Background Remover</h1>
		<div id='file-wrapper'>
			<input id='file' type='file' onchange="javascript: changeFile();"/>
		</div>
		<div id='main-wrapper'>
			<div id='drop1'></div>
			&nbsp;
			<div id='img1'></div>
		</div>

		<script>
			function changeFile() {
				var f=document.getElementById('file');
				var c1=document.getElementById('drop1');
				var c2=document.getElementById('img1');
				var mw=document.getElementById('main-wrapper');

				mw.style.display='none';
				c1.style.backgroundImage='';
				c1.innerHTML='';

				var reader = new FileReader();
			 
				reader.onloadend = function(evt) { 
				    if (f.files[0].type.indexOf("image/")!=-1) {
					c1.style.backgroundImage='url("'+evt.target.result+'")';
					c2.style.backgroundImage='';
					c2.innerHTML='<i id="loading" class="fas fa-hourglass-half"></i>';
					mw.style.display='block';

					var base64="";
					base64=evt.target.result.substring( evt.target.result.indexOf(",")+1 );

					var post="";
					post+="filename="+encodeURIComponent(f.files[0].name);
					post+="&content="+encodeURIComponent( base64 );

					fetch( "/removebg", {
		  				method: 'POST', 
		  				body: post,
						headers: {
							'Content-Type': 'application/x-www-form-urlencoded'
							}
						} ).then(function(response) {
							response.text().then(function(p) {
								c2.style.backgroundImage='url("data:image/jpeg;base64,'+p+'")';
								c2.innerHTML='';
								});
	    						});	

					} else { 
					alert("Formato no válido!");
				    	}
				    }; 
			     
				/* Leemos el fichero como una URL de datos(Base64) */
				reader.readAsDataURL( f.files[0] );
				}

		</script>
	</body>
</html>

Un proyecto super pequeño pero super potente, que ya está dando beneficios en Internet y que se puede implementar usando un puñado de librerías Open Source. Espero que lo disfruteis.

Si te ha servido, por favor comparte
 

Leave a Reply