Skip to content

Commit

Permalink
dev(narugo): add dbrating:
Browse files Browse the repository at this point in the history
  • Loading branch information
narugo1992 committed Mar 24, 2024
1 parent a5e2a4c commit 296359d
Show file tree
Hide file tree
Showing 52 changed files with 167 additions and 1 deletion.
15 changes: 15 additions & 0 deletions docs/source/api_doc/validate/dbrating.plot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import glob
import os.path

from natsort import natsorted

from plot import image_plot

if __name__ == '__main__':
image_plot(
*natsorted(glob.glob(os.path.join('dbrating', 'general', '*.jpg'))),
*natsorted(glob.glob(os.path.join('dbrating', 'sensitive', '*.jpg'))),
*natsorted(glob.glob(os.path.join('dbrating', 'questionable', '*.jpg'))),
*natsorted(glob.glob(os.path.join('dbrating', 'explicit', '*.jpg'))),
columns=4, figsize=(10, 15),
)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 36 additions & 0 deletions docs/source/api_doc/validate/dbrating_benchmark.plot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import random

from benchmark import BaseBenchmark, create_plot_cli
from imgutils.generic.classify import _open_models_for_repo_id
from imgutils.validate import anime_dbrating
from imgutils.validate.dbrating import _REPO_ID

_MODEL_NAMES = _open_models_for_repo_id(_REPO_ID).model_names


class AnimeDBRatingCharacterBenchmark(BaseBenchmark):
def __init__(self, model):
BaseBenchmark.__init__(self)
self.model = model

def load(self):
_open_models_for_repo_id(_REPO_ID)._open_model(self.model)

def unload(self):
_open_models_for_repo_id(_REPO_ID).clear()

def run(self):
image_file = random.choice(self.all_images)
_ = anime_dbrating(image_file, self.model)


if __name__ == '__main__':
create_plot_cli(
[
(name, AnimeDBRatingCharacterBenchmark(name))
for name in _MODEL_NAMES
],
title='Benchmark for Danbooru Rating Models',
run_times=10,
try_times=20,
)()
1 change: 1 addition & 0 deletions imgutils/validate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from .classify import *
from .color import *
from .completeness import *
from .dbrating import *
from .monochrome import *
from .nsfw import *
from .portrait import *
Expand Down
76 changes: 76 additions & 0 deletions imgutils/validate/dbrating.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"""
Overview:
A model for rating anime images into 4 classes (``general``, ``sensitive``, ``questionable`` and ``explicit``),
based on danbooru rating system.
The following are sample images for testing.
.. collapse:: The following are sample images for testing. (WARNING: NSFW!!!)
.. image:: dbrating.plot.py.svg
:align: center
This is an overall benchmark of all the rating validation models:
.. image:: dbrating_benchmark.plot.py.svg
:align: center
The models are hosted on
`huggingface - deepghs/anime_dbrating <https://huggingface.co/deepghs/anime_dbrating>`_.
.. note::
This model is based on danbooru rating system, trained with 1.2 million images.
If you need 3-level rating prediction, use :func:`imgutils.validate.rating.anime_rating`.
.. note::
Please note that the classification of ``general``, ``sensitive``, ``questionable`` and ``explicit`` types
does not have clear boundaries, making it challenging to clean the training data. As a result,
there is no strict ground truth for the rating classification problem. The judgment functionality
provided by the current module is intended as a quick and rough estimation.
**If you require an accurate filtering or judgment function specifically for R-18 images,
it is recommended to consider using object detection-based methods**,
such as using :func:`imgutils.detect.censor.detect_censors` to detect sensitive regions as the basis for judgment.
"""
from typing import Tuple, Dict

from ..data import ImageTyping
from ..generic import classify_predict, classify_predict_score

__all__ = [
'anime_dbrating_score',
'anime_dbrating',
]

_DEFAULT_MODEL_NAME = 'mobilenetv3_large_100_v0_ls0.2'
_REPO_ID = 'deepghs/anime_dbrating'


def anime_dbrating_score(image: ImageTyping, model_name: str = _DEFAULT_MODEL_NAME) -> Dict[str, float]:
"""
Overview:
Predict the rating of the given image, return the score with as a dict object.
:param image: Image to rating.
:param model_name: Model to use. Default is ``mobilenetv3_large_100_v0_ls0.2``.
All available models are listed on the benchmark plot above.
If you need better accuracy, just set this to ``caformer_s36_v0_ls0.2``.
:return: A dict with ratings and scores.
"""
return classify_predict_score(image, _REPO_ID, model_name)


def anime_dbrating(image: ImageTyping, model_name: str = _DEFAULT_MODEL_NAME) -> Tuple[str, float]:
"""
Overview:
Predict the rating of the given image, return the class and its score.
:param image: Image to rating.
:param model_name: Model to use. Default is ``mobilenetv3_large_100_v0_ls0.2``. All available models are listed
on the benchmark plot above. If you need better accuracy, just set this to ``caformer_s36_v0_ls0.2``.
:return: A tuple contains the rating and its score.
"""
return classify_predict(image, _REPO_ID, model_name)
2 changes: 1 addition & 1 deletion imgutils/validate/rating.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""
Overview:
A model for rating anime images into 4 classes (``safe``, ``r15`` and ``r18``).
A model for rating anime images into 3 classes (``safe``, ``r15`` and ``r18``), based on sankaku rating system.
The following are sample images for testing.
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 38 additions & 0 deletions test/validate/test_dbrating.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import glob
import os.path

import pytest

from imgutils.generic.classify import _open_models_for_repo_id
from imgutils.validate import anime_dbrating
from imgutils.validate.dbrating import anime_dbrating_score, _REPO_ID
from test.testings import get_testfile

_ROOT_DIR = get_testfile('anime_dbrating')
_EXAMPLE_FILES = [
(os.path.relpath(file, _ROOT_DIR), os.path.basename(os.path.dirname(file)))
for file in glob.glob(get_testfile(_ROOT_DIR, '**', '*.jpg'), recursive=True)
]


@pytest.fixture(scope='module', autouse=True)
def _release_model_after_run():
try:
yield
finally:
_open_models_for_repo_id(_REPO_ID).clear()


@pytest.mark.unittest
class TestValidatedbrating:
@pytest.mark.parametrize(['image', 'label'], _EXAMPLE_FILES)
def test_anime_dbrating(self, image, label):
image_file = get_testfile('anime_dbrating', image)
tag, score = anime_dbrating(image_file)
assert tag == label

@pytest.mark.parametrize(['image', 'label'], _EXAMPLE_FILES)
def test_anime_dbrating_score(self, image, label):
image_file = get_testfile('anime_dbrating', image)
scores = anime_dbrating_score(image_file)
assert scores[label] > 0.5

0 comments on commit 296359d

Please sign in to comment.