漫画风格迁移神器 AnimeGANv2:快速生成你的漫画形象

news2024/12/23 14:25:23

生成你的漫画形象! 漫画风格迁移神器 AnimeGANv2

文章目录

  • 生成你的漫画形象! 漫画风格迁移神器 AnimeGANv2
    • 快速在线生成你的漫画形象
    • AnimeGAN 简要介绍
    • 与其他动漫风格迁移模型的效果对比
    • AnimeGANv2 的优点
    • AnimeGANv2 风格多样化
    • AnimeGANv2 网络结构
    • 快速生成你的漫画形象
      • 导入人脸检测模型
      • 可视化landmarks
      • 预处理图片
      • 漫画风格图片生成
      • 利用本地图片生成
    • 利用在线图片生成

趁着有空的时间,给大家介绍一些有趣的项目吧,比如这个漫画风格迁移神器 AnimeGANv2,可以快速生成自己的漫画形象

快速在线生成你的漫画形象

首先告诉大家怎么用,可能这是大家最感兴趣的啦

如果希望能够在线生成自己的漫画形象的话,首先可以简单使用hungging face https://huggingface.co/spaces/akhaliq/AnimeGANv2,这里面可以快速生成自己的漫画形象,也可以选择一些明星来生成。

以下就是简单的在线生成自己的漫画形象,并且可以选择v1还是v2来生成自己的漫画形象

在这里插入图片描述

AnimeGAN 简要介绍

动漫是我们日常生活中常见的艺术形式,被广泛应用于广告、电影和儿童教育等多个领域。目前,动漫的制作主要是依靠手工实现。然而,手工制作动漫非常费力,需要非常专业的艺术技巧。对于动漫艺术家来说,创作高质量的动漫作品需要仔细考虑线条、纹理、颜色和阴影,这意味着创作动漫既困难又耗时。因此,能够将真实世界的照片自动转换为高质量动漫风格图像的自动技术是非常有价值的。它不仅能让艺术家们更多专注于创造性的工作,也能让普通人更容易创建自己的动漫作品。

AnimeGAN是来自武汉大学和湖北工业大学的一项研究,采用的是神经风格迁移 + 生成对抗网络(GAN)的组合。该项目可以实现将真实图像动漫化,由Jie Chen等人在论文AnimeGAN: A Novel Lightweight GAN for Photo Animation中提出。生成器为对称编解码结构,主要由标准卷积、深度可分离卷积、反向残差块(IRB)、上采样和下采样模块组成。判别器由标准卷积组成。

在初始版本发布时的论文《AnimeGAN: a novel lightweight GAN for photo animation》中还提出了三个全新的损失函数,用于提升风格化的动漫视觉效果。

这三个损失函数分别是:灰度风格损失,灰度对抗损失、颜色重建损失,下图也可以看到对比

Image

与其他动漫风格迁移模型的效果对比

去年九月发布的 AnimeGANv2 优化了模型效果,解决了 AnimeGAN 初始版本中的一些问题。

Image

AnimeGAN 初代模型运行效果

Image

AnimeGANv2 模型运行效果

以马斯克为例,AnimeGAN 初代的效果已经很令人惊艳,只是太过于白嫩病娇,仿佛韩国男团成员。相比之下,v2 更加自然,也更贴合真实气质。

AnimeGANv2 的优点

AnimeGANv2 的更新重点:

  • 解决了生成的图像中的高频伪影问题。
  • 它易于训练,并能直接达到论文所述的效果。
  • 进一步减少生成器网络的参数数量。(现在生成器大小 8.17Mb)
  • 尽可能多地使用来自BD电影的新的高质量的风格数据。

AnimeGANv2 风格多样化

在 v2 中新增了新海诚、宫崎骏、今敏三位漫画家漫画风格的训练数据集。

数据集包含6656张真实的风景图片,3种动漫风格:Hayao,Shinkai,Paprika,每一种动漫风格都是从对应的电影中通过对视频帧的随机裁剪生成的,除此之外数据集中也包含用于测试的各种尺寸大小的图像。数据集信息如下图所示:

