imgutils
一个便捷且用户友好的动漫风格图像数据处理库,集成了各种先进的动漫风格图像处理模型。
安装
您可以使用 pip
命令行从官方 PyPI 站点简单安装它。
pip install dghs-imgutils
如果您的运行环境包含可用的 GPU,您可以使用以下安装命令来获得更高的性能:
pip install dghs-imgutils[gpu]
有关安装的更多信息,您可以参考安装指南。
支持或开发中的功能
imgutils
还包括许多其他功能。有关详细描述和示例,请参阅官方文档。这里我们不会逐一详细介绍。
立绘(差分)检测和聚类
对于数据集,我们需要过滤立绘(差分)之间的差异。如下图所示
我们可以使用 lpips_clustering
来对这样的情况进行聚类,如下所示
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 表示噪声,与 sklearn 中的相同
# [0, 0, 0, 1, 1, -1, -1, -1, -1]
对比字符图像预训练
我们可以使用imgutils
从动漫角色图像(仅包含单个角色)中提取特征,计算两个角色之间的视觉差异,并确定两张图像是否描绘了同一个角色。我们还可以基于这个指标执行聚类操作,如下所示:
from imgutils.metrics import ccip_difference, ccip_clustering
# 同一角色
print(ccip_difference('ccip/1.jpg', 'ccip/2.jpg')) # 0.16583099961280823
# 不同角色
print(ccip_difference('ccip/1.jpg', 'ccip/6.jpg')) # 0.42947039008140564
print(ccip_difference('ccip/1.jpg', 'ccip/7.jpg')) # 0.4037521779537201
print(ccip_difference('ccip/2.jpg', 'ccip/6.jpg')) # 0.4371533691883087
print(ccip_difference('ccip/2.jpg', 'ccip/7.jpg')) # 0.40748104453086853
print(ccip_difference('ccip/6.jpg', 'ccip/7.jpg')) # 0.392294704914093
images = [f'ccip/{i}.jpg' for i in range(1, 13)]
print(images)
# ['ccip/1.jpg', 'ccip/2.jpg', 'ccip/3.jpg', 'ccip/4.jpg', 'ccip/5.jpg', 'ccip/6.jpg', 'ccip/7.jpg', 'ccip/8.jpg', 'ccip/9.jpg', 'ccip/10.jpg', 'ccip/11.jpg', 'ccip/12.jpg']
print(ccip_clustering(images, min_samples=2)) # 图像较少,min_sample不应太大
# [0, 0, 0, 3, 3, 3, 1, 1, 1, 1, 2, 2]
更多用法请参考CCIP的官方文档。
物体检测
目前支持动漫头部和人物的物体检测,如下所示:
- 人脸检测
- 头部检测
- 人物检测
根据实际测试,头部检测目前表现非常稳定,可用于自动化任务。然而,人物检测仍在进一步迭代中,未来将专注于增强对艺术插图的检测能力。
边缘检测 / 线稿生成
可以使用patrickvonplaten/controlnet_aux提供的模型将动漫图像转换为线稿,如下所示:
值得注意的是,lineart
模型可能消耗更多计算资源,而canny
是最快的但效果一般。因此,在大多数情况下,lineart_anime
可能是最平衡的选择。
单色图像检测
在筛选爬取的图像时,我们需要去除单色图像。然而,单色图像通常并不仅仅由灰度颜色组成,可能仍然包含颜色,如下图前两行的六张图像所示:
我们可以使用is_monochrome
来判断一张图像是否为单色,如下所示:
from imgutils.validate import is_monochrome
print(is_monochrome('mono/1.jpg')) # 单色图像
# 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')) # 彩色图像
# 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
更多详情请参考官方文档。
图像分级
我们可以使用imgutils
对动漫图像进行粗略且快速的分级(safe
、r15
或r18
)判断,如下所示:
from imgutils.validate import anime_rating
print(anime_rating('rating/safe/1.jpg')) # ('safe', 0.9999998807907104)
print(anime_rating('rating/safe/2.jpg')) # ('safe', 0.9924363493919373)
print(anime_rating('rating/safe/3.jpg')) # ('safe', 0.996969997882843)
print(anime_rating('rating/safe/4.jpg')) # ('safe', 0.9966891407966614)
print(anime_rating('rating/r15/5.jpg')) # ('r15', 0.9996721744537354)
print(anime_rating('rating/r15/6.jpg')) # ('r15', 0.9998563528060913)
print(anime_rating('rating/r15/7.jpg')) # ('r15', 0.9827859997749329)
print(anime_rating('rating/r15/8.jpg')) # ('r15', 0.8339558839797974)
print(anime_rating('rating/r18/9.jpg')) # ('r18', 0.9997004270553589)
print(anime_rating('rating/r18/10.jpg')) # ('r18', 0.9997699856758118)
print(anime_rating('rating/r18/11.jpg')) # ('r18', 0.9999485015869141)
print(anime_rating('rating/r18/12.jpg')) # ('r18', 0.9994290471076965)
截断图片检查
以下代码可用于检测不完整的图片文件(例如下载过程中中断的图片):
from imgutils.validate import is_truncated_file
if __name__ == '__main__':
filename = 'test_jpg.jpg'
if is_truncated_file(filename):
print('这张图片已被截断,你最好'
'从你的数据集中删除这个垃圾。')
else:
print('这张图片没问题!')
图片标签
imgutils
库集成了各种动漫风格的图片标签模型,可以得到类似以下的结果:
可以检测图片中的评级、特征和角色,如下所示:
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)
# {'1个女孩': 0.997527003288269, '单人': 0.9797663688659668, '长发': 0.9905703663825989, '胸部': 0.9761719703674316,
# '看向观众': 0.8981098532676697, '刘海': 0.8810765743255615, '大胸': 0.9498510360717773,
# '衬衫': 0.8377365469932556, '红眼': 0.945058286190033, '手套': 0.9457170367240906, '肚脐': 0.969594419002533,
# '手持物': 0.7881088852882385, '刘海间的头发': 0.7687551379203796, '超长发': 0.9301245212554932,
# '站立': 0.6703325510025024, '白发': 0.5292627811431885, '短袖': 0.8677047491073608,
# '灰发': 0.5859264731407166, '大腿': 0.9536856412887573, '半身像': 0.8056888580322266,
# '汗水': 0.8394746780395508, '户外': 0.9473626613616943, '微张的嘴唇': 0.8986269235610962,
# '天空': 0.9385137557983398, '短裤': 0.8408567905426025, 'alternate_costume': 0.4245271384716034,
# '白天': 0.931140661239624, '黑色手套': 0.8830795884132385, '露脐': 0.7279844284057617,
# '画师签名': 0.5333830714225769, '云': 0.64717698097229, '腹部': 0.9516432285308838,
# '蓝天': 0.9655293226242065, '露脐上衣': 0.9485014081001282, '黑色衬衫': 0.7366660833358765,
# '热裤': 0.7161656618118286, '大腿间可见臀部': 0.5858667492866516,
# '黑色短裤': 0.6186309456825256, '大腿间隙': 0.41193312406539917, '未戴头饰': 0.467605859041214,
# '低扎长发': 0.36282333731651306, '运动服': 0.3756745457649231, '动态模糊': 0.5091936588287354,
# '棒球棒': 0.951993465423584, '棒球': 0.5634750723838806, '手持棒球棒': 0.8232709169387817}
print(chars)
# {'斯卡蒂(明日方舟)': 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}
我们目前集成了以下标记模型:
- Deepdanbooru模型,但不推荐用于生产环境。
- wd14-v2模型,灵感来自SmilingWolf/wd-v1-4-tags。
此外,如果你需要将上述字典格式的数据转换为图像训练和标记所需的文本格式,你也可以使用tags_to_text
函数(参见此链接)进行格式化,如下所示:
from imgutils.tagging import tags_to_text
# 一组标签
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)'
角色提取
当我们需要从动漫图像中提取角色部分时,我们可以使用segment-rgba-with-isnetis
函数进行提取,并获得RGBA格式的图像(背景部分透明),就像下面的示例所示。
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')
这个模型可以在 https://huggingface.co/skytnt/anime-seg 找到。