Commit 3e7a6001 authored by narugo1992's avatar narugo1992
Browse files

dev(narugo): merge from main

parents 9d356e97 587dd8ca
Loading
Loading
Loading
Loading
+96 −1
Original line number Diff line number Diff line
@@ -10,8 +10,82 @@ on:
    types: [ published ]

jobs:
  contents:
    runs-on: ubuntu-latest
    if: ${{ !contains(github.event.head_commit.message, 'ci skip') }}
    strategy:
      matrix:
        python-version: [ 3.7 ]

    services:
      plantuml:
        image: plantuml/plantuml-server
        ports:
          - 18080:8080

    steps:
      - name: Set Swap Space
        uses: pierotofy/set-swap-space@master
        with:
          swap-size-gb: 8
      - name: Checkout code
        uses: actions/checkout@v2
        with:
          fetch-depth: 20
          submodules: 'recursive'
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v2
        with:
          python-version: ${{ matrix.python-version }}
      - name: Install dependencies
        if: ${{ github.event_name == 'push' }}
        run: |
          sudo apt-get update -y
          sudo apt-get install -y make wget curl cloc graphviz pandoc
          dot -V
          python -m pip install -r requirements.txt
          python -m pip install -r requirements-doc.txt
      - name: Prepare dataset
        uses: nick-fields/retry@v2
        if: ${{ github.event_name == 'push' }}
        env:
          CI: 'true'
          HF_NARUGO_USERNAME: ${{ secrets.HF_NARUGO_USERNAME }}
          HF_NARUGO_PASSWORD: ${{ secrets.HF_NARUGO_PASSWORD }}
        with:
          shell: bash
          timeout_minutes: 20
          max_attempts: 5
          retry_on: any
          command: |
            make dataset
      - name: Generate the contents
        if: ${{ github.event_name == 'push' }}
        env:
          ENV_PROD: 'true'
          PLANTUML_HOST: http://localhost:18080
        run: |
          plantumlcli -c
          make docs
      - name: Change Commit
        if: ${{ github.event_name == 'push' }}
        id: commit
        run: |
          git config user.name 'narugo1992'
          git config user.email 'narugo@126.com'
          git add -A
          git diff-index --quiet HEAD || git commit -a -m "dev(narugo): auto sync $(date -R)"
      - name: Push changes
        uses: ad-m/github-push-action@master
        if: ${{ github.event_name == 'push' }}
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          branch: ${{ github.ref }}

  doc:
    runs-on: ubuntu-latest
    needs:
      - contents
    if: "!contains(github.event.head_commit.message, 'ci skip')"
    strategy:
      matrix:
@@ -24,6 +98,10 @@ jobs:
          - 18080:8080

    steps:
      - name: Set Swap Space
        uses: pierotofy/set-swap-space@master
        with:
          swap-size-gb: 8
      - name: Checkout code
        uses: actions/checkout@v2
        with:
@@ -36,10 +114,27 @@ jobs:
      - name: Install dependencies
        run: |
          sudo apt-get update -y
          sudo apt-get install -y make wget curl cloc graphviz
          sudo apt-get install -y make wget curl cloc graphviz pandoc
          dot -V
          python -m pip install -r requirements.txt
          python -m pip install -r requirements-doc.txt
      - name: Prepare dataset
        uses: nick-fields/retry@v2
        env:
          CI: 'true'
          HF_NARUGO_USERNAME: ${{ secrets.HF_NARUGO_USERNAME }}
          HF_NARUGO_PASSWORD: ${{ secrets.HF_NARUGO_PASSWORD }}
        with:
          shell: bash
          timeout_minutes: 20
          max_attempts: 5
          retry_on: any
          command: |
            make dataset
      - name: Sync from ref
        if: ${{ github.event_name == 'push' }}
        run: |
          git pull
      - name: Generate
        env:
          ENV_PROD: 'true'
+4 −1
Original line number Diff line number Diff line
@@ -17,7 +17,10 @@ jobs:
          - '3.8'
        model-name:
          #          - 'lpips'
          - 'monochrome'
          #          - 'monochrome'
          - 'person_detect'
          #          - 'face_detect'
          #          - 'manbits_detect'

    steps:
      - name: Checkout code
