文章目录
- 前言
- 一、使用Labelme进行数据标注
- 二、使用PaddleSeg训练
- 1.数据集划分
- 2.PaddleSeg/train.py训练
- 3.结果可视化
- 4.对动漫视频进行分割
- 总结
前言
众所周知,深度学习被应用于各个方面,作为一个喜欢看动漫的人,还是想试试看能不能把相关技术应用到动漫图像上。于是就想到先试试动漫人物的实例分割。
一、使用Labelme进行数据标注
官方文档 Instance Segmentation Example
例如
由于使用的是PaddleSeg,所以要转换下格式,参照把用labelme标注生成的数据集改成PaddleSeg支持的数据集格式 最后如下
二、使用PaddleSeg训练
本人电脑不行,使用百度的飞桨平台进行训练。
1.数据集划分
- train_set(训练集):用于确定模型参数。
- val_set(验证集):用于调节模型超参数(如多个网络结构、正则化权重的最优选择)。
- test_set(测试集):用于估计应用效果(没有在模型中应用过的数据,更贴近模型在真实场景应用的效果)。
images_path = "work/startlabel" #设置数据集路径
image_count = len([os.path.join(images_path, image_name)
for image_name in os.listdir(images_path)])
print("用于训练的图片样本数量:", image_count)
def _sort_images(image_dir):
"""
对文件夹内的图像进行按照文件名排序
"""
images = []
labels = []
for image_name in os.listdir(image_dir):
if os.path.isdir(os.path.join(image_dir, image_name)):
images.append(os.path.join(os.path.join(image_dir, image_name), 'img.png'))
labels.append(os.path.join(os.path.join(image_dir, image_name), 'label.png'))
return sorted(images), sorted(labels)
"""
这里的分割符是\t,后面使用PaddleSeg的时候要注意修改相关代码,因为PaddleSeg读取文件时默认的分割符是空格。
当然也可以将这里的\t替换为空格。
"""
def write_file(mode, images, labels):
with open('./{}.txt'.format(mode), 'w') as f:
for i in range(len(images)):
#f.write('{}\t{}\n'.format(images[i], labels[i]))
f.write('{} {}\n'.format(images[i], labels[i]))
"""
由于所有文件都是散落在文件夹中,在训练时我们需要使用的是数据集和标签对应的数据关系,
所以我们第一步是对原始的数据集进行整理,得到数据集和标签两个数组,分别一一对应。
这样可以在使用的时候能够很方便的找到原始数据和标签的对应关系,否则对于原有的文件夹图片数据无法直接应用。
"""
images, labels = _sort_images(images_path)
eval_num = int(image_count * 0.1)
"""
由于图片数量有限,这里的测试集和验证集采用相同的一组图片。
"""
write_file('train', images[:-eval_num], labels[:-eval_num])
write_file('test', images[-eval_num:], labels[-eval_num:])
write_file('eval', images[-eval_num:], labels[-eval_num:])
划分完成后主目录生成三个文本文件。
2.PaddleSeg/train.py训练
训练参数配置详情见官方文档
# set CUDA_VISIBLE_DEVICES=0
!python PaddleSeg/train.py \
--config mynet.yml \
--do_eval \
--save_interval 100 \
--save_dir output
mynet.yml配置如下:
batch_size: 16
iters: 10000
train_dataset:
type: Dataset
dataset_root: /home/aistudio
train_path: train.txt
num_classes: 2
transforms:
- type: ResizeStepScaling
min_scale_factor: 0.5
max_scale_factor: 2.0
scale_step_size: 0.25
- type: RandomPaddingCrop
crop_size: [512, 512]
- type: RandomHorizontalFlip
- type: RandomDistort
brightness_range: 0.4
contrast_range: 0.4
saturation_range: 0.4
- type: Normalize
mode: train
val_dataset:
type: Dataset
dataset_root: /home/aistudio
val_path: eval.txt
transforms:
- type: Normalize
mode: val
num_classes: 2
test_dataset:
type: Dataset
dataset_root: /home/aistudio
val_path: test.txt
transforms:
- type: Normalize
mode: test
num_classes: 2
optimizer:
type: sgd
momentum: 0.9
weight_decay: 0.0005
learning_rate:
value: 0.01
decay:
type: poly
power: 0.9
end_lr: 0.0
loss:
types:
- type: CrossEntropyLoss
coef: [1]
model:
type: FCN
backbone:
type: HRNet_W48
pretrained: https://bj.bcebos.com/paddleseg/dygraph/hrnet_w48_ssld.tar.gz
num_classes: 2
pretrained: Null
backbone_indices: [-1]
3.结果可视化
i=35
pre_commend=f'python PaddleSeg/predict.py \
--config mynet.yml \
--model_path output/iter_5400/model.pdparams \
--image_path work/startlabel/Anime_{i}_json/img.png \
--save_dir output/result'
#这里对work/Line/0114目录下的图片进行预测,结果保存在output/result目录下,要注意匹配配置文件和模型参数还有待处理图片的路径
#展示效果看不清的话可以根据代码中的路径找到文件所在位置
b=os.popen(pre_commend).read()
print(b)
import cv2
image = cv2.imread('work/startlabel/Anime_'+str(i)+'_json/img.png')
label_viz = cv2.imread('work/startlabel/Anime_'+str(i)+'_json/label_viz.png')
mask = cv2.imread('output/result/added_prediction/img.png')
#用matplotlib将图片展示出来
plt.subplot(3, 1, 1)
plt.imshow(image)
plt.title('Input Image')
plt.axis("off")
plt.subplot(3, 1, 2)
plt.imshow(label_viz, cmap='gray')
plt.title('Label_viz')
plt.axis("off")
plt.subplot(3, 1, 3)
plt.imshow(mask, cmap='gray')
plt.title('Mask')
plt.axis("off")
之前
之后
4.对动漫视频进行分割
%env CUDA_VISIBLE_DEVICES=0
%matplotlib inline
import cv2
import paddlehub as hub
import os
your_file='chaojimingan.mp4'
video_capture = cv2.VideoCapture(your_file)
fps = video_capture.get(cv2.CAP_PROP_FPS)
count_all=video_capture.get(cv2.CAP_PROP_FRAME_COUNT)
print(fps,count_all)
思路就是把视频每一帧存为图片,然后进行预测,最后再组合成视频。(代码不全)
def combine_image_to_video(comb_path, output_file_path, fps, is_print=False):
'''
合并图像到视频
'''
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
file_items = os.listdir(comb_path)
file_len = len(file_items)
# print(comb_path, file_items)
if file_len > 0 :
temp_img = cv2.imread(os.path.join(comb_path, file_items[0]))
img_height, img_width = temp_img.shape[0], temp_img.shape[1]
out = cv2.VideoWriter(output_file_path, fourcc, fps, (img_width, img_height))
for i in range(file_len):
pic_name = os.path.join(comb_path, str(i)+".jpg")
if is_print:
print(i+1,'/', file_len, ' ', pic_name)
img = cv2.imread(pic_name)
out.write(img)
out.release()
import time
final_name="work/"+time.strftime("%Y%m%d%H%M%S", time.localtime())+".mp4"
# tran_name="! ffmpeg -i work/mp4_analysis.mp4 -i work/video.mp3 -c copy "+final_name
after_name=your_file.split('.')[0]+'_analysis.mp4'
combine_image_to_video(f'{img_path}_after_add/', after_name ,fps)
# combine_image_to_video('1_outadded', after_name ,fps)
pre_commend=f"ffmpeg -i {your_file} -vn work/{your_file.split('.')[0]}_video.mp3"
b=os.popen(pre_commend).read()
print(b)
pre_commend=f"ffmpeg -i {after_name} -i work/{your_file.split('.')[0]}_video.mp3 -c copy {your_file[:-4]}_final.mp4"
b=os.popen(pre_commend).read()
print(b)
动漫人物实例分割-演示
总结
机器学习还未入门,只能使用百度paddle的高层API,学习需要更深一步。至少看完西瓜书吧。
有了兴趣引导,这种事情也不算太难。
鸟欲高飞先振翅,人求上进先读书。——李苦禅