img

AnimeGANv2 网络结构

AnimeGANv2中生成器的网络结构如图所示,K代表卷积核大小,S代表步长,C代表卷积核个数,IRB代表倒残差块,resize代表插值up-采样方法,SUM表示逐元素相加。AnimeGANv2 的生成器参数大小为 8.6MB,AnimeGAN 的生成器参数大小为 15.8MB。AnimeGANv2 使用与 AnimeGAN 相同的判别器,区别在于判别器使用Layer Normalization而不是Instance Normalization(IN)。

在这里插入图片描述

快速生成你的漫画形象

前面讲了一下如何在线生成,现在介绍一下,使用的代码,其实也是几个步骤,下面我给大家简要介绍一下吧

## AnimeGANv2源码解析

import os
import dlib
import collections
from typing import Union, List
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')

导入人脸检测模型

这一部分是导入dlib库里面的face_detector也就是针对我们的人脸进行检测,所以需要导入我们的模型

def get_dlib_face_detector(predictor_path: str = "shape_predictor_68_face_landmarks.dat"):

    if not os.path.isfile(predictor_path):
        model_file = "shape_predictor_68_face_landmarks.dat.bz2"
        os.system(f"wget http://dlib.net/files/{model_file}")
        os.system(f"bzip2 -dk {model_file}")

    detector = dlib.get_frontal_face_detector()
    shape_predictor = dlib.shape_predictor(predictor_path)

    def detect_face_landmarks(img: Union[Image.Image, np.ndarray]):
        if isinstance(img, Image.Image):
            img = np.array(img)
        faces = []
        dets = detector(img)
        for d in dets:
            shape = shape_predictor(img, d)
            faces.append(np.array([[v.x, v.y] for v in shape.parts()]))
        return faces
    
    return detect_face_landmarks

可视化landmarks

接下来定义了可视化脸部的landmarks关键点的代码,这样可以使我们更清晰的认识。

def display_facial_landmarks(
    img: Image, 
    landmarks: List[np.ndarray],
    fig_size=[15, 15]
):
    plot_style = dict(
        marker='o',
        markersize=4,
        linestyle='-',
        lw=2
    )
    pred_type = collections.namedtuple('prediction_type', ['slice', 'color'])
    pred_types = {
        'face': pred_type(slice(0, 17), (0.682, 0.780, 0.909, 0.5)),
        'eyebrow1': pred_type(slice(17, 22), (1.0, 0.498, 0.055, 0.4)),
        'eyebrow2': pred_type(slice(22, 27), (1.0, 0.498, 0.055, 0.4)),
        'nose': pred_type(slice(27, 31), (0.345, 0.239, 0.443, 0.4)),
        'nostril': pred_type(slice(31, 36), (0.345, 0.239, 0.443, 0.4)),
        'eye1': pred_type(slice(36, 42), (0.596, 0.875, 0.541, 0.3)),
        'eye2': pred_type(slice(42, 48), (0.596, 0.875, 0.541, 0.3)),
        'lips': pred_type(slice(48, 60), (0.596, 0.875, 0.541, 0.3)),
        'teeth': pred_type(slice(60, 68), (0.596, 0.875, 0.541, 0.4))
    }

    fig = plt.figure(figsize=fig_size)
    ax = fig.add_subplot(1, 1, 1)
    ax.imshow(img)
    ax.axis('off')

    for face in landmarks:
        for pred_type in pred_types.values():
            ax.plot(
                face[pred_type.slice, 0],
                face[pred_type.slice, 1],
                color=pred_type.color, **plot_style
            )
    plt.show()

预处理图片

这一部分就是提取我们的数据,也就是对图片进行预处理得到预处理后的的图片,后续输入网络中

# https://github.com/NVlabs/ffhq-dataset/blob/master/download_ffhq.py

import PIL.Image
import PIL.ImageFile
import numpy as np
import scipy.ndimage


