diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 8995b7e8..bfcd9587 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -3,8 +3,7 @@ name: Bug report about: Create a report to help us improve title: "[BUG] ..." labels: bug -assignees: '' - +assignees: "" --- **Describe the bug** @@ -12,6 +11,7 @@ A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: + 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 6d01b8b2..7443d876 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -3,8 +3,7 @@ name: Feature request about: Suggest an idea for this project title: "[FEATURE] ..." labels: enhancement -assignees: '' - +assignees: "" --- **Is your feature request related to a problem? Please describe.** diff --git a/.github/workflows/close_inactive_issues.yml b/.github/workflows/close_inactive_issues.yml index 4d02a47b..df118003 100644 --- a/.github/workflows/close_inactive_issues.yml +++ b/.github/workflows/close_inactive_issues.yml @@ -1,23 +1,23 @@ name: Close inactive issues on: - schedule: - - cron: "30 1 * * *" + schedule: + - cron: "30 1 * * *" jobs: - close-issues: - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - steps: - - uses: actions/stale@v5 - with: - days-before-issue-stale: 30 - days-before-issue-close: 14 - stale-issue-label: "stale" - stale-issue-message: "This issue is stale because it has been open for 30 days with no activity." - close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale." - days-before-pr-stale: -1 - days-before-pr-close: -1 - repo-token: ${{ secrets.GITHUB_TOKEN }} + close-issues: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: actions/stale@v5 + with: + days-before-issue-stale: 30 + days-before-issue-close: 14 + stale-issue-label: "stale" + stale-issue-message: "This issue is stale because it has been open for 30 days with no activity." + close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale." + days-before-pr-stale: -1 + days-before-pr-close: -1 + repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml index 074cb480..57c386ae 100644 --- a/.github/workflows/lint_python.yml +++ b/.github/workflows/lint_python.yml @@ -1,18 +1,18 @@ -name: lint_python +name: Lint on: [pull_request, push] jobs: - lint_python: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - - run: pip install --upgrade pip wheel - - run: pip install bandit black flake8 flake8-bugbear flake8-comprehensions isort safety mypy - - run: mypy --install-types --non-interactive --ignore-missing-imports ./rembg - - run: bandit --recursive --skip B101,B104,B310,B311,B303 --exclude ./rembg/_version.py ./rembg - - run: black --force-exclude rembg/_version.py --check --diff ./rembg - - run: flake8 ./rembg --count --ignore=B008,C901,E203,E266,E731,F401,F811,F841,W503 --max-line-length=120 --show-source --statistics --exclude ./rembg/_version.py - - run: isort --check-only --profile black ./rembg - - run: safety check + lint_python: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + - run: pip install --upgrade pip wheel + - run: pip install bandit black flake8 flake8-bugbear flake8-comprehensions isort safety mypy + - run: mypy --install-types --non-interactive --ignore-missing-imports ./rembg + - run: bandit --recursive --skip B101,B104,B310,B311,B303 --exclude ./rembg/_version.py ./rembg + - run: black --force-exclude rembg/_version.py --check --diff ./rembg + - run: flake8 ./rembg --count --ignore=B008,C901,E203,E266,E731,F401,F811,F841,W503 --max-line-length=120 --show-source --statistics --exclude ./rembg/_version.py + - run: isort --check-only --profile black ./rembg + - run: safety check diff --git a/.github/workflows/publish_docker.yml b/.github/workflows/publish_docker.yml index faebe281..211c52ee 100644 --- a/.github/workflows/publish_docker.yml +++ b/.github/workflows/publish_docker.yml @@ -1,32 +1,28 @@ name: Publish Docker image on: - push: - tags: - - "v*.*.*" + push: + tags: + - "v*.*.*" jobs: - push_to_registry: - name: Push Docker image to Docker Hub - runs-on: ubuntu-latest - steps: - - - name: Checkout - uses: actions/checkout@v2 - - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - - - name: Build and push - uses: docker/build-push-action@v2 - with: - context: . - file: ./Dockerfile - push: true - tags: ${{ secrets.DOCKER_HUB_USERNAME }}/rembg:latest + push_to_registry: + name: Push Docker image to Docker Hub + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Login to Docker Hub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - name: Build and push + uses: docker/build-push-action@v2 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ secrets.DOCKER_HUB_USERNAME }}/rembg:latest diff --git a/.github/workflows/publish_pypi.yml b/.github/workflows/publish_pypi.yml index 81a044c7..e274dc6c 100644 --- a/.github/workflows/publish_pypi.yml +++ b/.github/workflows/publish_pypi.yml @@ -1,28 +1,28 @@ name: Publish to Pypi on: - push: - tags: - - "v*.*.*" + push: + tags: + - "v*.*.*" jobs: - push_to_pypi: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - with: - python-version: 3.9 + push_to_pypi: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: 3.9 - - name: "Installs dependencies" - run: | - python3 -m pip install --upgrade pip - python3 -m pip install setuptools wheel twine + - name: "Installs dependencies" + run: | + python3 -m pip install --upgrade pip + python3 -m pip install setuptools wheel twine - - name: "Builds and uploads to PyPI" - run: | - python3 setup.py sdist bdist_wheel - python3 -m twine upload dist/* - env: - TWINE_USERNAME: ${{ secrets.PIPY_USERNAME }} - TWINE_PASSWORD: ${{ secrets.PIPY_PASSWORD }} + - name: "Builds and uploads to PyPI" + run: | + python3 setup.py sdist bdist_wheel + python3 -m twine upload dist/* + env: + TWINE_USERNAME: ${{ secrets.PIPY_USERNAME }} + TWINE_PASSWORD: ${{ secrets.PIPY_PASSWORD }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 00000000..2483bed2 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,25 @@ +name: Run tests + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.7", "3.8", "3.9", "3.10"] + + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest + pip install -r requirements.txt + - name: Test with pytest + run: | + pytest diff --git a/.gitignore b/.gitignore index 48cccc13..40f8603c 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ __pycache__/ .envrc .python-version .idea +.pytest_cache # due to using tox and pytest .tox diff --git a/MANIFEST.in b/MANIFEST.in index 9eb6ca7f..800a885c 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -3,6 +3,8 @@ include LICENSE.txt include README.md include setup.py include pyproject.toml +include requirements.txt +include requirements-gpu.txt include versioneer.py include rembg/_version.py diff --git a/README.md b/README.md index 389dc0ad..1995a3ac 100644 --- a/README.md +++ b/README.md @@ -37,17 +37,16 @@ Rembg is a tool to remove images background. That is it. **If this project has helped you, please consider making a [donation](https://www.buymeacoffee.com/danielgatis).** - ### Installation -#### **!! This library is for Python 3.9 only !!** - CPU support: + ```bash pip install rembg ``` GPU support: + ```bash pip install rembg[gpu] ``` @@ -55,16 +54,19 @@ pip install rembg[gpu] ### Usage as a cli Remove the background from a remote image + ```bash curl -s http://input.png | rembg i > output.png ``` Remove the background from a local file + ```bash rembg i path/to/input.png path/to/output.png ``` Remove the background from all images in a folder + ```bash rembg p path/to/input path/to/output ``` @@ -72,6 +74,7 @@ rembg p path/to/input path/to/output ### Usage as a server Start the server + ```bash rembg s ``` @@ -83,26 +86,34 @@ http://localhost:5000/docs ``` Image with background: + ``` https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/Gull_portrait_ca_usa.jpg/1280px-Gull_portrait_ca_usa.jpg ``` Image without background: + ``` http://localhost:5000/?url=https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/Gull_portrait_ca_usa.jpg/1280px-Gull_portrait_ca_usa.jpg ``` Also you can send the file as a FormData (multipart/form-data): + ```html -
``` ### Usage as a library Input and output as bytes + ```python from rembg import remove @@ -117,6 +128,7 @@ with open(input_path, 'rb') as i: ``` Input and output as a PIL image + ```python from rembg import remove from PIL import Image @@ -130,6 +142,7 @@ output.save(output_path) ``` Input and output as a numpy array + ```python from rembg import remove import cv2 @@ -151,11 +164,13 @@ docker run -p 5000:5000 danielgatis/rembg s ``` Image with background: + ``` https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/Gull_portrait_ca_usa.jpg/1280px-Gull_portrait_ca_usa.jpg ``` Image without background: + ``` http://localhost:5000/?url=https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/Gull_portrait_ca_usa.jpg/1280px-Gull_portrait_ca_usa.jpg ``` @@ -166,10 +181,10 @@ All models are downloaded and saved in the user home folder in the `.u2net` dire The available models are: -- u2net ([download](https://drive.google.com/uc?id=1tCU5MM1LhRgGou5OpmpjBQbSrYIUoYab), [source](https://github.com/xuebinqin/U-2-Net)): A pre-trained model for general use cases. -- u2netp ([download](https://drive.google.com/uc?id=1tNuFmLv0TSNDjYIkjEdeH1IWKQdUA4HR), [source](https://github.com/xuebinqin/U-2-Net)): A lightweight version of u2net model. -- u2net_human_seg ([download](https://drive.google.com/uc?id=1ZfqwVxu-1XWC1xU1GHIP-FM_Knd_AX5j), [source](https://github.com/xuebinqin/U-2-Net)): A pre-trained model for human segmentation. -- u2net_cloth_seg ([download](https://drive.google.com/uc?id=15rKbQSXQzrKCQurUjZFg8HqzZad8bcyz), [source](https://github.com/levindabhi/cloth-segmentation)): A pre-trained model for Cloths Parsing from human portrait. Here clothes are parsed into 3 category: Upper body, Lower body and Full body. +- u2net ([download](https://drive.google.com/uc?id=1tCU5MM1LhRgGou5OpmpjBQbSrYIUoYab), [source](https://github.com/xuebinqin/U-2-Net)): A pre-trained model for general use cases. +- u2netp ([download](https://drive.google.com/uc?id=1tNuFmLv0TSNDjYIkjEdeH1IWKQdUA4HR), [source](https://github.com/xuebinqin/U-2-Net)): A lightweight version of u2net model. +- u2net_human_seg ([download](https://drive.google.com/uc?id=1ZfqwVxu-1XWC1xU1GHIP-FM_Knd_AX5j), [source](https://github.com/xuebinqin/U-2-Net)): A pre-trained model for human segmentation. +- u2net_cloth_seg ([download](https://drive.google.com/uc?id=15rKbQSXQzrKCQurUjZFg8HqzZad8bcyz), [source](https://github.com/levindabhi/cloth-segmentation)): A pre-trained model for Cloths Parsing from human portrait. Here clothes are parsed into 3 category: Upper body, Lower body and Full body. #### How to train your own model @@ -179,6 +194,7 @@ https://github.com/danielgatis/rembg/issues/193#issuecomment-1055534289 ### Advance usage Sometimes it is possible to achieve better results by turning on alpha matting. Example: + ```bash curl -s http://input.png | rembg i -a -ae 15 > output.png ``` @@ -206,11 +222,12 @@ Please contact me at danielgatis@gmail.com if you need help to put it on the clo ### References -- https://arxiv.org/pdf/2005.09007.pdf -- https://github.com/NathanUA/U-2-Net -- https://github.com/pymatting/pymatting +- https://arxiv.org/pdf/2005.09007.pdf +- https://github.com/NathanUA/U-2-Net +- https://github.com/pymatting/pymatting ### Buy me a coffee + Liked some of my work? Buy me a coffee (or more likely a beer)