CentOS 7: how to install U^2-Net HTTP server


U^2-Net HTTP is an HTTP service wrapper of the model: U^2-Net: Going Deeper with Nested U-Structure for Salient Object Detection (Qin et al, Pattern Recognition 2020)

Requirements:
Python >=3.6 (CentOS 7: install python36 and python36-pip)

Step 1:

cd ~/photoshop
git clone https://github.com/cyrildiagne/u2net-http.git

Result:

[root@s126368 photoshop]# git clone https://github.com/cyrildiagne/u2net-http.git
Cloning into 'u2net-http'...
remote: Enumerating objects: 23, done.
remote: Counting objects: 100% (23/23), done.
remote: Compressing objects: 100% (22/22), done.
remote: Total 23 (delta 6), reused 13 (delta 0), pack-reused 0
Unpacking objects: 100% (23/23), done.

Step 2:

cd u2net-http
git clone https://github.com/NathanUA/U-2-Net.git
[root@s126368 u2net-http]# git clone https://github.com/NathanUA/U-2-Net.git
Cloning into 'U-2-Net'...
remote: Enumerating objects: 247, done.
remote: Total 247 (delta 0), reused 0 (delta 0), pack-reused 247
Receiving objects: 100% (247/247), 8.26 MiB | 8.98 MiB/s, done.
Resolving deltas: 100% (101/101), done.

Step 3:
Step 3a:: Case 1: use u2net.pth, download this file to /home/tutorialspots/Downloads/

mkdir U-2-Net/saved_models
mkdir U-2-Net/saved_models/u2net
cp /home/tutorialspots/Downloads/u2net.pth U-2-Net/saved_models/u2net

Step 3b:: Case 2: use u2netp.pth, download this file to /home/tutorialspots/Downloads/

mkdir U-2-Net/saved_models
mkdir U-2-Net/saved_models/u2netp
cp /home/tutorialspots/Downloads/u2netp.pth U-2-Net/saved_models/u2netp

Step 4 (optinal): Fix for non CUDA device:
Error we got when ran python3 main.py:

RuntimeError: Attempting to deserialize object on a CUDA device but torch.cuda.is_available() is False. If you are running on a CPU-only machine, please use torch.load with map_location='cpu' to map your storages to the CPU.

Edit file u2net.py

Change lines:

net.load_state_dict(torch.load(model_dir))
if torch.cuda.is_available():
    net.cuda()

to:

if torch.cuda.is_available():
    net.load_state_dict(torch.load(model_dir))
    net.cuda()
else:
    net.load_state_dict(torch.load(model_dir,map_location='cpu'))

Step 5 (Optinal): only for Case 2 (Step 3b)

Edit file u2net.py

Line 22:

# from model import U2NETP # small version u2net 4.7 MB

to

from model import U2NETP # small version u2net 4.7 MB

Line 24:

model_dir = './U-2-Net/saved_models/u2net/u2net.pth'

to:

model_dir = './U-2-Net/saved_models/u2netp/u2netp.pth'

Line 27:

net = U2NET(3, 1)

to:

net = U2NETP(3, 1)

Step 6:

pip3 install torch==0.4.1

Result:

[root@s126368 u2net-http]# pip3 install torch==0.4.1
WARNING: Running pip install with root privileges is generally not a good idea. Try `pip3 install --user` instead.
Collecting torch==0.4.1
  Using cached https://files.pythonhosted.org/packages/49/0e/e382bcf1a6ae8225f50b99cc26effa2d4cc6d66975ccf3fa9590efcbedce/torch-0.4.1-cp36-cp36m-manylinux1_x86_64.whl
Installing collected packages: torch
Successfully installed torch-0.4.1

Step 7:

pip3 install -r requirements.txt

Result:

