python视频处理为卡通风格_用 python 快速「卡通化」人物头像

这个项目让我想起了以前玩QQ秀的时光。有了这个项目,再也不用找同学了,我自己也可以把头像卡通化了。

下图是我的头像、不得不说还真是神似。

人像卡通风格渲染的目标是,在保持原图像ID信息和纹理细节的同时,将真实照片转换为卡通风格的非真实感图像。

该项目的思路是,从大量照片/卡通数据中习得照片到卡通画的映射。

项目所需的主要依赖库如下:python 3.6

pytorch 1.4

tensorflow-gpu 1.14

face-alignment

dlib

训练

1.数据准备训练数据包括真实照片和卡通画像,为降低训练复杂度,该项目对两类数据进行了如下预处理:检测人脸及关键点。

根据关键点旋转校正人脸。

将关键点边界框按固定的比例扩张并裁剪出人脸区域。

使用人像分割模型将背景置白。

项目开源了204张处理后的卡通画数据,您还需准备约1000张人像照片(为匹配卡通数据,尽量使用亚洲年轻女性照片,人脸大小最好超过200x200像素),使用以下命令进行预处理:

python data_process.py --data_path YourPhotoFolderPath --save_path YourSaveFolderPath

将处理后的数据按照以下层级存放,trainA、testA中存放照片头像数据,trainB、testB中存放卡通头像数据。

├── dataset

└── photo2cartoon

├── trainA

├── xxx.jpg

├── yyy.png

└── ...

├── trainB

├── zzz.jpg

├── www.png

└── ...

├── testA

├── aaa.jpg

├── bbb.png

└── ...

└── testB

├── ccc.jpg

├── ddd.png

└── ...

2.训练重新训练:

python train.py --dataset photo2cartoon

加载预训练参数:

python train.py --dataset photo2cartoon --pretrained_weights models/photo2cartoon_weights.pt

测试

将一张测试照片(亚洲年轻女性)转换为卡通风格:

python test.py --photo_path ./images/photo_test.jpg --save_path ./images/cartoon_result.png

Q&A

Q:为什么开源的卡通化模型与小程序中的效果有差异?

A:开源模型的训练数据收集自互联网,为了得到更加精美的效果,我们在训练小程序中卡通化模型时,采用了定制的卡通画数据(200多张),且增大了输入分辨率。此外,小程序中的人脸特征提取器采用自研的识别模型,效果优于本项目使用的开源识别模型。

Q:如何选取效果最好的模型?

A:首先训练模型200k iterations,然后使用FID指标挑选出最优模型,最终挑选出的模型为迭代90k iterations时的模型。

Q:关于人脸特征提取模型。

A:实验中我们发现,使用自研的识别模型计算Face ID Loss训练效果远好于使用开源识别模型,若训练效果出现鲁棒性问题,可尝试将Face ID Loss权重置零。

Q:人像分割模型是否能用与分割半身像?

A:不能。该模型是针对本项目训练的专用模型,需先裁剪出人脸区域再输入。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一个简单的模拟彩票系统的Java程序,实现了随机生成彩票号码、用户购买彩票、开奖等基本功能。 ```java import java.util.*; public class LotterySystem { private static final int MAX_NUMBER = 50; // 最大彩票号码 private static final int MAX_CHOICE = 5; // 每张彩票选择的号码数量 private static final int MAX_TICKETS = 100; // 最大购买彩票数量 private static final int TICKET_PRICE = 2; // 每张彩票的价格 private static final int JACKPOT = 1000; // 奖池金额 private static List<Integer> lotteryNumbers; // 当前彩票号码 private static List<Ticket> tickets; // 购买的彩票列表 private static int jackpot; // 当前奖池金额 public static void main(String[] args) { initialize(); // 初始化 Scanner scanner = new Scanner(System.in); while (true) { System.out.println("请选择操作:"); System.out.println("1. 购买彩票"); System.out.println("2. 开奖"); System.out.println("3. 查看当前奖池金额"); System.out.println("4. 退出"); int choice = scanner.nextInt(); switch (choice) { case 1: buyTicket(scanner); break; case 2: drawLottery(); break; case 3: System.out.println("当前奖池金额为:" + jackpot); break; case 4: System.exit(0); default: System.out.println("无效操作,请重新选择。"); break; } } } // 初始化 private static void initialize() { lotteryNumbers = new ArrayList<>(); tickets = new ArrayList<>(); jackpot = JACKPOT; } // 随机生成彩票号码 private static List<Integer> generateLotteryNumbers() { List<Integer> numbers = new ArrayList<>(); Random random = new Random(); while (numbers.size() < MAX_CHOICE) { int number = random.nextInt(MAX_NUMBER) + 1; if (!numbers.contains(number)) { numbers.add(number); } } Collections.sort(numbers); return numbers; } // 购买彩票 private static void buyTicket(Scanner scanner) { if (tickets.size() >= MAX_TICKETS) { System.out.println("彩票已售完,无法购买。"); return; } System.out.println("请输入您选择的彩票号码(每个号码之间用空格分隔):"); List<Integer> numbers = new ArrayList<>(); for (int i = 0; i < MAX_CHOICE; i++) { numbers.add(scanner.nextInt()); } Ticket ticket = new Ticket(numbers); if (tickets.contains(ticket)) { System.out.println("该彩票已经被购买,请重新选择。"); return; } if (jackpot < TICKET_PRICE) { System.out.println("奖池金额不足,无法购买。"); return; } jackpot -= TICKET_PRICE; tickets.add(ticket); System.out.println("购买成功!"); } // 开奖 private static void drawLottery() { if (tickets.isEmpty()) { System.out.println("暂无彩票,无法开奖。"); return; } if (lotteryNumbers == null) { lotteryNumbers = generateLotteryNumbers(); } System.out.println("本期彩票号码为:" + lotteryNumbers); List<Ticket> winners = new ArrayList<>(); for (Ticket ticket : tickets) { if (ticket.getNumbers().equals(lotteryNumbers)) { winners.add(ticket); } } if (winners.isEmpty()) { System.out.println("本次开奖无人中奖,奖池金额累计。"); jackpot += TICKET_PRICE * tickets.size(); } else { int prize = jackpot / winners.size(); for (Ticket winner : winners) { winner.setPrize(prize); } System.out.println("恭喜中奖者:" + winners); jackpot = 0; } lotteryNumbers = null; } } class Ticket { private List<Integer> numbers; // 彩票号码 private int prize; // 中奖金额 public Ticket(List<Integer> numbers) { this.numbers = numbers; } public List<Integer> getNumbers() { return numbers; } public int getPrize() { return prize; } public void setPrize(int prize) { this.prize = prize; } @Override public String toString() { return "Ticket{" + "numbers=" + numbers + ", prize=" + prize + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Ticket ticket = (Ticket) o; return Objects.equals(numbers, ticket.numbers); } @Override public int hashCode() { return Objects.hash(numbers); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值