def align_and_crop_face(
    img: Image.Image,
    landmarks: np.ndarray,
    expand: float = 1.0,
    output_size: int = 1024, 
    transform_size: int = 4096,
    enable_padding: bool = True,
):
    # 将五官数据转为数组
    # pylint: disable=unused-variable
    lm = landmarks
    lm_chin          = lm[0  : 17]  # left-right
    lm_eyebrow_left  = lm[17 : 22]  # left-right
    lm_eyebrow_right = lm[22 : 27]  # left-right
    lm_nose          = lm[27 : 31]  # top-down
    lm_nostrils      = lm[31 : 36]  # top-down
    lm_eye_left      = lm[36 : 42]  # left-clockwise
    lm_eye_right     = lm[42 : 48]  # left-clockwise
    lm_mouth_outer   = lm[48 : 60]  # left-clockwise
    lm_mouth_inner   = lm[60 : 68]  # left-clockwise

    # 计算辅助向量
    eye_left     = np.mean(lm_eye_left, axis=0)
    eye_right    = np.mean(lm_eye_right, axis=0)
    eye_avg      = (eye_left + eye_right) * 0.5
    eye_to_eye   = eye_right - eye_left
    mouth_left   = lm_mouth_outer[0]
    mouth_right  = lm_mouth_outer[6]
    mouth_avg    = (mouth_left + mouth_right) * 0.5
    eye_to_mouth = mouth_avg - eye_avg

    # 提取矩形框
    x = eye_to_eye - np.flipud(eye_to_mouth) * [-1, 1] # flipud函数实现矩阵的上下翻转;数组乘法,每行对应位置相乘
    x /= np.hypot(*x)
    x *= max(np.hypot(*eye_to_eye) * 2.0, np.hypot(*eye_to_mouth) * 1.8)
    x *= expand
    y = np.flipud(x) * [-1, 1]
    c = eye_avg + eye_to_mouth * 0.1
    quad = np.stack([c - x - y, c - x + y, c + x + y, c + x - y])
    qsize = np.hypot(*x) * 2

    # 缩放
    shrink = int(np.floor(qsize / output_size * 0.5))
    if shrink > 1:
        rsize = (int(np.rint(float(img.size[0]) / shrink)), int(np.rint(float(img.size[1]) / shrink)))
        img = img.resize(rsize, PIL.Image.ANTIALIAS)
        quad /= shrink
        qsize /= shrink

    # 裁剪
    border = max(int(np.rint(qsize * 0.1)), 3)
    crop = (int(np.floor(min(quad[:,0]))), int(np.floor(min(quad[:,1]))), int(np.ceil(max(quad[:,0]))), int(np.ceil(max(quad[:,1]))))
    crop = (max(crop[0] - border, 0), max(crop[1] - border, 0), min(crop[2] + border, img.size[0]), min(crop[3] + border, img.size[1]))
    if crop[2] - crop[0] < img.size[0] or crop[3] - crop[1] < img.size[1]:
        img = img.crop(crop)
        quad -= crop[0:2]

    # 填充数据
    pad = (int(np.floor(min(quad[:,0]))), int(np.floor(min(quad[:,1]))), int(np.ceil(max(quad[:,0]))), int(np.ceil(max(quad[:,1]))))
    pad = (max(-pad[0] + border, 0), max(-pad[1] + border, 0), max(pad[2] - img.size[0] + border, 0), max(pad[3] - img.size[1] + border, 0))
    if enable_padding and max(pad) > border - 4:
        pad = np.maximum(pad, int(np.rint(qsize * 0.3)))
        img = np.pad(np.float32(img), ((pad[1], pad[3]), (pad[0], pad[2]), (0, 0)), 'reflect')
        h, w, _ = img.shape
        y, x, _ = np.ogrid[:h, :w, :1]
        mask = np.maximum(1.0 - np.minimum(np.float32(x) / pad[0], np.float32(w-1-x) / pad[2]), 1.0 - np.minimum(np.float32(y) / pad[1], np.float32(h-1-y) / pad[3]))
        blur = qsize * 0.02
        img += (scipy.ndimage.gaussian_filter(img, [blur, blur, 0]) - img) * np.clip(mask * 3.0 + 1.0, 0.0, 1.0)
        img += (np.median(img, axis=(0,1)) - img) * np.clip(mask, 0.0, 1.0)
        img = PIL.Image.fromarray(np.uint8(np.clip(np.rint(img), 0, 255)), 'RGB')
        quad += pad[:2]

    # 转化图片
    img = img.transform((transform_size, transform_size), PIL.Image.QUAD, (quad + 0.5).flatten(), PIL.Image.BILINEAR)
    if output_size < transform_size:
        img = img.resize((output_size, output_size), PIL.Image.ANTIALIAS)

    return img