[root@s126368 u2net-http]# pip3 install -r requirements.txt
WARNING: Running pip install with root privileges is generally not a good idea. Try `pip3 install --user` instead.
Collecting Flask==1.1.1 (from -r requirements.txt (line 1))
  Using cached https://files.pythonhosted.org/packages/9b/93/628509b8d5dc749656a9641f4caf13540e2cdec85276964ff8f43bbb1d3b/Flask-1.1.1-py2.py3-none-any.whl
Collecting flask-cors==3.0.8 (from -r requirements.txt (line 2))
  Using cached https://files.pythonhosted.org/packages/78/38/e68b11daa5d613e3a91e4bf3da76c94ac9ee0d9cd515af9c1ab80d36f709/Flask_Cors-3.0.8-py2.py3-none-any.whl
Collecting gunicorn==19.9.0 (from -r requirements.txt (line 3))
  Using cached https://files.pythonhosted.org/packages/8c/da/b8dd8deb741bff556db53902d4706774c8e1e67265f69528c14c003644e6/gunicorn-19.9.0-py2.py3-none-any.whl
Collecting numpy==1.15.2 (from -r requirements.txt (line 4))
  Using cached https://files.pythonhosted.org/packages/22/02/bae88c4aaea4256d890adbf3f7cf33e59a443f9985cf91cd08a35656676a/numpy-1.15.2-cp36-cp36m-manylinux1_x86_64.whl
Collecting scikit-image==0.14.0 (from -r requirements.txt (line 5))
  Using cached https://files.pythonhosted.org/packages/34/79/cefff573a53ca3fb4c390739d19541b95f371e24d2990aed4cd8837971f0/scikit_image-0.14.0-cp36-cp36m-manylinux1_x86_64.whl
Collecting Pillow==6.2.2 (from -r requirements.txt (line 6))
  Using cached https://files.pythonhosted.org/packages/8a/fd/bbbc569f98f47813c50a116b539d97b3b17a86ac7a309f83b2022d26caf2/Pillow-6.2.2-cp36-cp36m-manylinux1_x86_64.whl
Collecting torchvision==0.2.1 (from -r requirements.txt (line 7))
  Using cached https://files.pythonhosted.org/packages/ca/0d/f00b2885711e08bd71242ebe7b96561e6f6d01fdb4b9dcf4d37e2e13c5e1/torchvision-0.2.1-py2.py3-none-any.whl
Collecting itsdangerous>=0.24 (from Flask==1.1.1->-r requirements.txt (line 1))
  Using cached https://files.pythonhosted.org/packages/76/ae/44b03b253d6fade317f32c24d100b3b35c2239807046a4c953c7b89fa49e/itsdangerous-1.1.0-py2.py3-none-any.whl
Requirement already satisfied: Jinja2>=2.10.1 in /usr/local/lib64/python3.6/site-packages (from Flask==1.1.1->-r requirements.txt (line 1))
Collecting Werkzeug>=0.15 (from Flask==1.1.1->-r requirements.txt (line 1))
  Using cached https://files.pythonhosted.org/packages/cc/94/5f7079a0e00bd6863ef8f1da638721e9da21e5bacee597595b318f71d62e/Werkzeug-1.0.1-py2.py3-none-any.whl
Collecting click>=5.1 (from Flask==1.1.1->-r requirements.txt (line 1))
  Using cached https://files.pythonhosted.org/packages/d2/3d/fa76db83bf75c4f8d338c2fd15c8d33fdd7ad23a9b5e57eb6c5de26b430e/click-7.1.2-py2.py3-none-any.whl
Requirement already satisfied: Six in /usr/local/lib/python3.6/site-packages (from flask-cors==3.0.8->-r requirements.txt (line 2))
Collecting scipy>=0.17.0 (from scikit-image==0.14.0->-r requirements.txt (line 5))
  Using cached https://files.pythonhosted.org/packages/2b/a8/f4c66eb529bb252d50e83dbf2909c6502e2f857550f22571ed8556f62d95/scipy-1.5.2-cp36-cp36m-manylinux1_x86_64.whl