+6 −1
Original line number Diff line number Diff line
@@ -1205,7 +1205,9 @@ fabric.properties
/docs/source/**/*.sh.err
/docs/source/**/*.sh.exitcode
/docs/source/**/*.dat.*
!/docs/source/**/*.benchmark.py.*
!/docs/source/_static/**/*
/docs/source/**/*.result.ipynb
/cartpole_dqn_*
/imgutils/**/*.json
/imgutils/**/*.yaml
@@ -1218,3 +1220,6 @@ fabric.properties
/test/testfile/dataset
/zoo/testfile/dataset
/.train
*.pt
/runs
/YOLOv8
+227 −3
Original line number Diff line number Diff line
@@ -18,10 +18,128 @@
[![Contributors](https://img.shields.io/github/contributors/deepghs/imgutils)](https://github.com/deepghs/imgutils/graphs/contributors)
[![GitHub license](https://img.shields.io/github/license/deepghs/imgutils)](https://github.com/deepghs/imgutils/blob/master/LICENSE)

Utilities for Images
A convenient and user-friendly anime-style image data processing library that integrates various advanced anime-style
image processing models.

## Installation

## How to check truncated image
You can simply install it with `pip` command line from the official PyPI site.

```shell
pip install dghs-imgutils
```

If your operating environment includes a available GPU, you can use the following installation command to achieve higher
performance:

```shell
pip install dghs-imgutils[gpu]
```

For more information about installation, you can refer
to [Installation](https://deepghs.github.io/imgutils/main/tutorials/installation/index.html).

## Supported or Developing Features

* [Tachie(差分) Detection and Clustering](https://github.com/deepghs/imgutils#tachie%E5%B7%AE%E5%88%86-detection-and-clustering)
* [Object Detection](https://github.com/deepghs/imgutils#object-detection)
* [Edge Detection / Lineart Generation](https://github.com/deepghs/imgutils#edge-detection--lineart-generation)
* [Monochrome Image Detection](https://github.com/deepghs/imgutils#monochrome-image-detection)
* [Truncated Image Check](https://github.com/deepghs/imgutils#truncated-image-check)
* [Image Tagging](https://github.com/deepghs/imgutils#image-tagging)
* [Character Extraction](https://github.com/deepghs/imgutils#character-extraction)

### Tachie(差分) Detection and Clustering

For the dataset, we need to filter the differences between the tachie(差分). As shown in the following picture

![tachie](https://deepghs.github.io/imgutils/main/_images/lpips_full.dat.svg)

We can use `lpips_clustering` to cluster such situations as shown below

```python
from imgutils.metrics import lpips_clustering

images = [f'lpips/{i}.jpg' for i in range(1, 10)]
print(images)
# ['lpips/1.jpg', 'lpips/2.jpg', 'lpips/3.jpg', 'lpips/4.jpg', 'lpips/5.jpg', 'lpips/6.jpg', 'lpips/7.jpg', 'lpips/8.jpg', 'lpips/9.jpg']
print(lpips_clustering(images))  # -1 means noises, the same as that in sklearn
# [0, 0, 0, 1, 1, -1, -1, -1, -1]
```

### Object Detection

Currently, object detection is supported for anime faces and person, as shown below

* Face Detection

![face detection](https://github.com/deepghs/imgutils/blob/gh-pages/main/_images/face_detect.dat.svg)

* Person Detection

![person detection](https://github.com/deepghs/imgutils/blob/gh-pages/main/_images/person_detect.dat.svg)

Based on practical tests, face detection currently has a very stable performance and can be used for automation tasks.
However, person detection is still being further iterated and will focus on enhancing detection capabilities for
artistic illustrations in the future.

### Edge Detection / Lineart Generation

Anime images can be converted to line drawings using the model provided
by [patrickvonplaten/controlnet_aux](https://github.com/patrickvonplaten/controlnet_aux), as shown below.

![edge example](https://github.com/deepghs/imgutils/blob/gh-pages/main/_images/edge.dat.svg)

It is worth noting that the `lineart` model may consume more computational resources, while `canny` is the fastest but
has average effect. Therefore, `lineart_anime` may be the most balanced choice in most cases.

### Monochrome Image Detection

When filtering the crawled images, we need to remove monochrome images. However, monochrome images are often not simply
composed of grayscale colors and may still contain colors, as shown by the first two rows of six images in the figure
below

![monochrome example](https://deepghs.github.io/imgutils/main/_images/monochrome.dat.svg)

We can use `is_monochrome` to determine whether an image is monochrome, as shown below:

```python
from imgutils.validate import is_monochrome

print(is_monochrome('mono/1.jpg'))  # monochrome images
# True
print(is_monochrome('mono/2.jpg'))
# True
print(is_monochrome('mono/3.jpg'))
# True
print(is_monochrome('mono/4.jpg'))
# True
print(is_monochrome('mono/5.jpg'))
# True
print(is_monochrome('mono/6.jpg'))
# True
print(is_monochrome('colored/7.jpg'))  # colored images
# False
print(is_monochrome('colored/8.jpg'))
# False
print(is_monochrome('colored/9.jpg'))
# False
print(is_monochrome('colored/10.jpg'))
# False
print(is_monochrome('colored/11.jpg'))
# False
print(is_monochrome('colored/12.jpg'))
# False
```

For more details, please refer to
the [official documentation](https://deepghs.github.io/imgutils/main/api_doc/validate/monochrome.html#module-imgutils.validate.monochrome)
.

### Truncated Image Check

The following code can be used to detect incomplete image files (such as images interrupted during the download
process):

```python
from imgutils.validate import is_truncated_file
@@ -35,3 +153,109 @@ if __name__ == '__main__':
        print('This image is okay!')

```

### Image Tagging

The `imgutils` library integrates various anime-style image tagging models, allowing for results similar to the
following:

![tagging demo images](https://deepghs.github.io/imgutils/main/_images/tagging_demo.dat.svg)

The ratings, features, and characters in the image can be detected, like this:

```python
import os
from imgutils.tagging import get_wd14_tags

rating, features, chars = get_wd14_tags('skadi.jpg')
print(rating)
# {'general': 0.0011444687843322754, 'sensitive': 0.8876402974128723, 'questionable': 0.106781005859375, 'explicit': 0.000277101993560791}
print(features)
# {'1girl': 0.997527003288269, 'solo': 0.9797663688659668, 'long_hair': 0.9905703663825989, 'breasts': 0.9761719703674316,
#  'looking_at_viewer': 0.8981098532676697, 'bangs': 0.8810765743255615, 'large_breasts': 0.9498510360717773,
#  'shirt': 0.8377365469932556, 'red_eyes': 0.945058286190033, 'gloves': 0.9457170367240906, 'navel': 0.969594419002533,
#  'holding': 0.7881088852882385, 'hair_between_eyes': 0.7687551379203796, 'very_long_hair': 0.9301245212554932,
#  'standing': 0.6703325510025024, 'white_hair': 0.5292627811431885, 'short_sleeves': 0.8677047491073608,
#  'grey_hair': 0.5859264731407166, 'thighs': 0.9536856412887573, 'cowboy_shot': 0.8056888580322266,
#  'sweat': 0.8394746780395508, 'outdoors': 0.9473626613616943, 'parted_lips': 0.8986269235610962,
#  'sky': 0.9385137557983398, 'shorts': 0.8408567905426025, 'alternate_costume': 0.4245271384716034,
#  'day': 0.931140661239624, 'black_gloves': 0.8830795884132385, 'midriff': 0.7279844284057617,
#  'artist_name': 0.5333830714225769, 'cloud': 0.64717698097229, 'stomach': 0.9516432285308838,
#  'blue_sky': 0.9655293226242065, 'crop_top': 0.9485014081001282, 'black_shirt': 0.7366660833358765,
#  'short_shorts': 0.7161656618118286, 'ass_visible_through_thighs': 0.5858667492866516,
#  'black_shorts': 0.6186309456825256, 'thigh_gap': 0.41193312406539917, 'no_headwear': 0.467605859041214,
#  'low-tied_long_hair': 0.36282333731651306, 'sportswear': 0.3756745457649231, 'motion_blur': 0.5091936588287354,
#  'baseball_bat': 0.951993465423584, 'baseball': 0.5634750723838806, 'holding_baseball_bat': 0.8232709169387817}
print(chars)
# {'skadi_(arknights)': 0.9869340658187866}

rating, features, chars = get_wd14_tags('hutao.jpg')
print(rating)
# {'general': 0.49491602182388306, 'sensitive': 0.5193622708320618, 'questionable': 0.003406703472137451,
#  'explicit': 0.0007208287715911865}
print(features)
# {'1girl': 0.9798132181167603, 'solo': 0.8046203851699829, 'long_hair': 0.7596215009689331,
#  'looking_at_viewer': 0.7620116472244263, 'blush': 0.46084529161453247, 'smile': 0.48454540967941284,
#  'bangs': 0.5152207016944885, 'skirt': 0.8023070096969604, 'brown_hair': 0.8653596639633179,
#  'hair_ornament': 0.7201820611953735, 'red_eyes': 0.7816740870475769, 'long_sleeves': 0.697688639163971,
#  'twintails': 0.8974947333335876, 'school_uniform': 0.7491052746772766, 'jacket': 0.5015512704849243,
#  'flower': 0.6401398181915283, 'ahoge': 0.43420469760894775, 'pleated_skirt': 0.4528769850730896,
#  'outdoors': 0.5730487704277039, 'tongue': 0.6739872694015503, 'hair_flower': 0.5545973181724548,
#  'tongue_out': 0.6946243047714233, 'bag': 0.5487751364707947, 'symbol-shaped_pupils': 0.7439308166503906,
#  'blazer': 0.4186026453971863, 'backpack': 0.47378358244895935, ':p': 0.4690653085708618, 'ghost': 0.7565015554428101}
print(chars)
# {'hu_tao_(genshin_impact)': 0.9262397289276123, 'boo_tao_(genshin_impact)': 0.942080020904541}
```

We currently integrate the following tagging models:

* [Deepdanbooru model](https://deepghs.github.io/imgutils/main/api_doc/tagging/deepdanbooru.html), but not recommended
  for production use.
* [wd14-v2 model](https://deepghs.github.io/imgutils/main/api_doc/tagging/wd14.html#), inspired
  by [SmilingWolf/wd-v1-4-tags](https://huggingface.co/spaces/SmilingWolf/wd-v1-4-tags).

In addition, if you need to convert the dict-formatted data mentioned above into the text format required for image
training and tagging, you can also use the `tags_to_text` function (see the
link [here](https://deepghs.github.io/imgutils/main/api_doc/tagging/format.html#tags-to-text)) for formatting, as shown
below:

```python
from imgutils.tagging import tags_to_text

# a group of tags
tags = {
    'panty_pull': 0.6826801300048828,
    'panties': 0.958938717842102,
    'drinking_glass': 0.9340789318084717,
    'areola_slip': 0.41196826100349426,
    '1girl': 0.9988248348236084
}

print(tags_to_text(tags))
# '1girl, panties, drinking_glass, panty_pull, areola_slip'
print(tags_to_text(tags, use_spaces=True))
# '1girl, panties, drinking glass, panty pull, areola slip'
print(tags_to_text(tags, include_score=True))
# '(1girl:0.999), (panties:0.959), (drinking_glass:0.934), (panty_pull:0.683), (areola_slip:0.412)'
```

### Character Extraction

When we need to extract the character parts from anime images, we can use
the [`segment-rgba-with-isnetis`](https://deepghs.github.io/imgutils/main/api_doc/segment/isnetis.html#segment-rgba-with-isnetis)
function for extraction and obtain an RGBA format image (with the background part being transparent), just like the
example shown below.

![isnetis](https://deepghs.github.io/imgutils/main/_images/isnetis_trans.dat.svg)

```python
from imgutils.segment import segment_rgba_with_isnetis

mask_, image_ = segment_rgba_with_isnetis('hutao.png')
image_.save('hutao_seg.png')

mask_, image_ = segment_rgba_with_isnetis('skadi.jpg')
image_.save('skadi_seg.png')
```

This model can be found at https://huggingface.co/skytnt/anime-seg .
 No newline at end of file
+6 −1
Original line number Diff line number Diff line
@@ -11,6 +11,8 @@ BUILDDIR ?= ${PROJ_DIR}/build
ALL_MK := ${SOURCEDIR}/all.mk
ALL    := $(MAKE) -f "${ALL_MK}" SOURCE=${SOURCEDIR}

BMS    := $(shell find ${SOURCEDIR} -name 'benchmark_*.dat.*')

.EXPORT_ALL_VARIABLES:

NO_CONTENTS_BUILD = true
@@ -42,3 +44,6 @@ sourcedir:
	@echo $(shell readlink -f ${SOURCEDIR})
builddir:
	@echo $(shell readlink -f ${BUILDDIR}/html)

cleanbm:
	$(ALL) cleanbm
Loading