漫画风格图片生成

接下来我们就需要导入我们的生成模型,我们可以导入我们的模型,可以选择v2版本,下载到本地后,进入导入我们的模型的权重,模型非常小,只有8M多,是很轻量的,这样我们就导入我们的检测模型和生成模型

其次,还定义了一个face2paint的函数,也就是将输入的人脸转化为漫画,利用生成模型来生成

#@title AnimeGAN model from https://github.com/bryandlee/animegan2-pytorch
# !git clone https://github.com/bryandlee/animegan2-pytorch

model_fname = "face_paint_512_v2_0.pt"

# model_urls = {
#     "face_paint_512_v0.pt": "https://drive.google.com/uc?id=1WK5Mdt6mwlcsqCZMHkCUSDJxN1UyFi0-",
#     "face_paint_512_v2_0.pt": "https://drive.google.com/uc?id=18H3iK09_d54qEDoWIc82SyWB2xun4gjU",
# }

import sys
sys.path.append("animegan2-pytorch")

import torch
torch.set_grad_enabled(False)

from model import Generator

device = "cpu"

model = Generator().eval().to(device)
model.load_state_dict(torch.load(model_fname))

from PIL import Image
from torchvision.transforms.functional import to_tensor, to_pil_image

def face2paint(
    img: Image.Image,
    size: int,
    side_by_side: bool = True,
) -> Image.Image:

    w, h = img.size
    s = min(w, h)
    img = img.crop(((w - s) // 2, (h - s) // 2, (w + s) // 2, (h + s) // 2))
    img = img.resize((size, size), Image.LANCZOS)

    input = to_tensor(img).unsqueeze(0) * 2 - 1
    output = model(input.to(device)).cpu()[0]

    if side_by_side:
        output = torch.cat([input[0], output], dim=2)

    output = (output * 0.5 + 0.5).clip(0, 1)

    return to_pil_image(output)

利用本地图片生成

我们可以读入我们的图片生成我们的结果,并且可以可视化我们的landmarks

def inference_from_file(filepath):
    img = Image.open(filepath).convert("RGB")

    face_detector = get_dlib_face_detector()
    landmarks = face_detector(img)

    display_facial_landmarks(img, landmarks, fig_size=[5, 5])

    for landmark in landmarks:
        face = align_and_crop_face(img, landmark, expand=1.3)
        display(face2paint(face, 512))
inference_from_file('tony-stack.png')

在这里插入图片描述

在这里插入图片描述

inference_from_file('girl.png')

在这里插入图片描述

在这里插入图片描述

利用在线图片生成

输入图片的url网址,我们也可以读入进行生成

import requests

def inference_from_url(url):
    img = Image.open(requests.get(url, stream=True).raw).convert("RGB")

    face_detector = get_dlib_face_detector()
    landmarks = face_detector(img)

    display_facial_landmarks(img, landmarks, fig_size=[5, 5])

    for landmark in landmarks:
        face = align_and_crop_face(img, landmark, expand=1.3)
        display(face2paint(face, 512))
inference_from_url("https://upload.wikimedia.org/wikipedia/commons/8/85/Elon_Musk_Royal_Society_%28crop1%29.jpg")

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/22305.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于stm32单片机的水位检测自动抽水系统

资料编号&#xff1a;106 下面是相关功能视频演示&#xff1a; 106-基于stm32单片机的水位检测自动抽水系统Proteus仿真&#xff08;源码仿真全套资料&#xff09;功能介绍&#xff1a; 使用滑动变阻器模拟水位监测器&#xff0c;通过改变电压值表示水位的变化。stm32通过ADC…

【前端】从 0 到 1 实现一个网站框架(一、注册 [1] )

Hi~你好呀&#xff0c;等你很久啦~ 我是 LStar&#xff0c;一枚来自北京的初二女生&#xff0c;2020 年年初加入 CSDN。 话不多说&#xff0c;直入主题~&#xff08;我现在看两年多前我 11 岁那会发的文章&#xff0c;越看越想笑。为了不让四年后 18 岁的我看着这篇文章露出 …

超详细的mysql多表操作教程

目录 外键约束 概念 特点 操作 多表联合查询 概念 操作 多表操作总结 外键约束 概念 特点 定义一个外键时&#xff0c;需要遵守下列规则&#xff1a; 主表必须已经存在于数据库中&#xff0c;或者是当前正在创建的表。 必须为主表定义主键。 主键不能包含空值&#xf…

967亿销售额!博世解码智能汽车新蓝图

随着新一轮科技革命和产业变革的深化&#xff0c;在低碳化、电动化和智能化的推动下&#xff0c;处于变革关键时期的新能源汽车产业&#xff0c;正逐步由“政策驱动”转向“市场驱动”&#xff0c;智能化、网联化成为新趋势。 据中国汽车工业协会统计&#xff0c;今年我国新能…

通过 Traefik Hub 暴露家里的网络服务

Traefik Hub 简介 &#x1f4da;️Reference: 你的云原生网络平台 -- 发布和加固你的容器从未如此简单。 Traefik Hub 为您在 Kubernetes 或其他容器平台上运行的服务提供一个网关。 Traefik Hub 定位&#xff1a; 云原生网络平台 它有 2 大核心功能&#xff0c;我这次体验感…

pytorch深度学习实战lesson23

第二十三课 AlexNet AlexNet是在2012年被发表的一个金典之作&#xff0c;并在当年取得了ImageNet最好成绩&#xff0c;也是在那年之后&#xff0c;更多的更深的神经网路被提出&#xff0c;比如优秀的vgg,GoogleLeNet. 其官方提供的数据模型&#xff0c;准确率达到57.1%,top 1-5…

认识计算机中的简单指令集

我们现在有了一个新的寄存器&#xff0c;叫做指令寄存器。它包含一个字节&#xff0c;不同的内容表示控制部分的不同操作模式。也被称为指令代码。指令寄存器是一个字节&#xff0c;因此可能有多达256条不同的指令。所有指令都涉及在总线上移动字节。指令将导致字节进出RAM&…

【JavaEE】PCB和进程调度的基本过程

文章目录什么是进程PCB的组成PID内存指针文件描述符表并行和并发进程调度相关属性进程的状态优先级上下文进程的记账信息什么是进程 进程是正在运行的程序的实例&#xff08;an instance of a computer program that is being executed&#xff09; 进程&#xff08;process&am…

《爱的四十条法则》

《爱的四十条法则》 [土]艾丽芙沙法克 作者用别样的手法间接向我们阐述了爱的四十条法则&#xff0c;每一条都会触及不同阶段的灵魂&#xff0c;我仅将文中感触较深的摘录如下&#xff1a; 1.尽管有人这样说&#xff0c;但是爱绝对不是来的快&#xff0c;去的也快的甜蜜感觉而…

长尾分布系列论文解析(二)Delving into Deep Imbalanced Regression

大纲引言回归问题中的长尾分布LDSFDS实验和结果总结引言 本文是长尾分布系列论文解析的第二篇&#xff0c;前情提要详见长尾分布系列论文解析&#xff08;一&#xff09;Decoupling Representation and Classifier for Long-Tailed Recognition&#xff0c;本篇要介绍的是回归任…

弹性力学之边界条件

作者&#xff1a;张伟伟&#xff0c;来源&#xff1a;力学酒吧 弹性力学基本方程包括平衡方程、几何方程和广义胡克定律&#xff0c;其中平衡方程和几何方程都属于微分方程。我们知道&#xff0c;在求解微分方程时&#xff0c;会出现积分常数&#xff0c;只有确定了积分常数&a…

JS —— js中的节流与防抖

文章目录 前言一、节流 1.什么是节流2.做节流可解决什么问题3.如何做节流二、防抖 1.什么是防抖2.做防抖可解决什么问题3.如何做防抖总结前言 最近有同学问到节流与防抖的相关知识点&#xff0c;于是乎&#xff0c;四处查资料&#xff0c;找一找&#xff0c;看一看&#xff0c…

单元测试:会变化的定义

有一种东西&#xff0c; 如果它太小&#xff0c;需要付出的努力就太大&#xff1b;如果它太大&#xff0c;就很难测试。 没错&#xff01;它是单元。 但是什么才是一个好的单元定义呢?为什么它如此重要? 单元的定义对测试过程有很大的影响&#xff0c;但同时单元的定义也是不…

Transformer总结和梳理

Transformer总结和梳理Positional encodingSelf-attentionMulti--head-attentionAdd&NormAdd操作Norm操作FeedForwardMASKPadding MaskedSelf-Attention Masked首先来看一下Transformer结构的结构&#xff1a;Transformer是由Encoder和Decoder两大部分组成&#xff0c;首先…

mysql安装与配置及四大引擎和数据类型、建表以及约束、增删改查、常用函数、聚合函数以及合并

目录 一.mysql安装与配置 1.mysql简介 2.mysql 安装 安装MySQL&#xff08;8.0的版本&#xff09; 安装MySQL&#xff08;5.7的版本&#xff09; 删除MySQL&#xff08;这是5.5版本的卸载方式&#xff09; 3.命令行登陆及权限修改 一.启动方式 二.停止 三.重启 wind…

LeetCode每日一题——808. 分汤

LeetCode每日一题系列 题目&#xff1a;808. 分汤 难度&#xff1a;普通 文章目录LeetCode每日一题系列题目示例思路题解题目 有 A 和 B 两种类型 的汤。一开始每种类型的汤有 n 毫升。有四种分配操作&#xff1a; 提供 100ml 的 汤A 和 0ml 的 汤B 。 提供 75ml 的 汤A 和…

大衣哥在《火火的情怀》后,和孟文豪张成军推出《新时代的农民》

最近一段时间&#xff0c;因为《火火的情怀》版权问题&#xff0c;农民歌唱家大衣哥&#xff0c;被著名导演兼编剧谷传民起诉。话说大衣哥因为被谷传民起诉&#xff0c;也被推上了舆论的风口浪尖&#xff0c;同时也让《火火的情怀》又一次大火。 在谷传民起诉大衣哥的案件当中&…

注册会计师怎么注册非执业?注会执业与非执业有何区别

注册会计师怎么注册非执业?以下就是关于注册会计师怎么注册非执业等等的介绍&#xff0c;希望对您有所帮助! 一、申请注册为非执业会员 取得注册会计师考试已合格&#xff0c;但尚未在中国境内从事审计业务工作二年以上者&#xff0c;可以自行向取得全科合格证书省级注册会计…

调研主板,树莓派 VS RK3288板子,还是 RK的主板香,但是只支持 anrdoid 7系统,估计也有刷机成 armbian或者

1&#xff0c;目前树莓派好贵啊&#xff01;Pi4bB 2G卖810 现在价格是&#xff1a;800多啊&#xff0c;疯了 哎真叫贵。 但是有个东西叫做 广告机的板子&#xff0c;是批量生产放到商场&#xff0c;地铁播视频的。 再配上一个屏幕&#xff0c;就可以直接播放广告了。 不同的地…

计算机网络4小时速成:传输层,功能,UDP协议,TCP协议,三次握手,传输数据,四次握手,超时重传,流量控制

计算机网络4小时速成&#xff1a;传输层 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多算法学生都得去找开发&#xff0c;测开 测开的话&#xff0c;你就得学数据库&#xff0c;sql&#xff0c;oracle&#xff0c…