Collecting PyWavelets>=0.4.0 (from scikit-image==0.14.0->-r requirements.txt (line 5))
  Using cached https://files.pythonhosted.org/packages/59/bb/d2b85265ec9fa3c1922210c9393d4cdf7075cc87cce6fe671d7455f80fbc/PyWavelets-1.1.1-cp36-cp36m-manylinux1_x86_64.whl
Collecting matplotlib>=2.0.0 (from scikit-image==0.14.0->-r requirements.txt (line 5))
  Using cached https://files.pythonhosted.org/packages/96/a7/b6fa244fd8a8814ef9408c8a5a7e4ed0340e232a6f0ce2046b42e50672c0/matplotlib-3.3.1-cp36-cp36m-manylinux1_x86_64.whl
Collecting cloudpickle>=0.2.1 (from scikit-image==0.14.0->-r requirements.txt (line 5))
  Using cached https://files.pythonhosted.org/packages/8f/d7/bdb029d3de92c165afe6cdc69a2d01e26189b3bad64a1edf6ef5a5f11d1a/cloudpickle-1.5.0-py3-none-any.whl
Collecting dask[array]>=0.9.0 (from scikit-image==0.14.0->-r requirements.txt (line 5))
  Using cached https://files.pythonhosted.org/packages/aa/be/1221750e57f15183c5c179e5f7dda6bae39d7f177dcc7b59ed6a42eeeebf/dask-2.24.0-py3-none-any.whl
Collecting networkx>=1.8 (from scikit-image==0.14.0->-r requirements.txt (line 5))
  Using cached https://files.pythonhosted.org/packages/9b/cd/dc52755d30ba41c60243235460961fc28022e5b6731f16c268667625baea/networkx-2.5-py3-none-any.whl
Requirement already satisfied: torch in /usr/local/lib64/python3.6/site-packages (from torchvision==0.2.1->-r requirements.txt (line 7))
Requirement already satisfied: MarkupSafe>=0.23 in /usr/local/lib64/python3.6/site-packages (from Jinja2>=2.10.1->Flask==1.1.1->-r requirements.txt (line 1))
Collecting cycler>=0.10 (from matplotlib>=2.0.0->scikit-image==0.14.0->-r requirements.txt (line 5))
  Downloading https://files.pythonhosted.org/packages/f7/d2/e07d3ebb2bd7af696440ce7e754c59dd546ffe1bbe732c8ab68b9c834e61/cycler-0.10.0-py2.py3-none-any.whl
Collecting kiwisolver>=1.0.1 (from matplotlib>=2.0.0->scikit-image==0.14.0->-r requirements.txt (line 5))
  Downloading https://files.pythonhosted.org/packages/ae/23/147de658aabbf968324551ea22c0c13a00284c4ef49a77002e91f79657b7/kiwisolver-1.2.0-cp36-cp36m-manylinux1_x86_64.whl (88kB)
    100% |████████████████████████████████| 92kB 6.5MB/s
Collecting certifi>=2020.06.20 (from matplotlib>=2.0.0->scikit-image==0.14.0->-r requirements.txt (line 5))
  Downloading https://files.pythonhosted.org/packages/5e/c4/6c4fe722df5343c33226f0b4e0bb042e4dc13483228b4718baf286f86d87/certifi-2020.6.20-py2.py3-none-any.whl (156kB)
    100% |████████████████████████████████| 163kB 1.7MB/s
Collecting pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.3 (from matplotlib>=2.0.0->scikit-image==0.14.0->-r requirements.txt (line 5))
  Downloading https://files.pythonhosted.org/packages/8a/bb/488841f56197b13700afd5658fc279a2025a39e22449b7cf29864669b15d/pyparsing-2.4.7-py2.py3-none-any.whl (67kB)
    100% |████████████████████████████████| 71kB 6.7MB/s
