转载:https://blog.csdn.net/yshtjdx/article/details/112425866
转载:https://blog.csdn.net/baidu_14831657/article/details/77498467
记录
python3不兼容的可以自行修改
自然场景的文字识别的数据生成至关重要,可以大量降低人工标注的成本,这里详细介绍SynthText的安装和使用,并生成自己的bg数据集对应的图片以及优化引入生成垂直文本的功能。
SynthText官方示例生成效果
https://github.com/ankush-me/SynthText
直接下载工程,和工程开源的SynthText.h5等数据,直接python gen.py即可。
我这里使用的是工程中的python3分支
Adding New Images
Segmentation and depth-maps are required to use new images as background. Sample scripts for obtaining these are available here.
predict_depth.m
MATLAB script to regress a depth mask for a given RGB image; uses the network of Liu etal. However, more recent works (e.g., this) might give better results.run_ucm.m
andfloodFill.py
for getting segmentation masks using gPb-UCM.
For an explanation of the fields in dset.h5
(e.g.: seg
,area
,label
), please check this comment.
要想使用自己的bg数据,需要先得到depth和seg, 然后合并成dset.h5文件,之后调用SynthText中的gen.py生成数据;
生成depth
https://bitbucket.org/fayao/dcnf-fcsp/src/master/
我这里使用的自己的window10的笔记本电脑中的matlab环境(Matlab2016b)
使用改代码时,需要在libs下MatConvNet和VLFeat,虽然原工程已经配置了这两个,但是matconvnet_20141015需要换成matconvnet-1.0-beta9版本(下载地址:https://www.vlfeat.org/matconvnet/download/),不然程序运行时会报错, VLFeat不用修改;同时修改./demo/demo_DCNF_FCSP_depths_prediction.m中的相关部分(P15-23行)如下:
function demo_DCNF_FCSP_depths_prediction(varargin)
run( '../libs/vlfeat-0.9.18/toolbox/vl_setup');
% dir_matConvNet='../libs/matconvnet_20141015/matlab/';
dir_matConvNet='../libs/matconvnet-1.0-beta9/matconvnet-1.0-beta9/matlab/';
addpath(genpath(dir_matConvNet));
run([dir_matConvNet 'vl_setupnn.m']);
-
function demo_DCNF_FCSP_depths_prediction(varargin)
run( '../libs/vlfeat-0.9.18/toolbox/vl_setup');% dir_matConvNet='../libs/matconvnet_20141015/matlab/';
dir_matConvNet='../libs/matconvnet-1.0-beta9/matconvnet-1.0-beta9/matlab/';
addpath(genpath(dir_matConvNet));
run([dir_matConvNet 'vl_setupnn.m']);
注意重新编译matconvert-1.0-beta9版式时,参考https://www.vlfeat.org/matconvnet/install/中的说明,我这里是直接编译的CPU版本;具体步骤如下,因为我的matlab一开始没有装C++的编译器,所以需要配置VS2015的C++编译器给matlab(https://blog.csdn.net/qq_17783559/article/details/82017379),然后mex -setup C++才能成功。
编译成功后,使用dcnf-fcsp/src/master/demo/demo_DCNF_FCSP_depths_prediction.m或者SynthText/prep_scripts/predict_depth.m生成自己准备的bg图片的depth.mat文件,我是准备了12张example,每一个example对应一个文件夹,最终生成的效果是每一个文件夹下有一张rgb原始图片,生成一张gray灰度图片和一份depth.mat文件。
将这12个文件夹放到服务器上,运行convert_depth_mat_to_h5.py程序,得到depth.h5文件。
##convert_depth_mat_to_h5.py
import os
import h5py
import glob
def convert_mat_to_h5(mat_path, h5_output_path):
data_w=h5py.File(h5_output_path,'w')
for sample in glob.glob(path):
print('sample:',sample)
imname = sample.split('/')[-2] + '.jpg'
data=h5py.File(sample,'r')
data_w.create_dataset(imname, data=data['data_obj'][:])
data_w.close()
if __name__=='__main__':
path = r'/data/nfs/yangsuhui/SynthText/prep_scripts/new_own_image_material/results_three/custom_outdoor_sample/*/*.mat'
output_path = r'/data/nfs/yangsuhui/SynthText/prep_scripts/new_own_image_material/depth.h5'
convert_mat_to_h5(path,output_path)
-
##convert_depth_mat_to_h5.py
import os
import h5py
import globdef convert_mat_to_h5(mat_path, h5_output_path):
data_w=h5py.File(h5_output_path,'w')
for sample in glob.glob(path):
print('sample:',sample)
imname = sample.split('/')[-2] + '.jpg'
data=h5py.File(sample,'r')
data_w.create_dataset(imname, data=data['data_obj'][:])
data_w.close()if __name__=='__main__':
path = r'/data/nfs/yangsuhui/SynthText/prep_scripts/new_own_image_material/results_three/custom_outdoor_sample/*/*.mat'
output_path = r'/data/nfs/yangsuhui/SynthText/prep_scripts/new_own_image_material/depth.h5'
convert_mat_to_h5(path,output_path)
生成seg
https://github.com/jponttuset/mcg
此处修改:我的安装环境是win10+vmware15+ubuntu20.04,中间虚拟机安装ubuntu会卡住
查过很多资料,最后发现是系统的安装iso,显卡驱动nv卡和ubuntu有些问题
解决办法,虚拟机安装系统一开始就按ESC,进入脚本安装界面,然后选择install(原始图像驱动)这个选项安装就可以。(该问题卡了我两天)
该程序只能运行在linux环境下,因此我在ubuntu16.04的环境下安装了matlab R2016b,然后使用SynthText/prep_scripts/run_ucm.m,如下图所示,修改代码中的img_dir和mcg_dir路径即可,得到指定路径下的
ucm.mat文件,然后运行SynthText/prep_scripts/floodFill.py,修改floodFill.py程序中的base_dir为第一步生成的ucm.mat文件路径,得到最终的seg_uint16.h5文件。
合并depth和seg等文件成统一的dest.h5
运行程序add_more_data.py,借鉴use_preproc_bg.py写法),用于将1、2步生成的depth和seg和原图组合成同一个dset文件。
##add_more_data.py
import numpy as np
import h5py
import os, sys, traceback
import os.path as osp
import wget, tarfile
import cv2
from PIL import Image
def add_more_data_into_dset(DB_FNAME,more_img_file_path,more_depth_path,more_seg_path):
db=h5py.File(DB_FNAME,'w')
#depth_db=get_data(more_depth_path)
depth_db=h5py.File(more_depth_path,'r')
#seg_db=get_data(more_seg_path)
seg_db=h5py.File(more_seg_path,'r')
db.create_group('image')
db.create_group('depth')
db.create_group('seg')
for imname in os.listdir(more_img_file_path):
if imname.endswith('.jpg'):
full_path=more_img_file_path+imname
print(full_path,imname)
# j=Image.open(full_path)
# imgSize=j.size
# rawData=j.tostring()
# img=Image.fromstring('RGB',imgSize,rawData)
img = cv2.imread(full_path)
img = img[...,::-1]
#img = img.astype('uint16')
db['image'].create_dataset(imname,data=img)
db['depth'].create_dataset(imname,data=depth_db[imname])
db['seg'].create_dataset(imname,data=seg_db['mask'][imname])
db['seg'][imname].attrs['area']=seg_db['mask'][imname].attrs['area']
db['seg'][imname].attrs['label']=seg_db['mask'][imname].attrs['label']
db.close()
depth_db.close()
seg_db.close()
# path to the data-file, containing image, depth and segmentation:
DB_FNAME = '/data/nfs/yangsuhui/SynthText/prep_scripts/new_own_image_material/dset_own_12.h5'
#add more data into the dset
more_depth_path='/data/nfs/yangsuhui/SynthText/prep_scripts/new_own_image_material/depth.h5'
more_seg_path='/data/nfs/yangsuhui/SynthText/prep_scripts/new_own_image_material/seg_uint16.h5'
more_img_file_path='/data/nfs/yangsuhui/SynthText/prep_scripts/new_own_image_material/bg_imgs/'
add_more_data_into_dset(DB_FNAME,more_img_file_path,more_depth_path,more_seg_path)
-
##add_more_data.py
import numpy as np
import h5py
import os, sys, traceback
import os.path as osp
import wget, tarfile
import cv2
from PIL import Imagedef add_more_data_into_dset(DB_FNAME,more_img_file_path,more_depth_path,more_seg_path):
db=h5py.File(DB_FNAME,'w')
#depth_db=get_data(more_depth_path)
depth_db=h5py.File(more_depth_path,'r')
#seg_db=get_data(more_seg_path)
seg_db=h5py.File(more_seg_path,'r')
db.create_group('image')
db.create_group('depth')
db.create_group('seg')
for imname in os.listdir(more_img_file_path):
if imname.endswith('.jpg'):
full_path=more_img_file_path+imname
print(full_path,imname)# j=Image.open(full_path)
# imgSize=j.size
# rawData=j.tostring()
# img=Image.fromstring('RGB',imgSize,rawData)
img = cv2.imread(full_path)
img = img[...,::-1]
#img = img.astype('uint16')
db['image'].create_dataset(imname,data=img)
db['depth'].create_dataset(imname,data=depth_db[imname])
db['seg'].create_dataset(imname,data=seg_db['mask'][imname])
db['seg'][imname].attrs['area']=seg_db['mask'][imname].attrs['area']
db['seg'][imname].attrs['label']=seg_db['mask'][imname].attrs['label']
db.close()
depth_db.close()
seg_db.close()
# path to the data-file, containing image, depth and segmentation:
DB_FNAME = '/data/nfs/yangsuhui/SynthText/prep_scripts/new_own_image_material/dset_own_12.h5'#add more data into the dset
more_depth_path='/data/nfs/yangsuhui/SynthText/prep_scripts/new_own_image_material/depth.h5'
more_seg_path='/data/nfs/yangsuhui/SynthText/prep_scripts/new_own_image_material/seg_uint16.h5'
more_img_file_path='/data/nfs/yangsuhui/SynthText/prep_scripts/new_own_image_material/bg_imgs/'add_more_data_into_dset(DB_FNAME,more_img_file_path,more_depth_path,more_seg_path)
生成数据
根据自己数据生成的dset_own_12.h5文件,运行gen.py(修改DB_FNAME = osp.join(DATA_PATH,‘dset.h5’)为自己的dset文件),即可生成自己数据背景下的生成数据。
运行gen.py,终端显示(有些bg图片计算过程中会出现一些错误,比如下面的0 of 11,这表明有些图片做bg不太合适,最终生成的是10张图片(去掉背景错误生成不了的),10中背景,不同背景只生成一张,通过gen.py中的超参数设置(INSTANCE_PER_IMAGE)):
运行visualize_results.py可以查看SynthText.h5文件生成的效果,并保存图片,运行效果如下,运行一张图片,并弹出图片窗口,终端是显示图片名称和生成的图片中的words和chars个数以及生成的文本text,最终的图片上可以控制显示charBB(字符级别的框)和wordBB(单词级别)。
下图中除了第一张是用的官方的SynthText.h5生成的,其余的都是自己的bg图片生成的效果。
垂直文本的生成
参考https://github.com/ankush-me/SynthText/issues/114, 修改text_utils.py文件下的相应函数(render_multiline)即可,效果如下:
注意事项
1、该程序的visualize_results.py利用matplotlib可以将远程的SynthText.h5中的生成的内容显示出来,用pillow或者opencv很难将图像显示出来在MobaxTerm上;
2、步骤1和2中的depth.mat和ucm.mat文件转h5文件时,mat文件的读取有两种方式,尝试了scipy的io模块和h5py模块,其中如果保存的mat文件时用的matlab指定的-v7.3(如步骤2中run_ucm.py中最后一行save(‘ucm.mat’,‘ucms’,‘names’,’-v7.3’)😉,则scipy的io读取会报错,解决方法就是统一用h5py读取mat文件(参考1,2);有时候scipy的io模块导入不了,解决方法;
3、将多个图片拼成一张长图,我是用的是pinthemall工具,当然还有许多其他好用的图像拼接工具, 其中Shapecollage可以将图片拼成不同形状,甚至绘制自定义形状,而Collagelt则只能固定长方形(https://zhuanlan.zhihu.com/p/25151315);
4、从代码和最后生成的效果上看,SynthText主要是根据depth图和seg图,主要将根据语料和文字频率生成的文字放到图片中的光滑区域,与实际场景图片中的文字出现的位置更加切合;
5、SynthText生成的框有char和word级别,没有sentence级别,因此如果是需要直接检测场景图片中的句子级别的(检测+识别),该工程需要额外修改,或者应该使用其他的工程;
6、该工程生成数据的过程比较繁琐,而且速度比较慢;
7、修改后的代码,因为自己生成的depth.h5中是单通道的,而官方的示例是多通道的,因此根据需要选择是否注释gen.py中112行(#depth = depth[:,:,1] ##use own data to 注释这一行)。
==============================================================================================================================================
一,运行demo
1, 下载SynthText 源码,链接地址如下: https://github.com/ankush-me/SynthText.git
解压后,文件目录如下:
2,运行:
python gen.py --viz
这个文件会下载大概56M的文件,包括:
dset.h5:这是一个示例h5文件,其中包含一组5个图像及其深度和分割信息。
data/fonts:三个样本字体(我们可以添加更多的字体到这个文件夹,然后用他们的路径更新`fonts / fontlist.txt')。
data/newsgroup: 文本源(来自新闻组数据集)。
data/models/colors_new.cp: 从IIIT-5K字数据集学习本的颜色模型(前景/背景文本颜色模型)。
data/models: 其他cPickle文件;
这个脚本输出结果为: results/SynthText.h5
二,生成文本检测数据集
1 , 预处理的背景图像
下载本文中使用的8000个背景图像,以及它们的分割和深度模板,下载链接地址如下:
`http://zeus.robots.ox.ac.uk/textspot/static/db/ <filename>`,其中``文件名``是:
- “imnames.cp”[180K]:已过滤文件的名称,即,这些文件不包含文本;
- `bg_img.tar.gz` [8.9G]:压缩的图像文件(超过8000,所以只能使用imnames.cp中的过滤的文件)
- “depth.h5”[15G]:深度图
- `seg.h5` [6.9G]:分割图
2 ,生成dset.h5文件
将下载的图片文件bg_img.tar.gz,解压到bg_img文件夹, 新建一个Python文件,命名为makeDset.py,将makeDset.py与bg_img图片文件夹,depth.h5,seg.h5 放在同一个文件夹下。
makeDset.py代码如下:
# -*- coding: UTF-8 -*-
import numpy as np
import h5py
import os, sys, traceback
import os.path as osp
import matplotlib.image as mpimg
ImageListDir='imagesName.txt'
ImagesDir='bg_img/'
seg_db = h5py.File('seg.h5','r')
depth_db = h5py.File('depth.h5','r')
db = h5py.File('dset.h5','w')
input = open(ImageListDir, 'r') #将图片、seg文件、depth文件写入.h5w文件
imagesName = input.readlines()
image=db.create_group("image")
depth=db.create_group("depth")
seg=db.create_group("seg")
num=0
for name in seg_db['mask']:
name=name.rstrip("\n")
try:
img = mpimg.imread(ImagesDir+name)
d=depth_db[name][:]
s=seg_db['mask'][name][:]
except:
continue
image[name]=img
s_max=np.amax(s)
label=range(1,s_max+1)
area=range(1,s_max+1)
for i in label:
area[i-1]=int(np.sum(s==i))
depth[name]=d
seg[name]=s
seg[name].attrs['area']=area
seg[name].attrs['label']=label
num=num+1
print num
print name + 'is ok!\n'
db.close()
seg_db.close()
depth_db.close()
3,运行makeDset.py
python makeDset.py
在makeDset.py,同级目录下生成dset.h5文件。
4 ,生成SynthText.h5
将生成的dset.h5文件放到SynthText /data文件夹下;运行gen.py文件:
python gen.py --viz
脚本输出结果为: results/SynthText.h5