深度有趣 | 18 二次元头像生成

这篇博客介绍了如何利用ACGAN结构生成二次元头像,涉及数据爬取、头像截取、标签提取、预处理、模型构建等步骤。通过 Illustration2Vec 提取标签,采用ResNet和Sub-pixel CNN技术进行图像生成。文章还讨论了训练过程中处理标签不均衡问题的方法,并展示了训练结果。
摘要由CSDN通过智能技术生成

简介

和CelebA类似,使用ACGAN生成二次元头像,并且用多个条件进行控制

数据

图片爬取自http://getchu.com/,是一个日本二次元游戏网站,包含大量游戏人物立绘,共爬取31,970张

二次元头像示例

头像截取

之前介绍的dlib可用于提取人脸,但不适用于二次元头像

使用OpenCV从每张图片中截取头像部分,用到以下项目,https://github.com/nagadomi/lbpcascade_animeface

对于检测结果适当放大范围,以包含更多人物细节

# -*- coding: utf-8 -*-

import cv2

cascade = cv2.CascadeClassifier('lbpcascade_animeface.xml')

image = cv2.imread('imgs/二次元头像示例.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.equalizeHist(gray)
faces = cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(64, 64))
for i, (x, y, w, h) in enumerate(faces):
    cx = x + w // 2
    cy = y + h // 2
    x0 = cx - int(0.75 * w)
    x1 = cx + int(0.75 * w)
    y0 = cy - int(0.75 * h)
    y1 = cy + int(0.75 * h)
    if x0 < 0:
        x0 = 0
    if y0 < 0:
        y0 = 0
    if x1 >= image.shape[1]:
        x1 = image.shape[1] - 1
    if y1 >= image.shape[0]:
        y1 = image.shape[0] - 1
    w = x1 - x0
    h = y1 - y0
    if w > h:
        x0 = x0 + w // 2 - h // 2
        x1 = x1 - w // 2 + h // 2
        w = h
    else:
        y0 = y0 + h // 2 - w // 2
        y1 = y1 - h // 2 + w // 2
        h = w
    face = image[y0: y0 + h, x0: x0 + w, :]
    face = cv2.resize(face, (128, 128))
    cv2.imwrite('face_%d.jpg' % i, face)

二次元头像截取结果示例

标签提取

使用Illustration2Vec从二次元图片中抽取丰富的标签,https://github.com/rezoo/illustration2vec

Illustration2Vec用到chainer这个深度学习框架,以及一些其他库,如果没有则安装

pip install chainer Pillow scikit-image

Illustration2Vec可以完成以下三项功能:

  • 将每张图片表示为一个4096维的向量
  • 指定阈值,并提取概率高于阈值的标签
  • 指定一些标签,并返回对应的概率

举个例子,提取全部可能的标签,以0.5为阈值

# -*- coding: utf-8 -*-

import i2v
from imageio import imread

illust2vec = i2v.make_i2v_with_chainer('illust2vec_tag_ver200.caffemodel', 'tag_list.json')

img = imread('imgs/二次元头像示例.jpg')
tags = illust2vec.estimate_plausible_tags([img], threshold=0.5)
print(tags)
tags = illust2vec.estimate_specific_tags([img], ['blue eyes', 'red hair'])
print(tags)

也可以指定标签并获取对应的概率

[{'blue eyes': 0.9488178491592407, 'red hair': 0.0025324225425720215}]

预处理

在服务器上处理全部图片,即截取头像、提取标签

加载库

# -*- coding: utf-8 -*-

import i2v
import cv2
import glob
import os
from imageio import imread
from tqdm import tqdm
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import pickle

读取图片路径

images = glob.glob('characters/*.jpg')
print(len(images))

加载两个模型

illust2vec = i2v.make_i2v_with_chainer('illust2vec_tag_ver200.caffemodel', 'tag_list.json')
cascade = cv2.CascadeClassifier('lbpcascade_animeface.xml')
OUTPUT_DIR = 'faces/'
if not os.path.exists(OUTPUT_DIR):
    os.mkdir(OUTPUT_DIR)

提取全部头像,共检测到27772张

num = 0
for x in tqdm(range(len(images))):
    img_path = images[x]
    image = cv2.imread(img_path)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    gray = cv2.equalizeHist(gray)
    faces = cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(64, 64))
    for (x, y, w, h) in faces:
        cx = x + w // 2
        cy = y + h // 2
        x0 = cx - int(0.75 * w)
        x1 = cx + int(0.75 * w)
        y0 = cy - int(0.75 * h)
        y1 = cy + int(0.75 * h)
        if x0 < 0:
            x0 = 0
        if y0 < 0:
            y0 = 0
        if x1 >= image.shape[1]:
            x1 = image.shape[1] - 1
        if y1 >= image.shape[0]:
            y1 = image.shape[0] - 1
        w = x1 - x0
        h = y1 - y0
        if w > h:
            x0 = x0 + w // 2 - h // 2
            x1 = x1 - w // 2 + h // 2
            w = h
        else:
            y0 = y0 + h // 2 - w // 2
            y1 = y1 - h // 2 + w // 2
            h = w
        
        face = image[y0: y0 + h, x0: x0 + w, :]
        face = cv2.resize(face, (128, 128))
        cv2.imwrite(os.path.join(OUTPUT_DIR, '%d.jpg' % num), face)
        num += 1
print(num)

感兴趣的标签包括以下34个:

  • 13种头发颜色:blonde hair, brown hair, black hair, blue hair, pink hair, purple hair, green hair, red hair, silver hair, white hair, orange hair, aqua hair, grey hair
  • 5种发型:long hair, short hair, twintails, drill hair, ponytail
  • 10种眼睛颜色:blue eyes, red eyes, brown eyes, green eyes, purple eyes, yellow eyes, pink eyes, aqua eyes, black eyes, orange eyes
  • 6种其他属性:blush, smile, open mouth, hat, ribbon, glasses

头发颜色、发型和眼睛颜色取概率最高的一种,其他属性概率高于0.25则以存在处理

fw = open('face_tags.txt', 'w')
tags = ['blonde hair', 'brown hair', 'black hair',
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值