Collecting python-dateutil>=2.1 (from matplotlib>=2.0.0->scikit-image==0.14.0->-r requirements.txt (line 5))
  Downloading https://files.pythonhosted.org/packages/d4/70/d60450c3dd48ef87586924207ae8907090de0b306af2bce5d134d78615cb/python_dateutil-2.8.1-py2.py3-none-any.whl (227kB)
    100% |████████████████████████████████| 235kB 4.1MB/s
Collecting pyyaml (from dask[array]>=0.9.0->scikit-image==0.14.0->-r requirements.txt (line 5))
  Downloading https://files.pythonhosted.org/packages/64/c2/b80047c7ac2478f9501676c988a5411ed5572f35d1beff9cae07d321512c/PyYAML-5.3.1.tar.gz (269kB)
    100% |████████████████████████████████| 276kB 3.6MB/s
Collecting toolz>=0.8.2; extra == "array" (from dask[array]>=0.9.0->scikit-image==0.14.0->-r requirements.txt (line 5))
  Downloading https://files.pythonhosted.org/packages/22/8e/037b9ba5c6a5739ef0dcde60578c64d49f45f64c5e5e886531bfbc39157f/toolz-0.10.0.tar.gz (49kB)
    100% |████████████████████████████████| 51kB 6.7MB/s
Collecting decorator>=4.3.0 (from networkx>=1.8->scikit-image==0.14.0->-r requirements.txt (line 5))
  Downloading https://files.pythonhosted.org/packages/ed/1b/72a1821152d07cf1d8b6fce298aeb06a7eb90f4d6d41acec9861e7cc6df0/decorator-4.4.2-py2.py3-none-any.whl
Installing collected packages: itsdangerous, Werkzeug, click, Flask, flask-cors, gunicorn, numpy, Pillow, scipy, PyWavelets, cycler, kiwisolver, certifi, pyparsing, python-dateutil, matplotlib, cloudpickle, pyyaml, toolz, dask, decorator, networkx, scikit-image, torchvision
  Found existing installation: numpy 1.19.1
    Uninstalling numpy-1.19.1:
      Successfully uninstalled numpy-1.19.1
  Found existing installation: Pillow 7.2.0
    Uninstalling Pillow-7.2.0:
      Successfully uninstalled Pillow-7.2.0
  Running setup.py install for pyyaml ... done
  Running setup.py install for toolz ... done
Successfully installed Flask-1.1.1 Pillow-6.2.2 PyWavelets-1.1.1 Werkzeug-1.0.1 certifi-2020.6.20 click-7.1.2 cloudpickle-1.5.0 cycler-0.10.0 dask-2.24.0 decorator-4.4.2 flask-cors-3.0.8 gunicorn-19.9.0 itsdangerous-1.1.0 kiwisolver-1.2.0 matplotlib-3.3.1 networkx-2.5 numpy-1.15.2 pyparsing-2.4.7 python-dateutil-2.8.1 pyyaml-5.3.1 scikit-image-0.14.0 scipy-1.5.2 toolz-0.10.0 torchvision-0.2.1

Step 8: Run server

[root@s126368 u2net-http]# python3 main.py
Loading U-2-Net...
 * Serving Flask app "main" (lazy loading)
 * Environment: development
 * Debug mode: on
INFO:werkzeug: * Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)
INFO:werkzeug: * Restarting with stat
Loading U-2-Net...
WARNING:werkzeug: * Debugger is active!
INFO:werkzeug: * Debugger PIN: 286-791-475

For production, we can use a service:
Create file /etc/systemd/system/my-python-daemon-3.service

vi /etc/systemd/system/my-python-daemon-3.service

Content:

[Unit]
Description=My Python App 3
 
[Service]
Type=simple
Environment="PORT=8080"
WorkingDirectory=/root/photoshop/u2net-http
ExecStart=/usr/bin/python3 main.py
Restart=always
# Restart service after 10 seconds if python service crashes
RestartSec=10
 
[Install]
WantedBy=multi-user.target

Start service:

systemctl enable my-python-daemon-3
systemctl start my-python-daemon-3

Leave a Reply