想要复现fcn网络,用自己的数据训练网络,本以为网上下载代码会很容易,没想到调试代码用了好几天的时间,总是一些小问题和网上给出的结果不一致,导致代码运行失败,总结原因可能是使用的包版本不同,电脑环境配置不同导致。
1、使用labelme,实现标注,批量转换成想要的图片。参考博客:https://blog.csdn.net/weixin_41319671/article/details/82684334,https://blog.csdn.net/fengxin1995/article/details/80511227,
(1)使用labelme标注图像,生成.json文件。
(2)将.json文件,转换成文件夹。很多文章都有下面的代码,功能为实现批量执行下面的语句,语句为调用labelme安装带的程序,实现转换。
#coding:utf-8
import os
path = 'E:\\data' #path是存放json的路径
json_file = os.listdir(path)
for file in json_file:
os.system("python E:\Anocado\Anocado3\envs\labelme\Scripts\labelme_json_to_dataset.py %s"
% (path + file)) #使用自己的labelme路径
将C:\Users\Administrator\Anaconda3\envs\labelme\Lib\site-packages\labelme\cli下的json_to_dataset.py,改为下面的代码
import argparse
import base64
import json
import os
import os.path as osp
import warnings
import PIL.Image
import yaml
from labelme import utils
def main():
warnings.warn("This script is aimed to demonstrate how to convert the\n"
"JSON file to a single image dataset, and not to handle\n"
"multiple JSON files to generate a real-use dataset.")
parser = argparse.ArgumentParser()
parser.add_argument('json_file')
parser.add_argument('-o', '--out', default=None)
args = parser.parse_args()
json_file = args.json_file
alist = os.listdir(json_file)
for i in range(0,len(alist)):
path = os.path.join(json_file,alist[i])
data = json.load(open(path))
out_dir = osp.basename(path).replace('.', '_')
out_dir = osp.join(osp.dirname(path), out_dir)
if not osp.exists(out_dir):
os.mkdir(out_dir)
if data['imageData']:
imageData = data['imageData']
else:
imagePath = os.path.join(os.path.dirname(path), data['imagePath'])
with open(imagePath, 'rb') as f:
imageData = f.read()
imageData = base64.b64encode(imageData).decode('utf-8')
img = utils.img_b64_to_arr(imageData)
label_name_to_value = {'_background_': 0}
for shape in data['shapes']:
label_name = shape['label']
if label_name in label_name_to_value:
label_value = label_name_to_value[label_name]
else:
label_value = len(label_name_to_value)
label_name_to_value[label_name] = label_value
# label_values must be dense
label_values, label_names = [], []
for ln, lv in sorted(label_name_to_value.items(), key=lambda x: x[1]):
label_values.append(lv)
label_names.append(ln)
assert label_values == list(range(len(label_values)))
lbl = utils.shapes_to_label(img.shape, data['shapes'], label_name_to_value)
captions = ['{}: {}'.format(lv, ln)
for ln, lv in label_name_to_value.items()]
lbl_viz = utils.draw_label(lbl, img, captions)
PIL.Image.fromarray(img).save(osp.join(out_dir, 'img.png'))
utils.lblsave(osp.join(out_dir, 'label.png'), lbl)
PIL.Image.fromarray(lbl_viz).save(osp.join(out_dir, 'label_viz.png'))
with open(osp.join(out_dir, 'label_names.txt'), 'w') as f:
for lbl_name in label_names:
f.write(lbl_name + '\n')
warnings.warn('info.yaml is being replaced by label_names.txt')
info = dict(label_names=label_names)
with open(osp.join(out_dir, 'info.yaml'), 'w') as f:
yaml.safe_dump(info, f, default_flow_style=False)
print('Saved to: %s' % out_dir)
if __name__ == '__main__':
main()
在终端激活labelme环境:activate labelme,打开要保存结果的文件夹,执行语句:labelme_json_to_dataset + (.json文件的文件夹) ,下面的截图中,前5行为打开保存结果的文件夹,然后是激活环境,然后是执行语句。
注意:代码运行中会报错:ModuleNotFoundError: No module named 'labelme',解决办法为:打开labelme环境下的编译器spyder即可解决。过程中还报错:ModuleNotFoundError: No module named 'skimage',解决办法:激活labelme的环境下:conda install scikit-image。总结:在labelme环境下运行代码,安装需要的库要到labelme环境下。
(3)生成对应图片的标注图片,下载https://github.com/hitzoro/FCN-ColorLabel.git文件,修改x.py文件。
import colorlabel
import PIL.Image
import yaml
import os
label_color = {
'crack': 'red',
'_background_': 'black'
#这个是你自己的类别和对应的颜色
#例如,'Dog': 'maroon'
#注意:这里的颜色需要是下面颜色列表color中的颜色
}
path = 'E:\\testFCNvgg\\prepic\\111\\' #你执行第二步时的存储路径
label_path = os.listdir(path)
for label_class in label_path:
img = PIL.Image.open('%s\\label.png' % (path + label_class))
import numpy as np
from skimage import io,data,color
label = np.array(img)
yaml_file = path + label_class + '\\' + 'info.yaml'
print(yaml_file)
with open(yaml_file) as f:
f = yaml.load(f)
classes = f['label_names']
color = ['red','black'] #颜色列表
c = 1
for i in classes:
if c == 1:
c = c+1
continue
color.append(label_color[i])
#print (color) #颜色列表
dst = colorlabel.label2rgb(label, colors=(tuple)(color), bg_label = 0,bg_color =(0,0,0))
#final = PIL.Image.fromarray(np.uint8(dst * 255))
#final.show()
#final.save('000001.png')
save_path = 'E:\\testFCNvgg\\prepic\\1111' + '\\' + label_class[:-5] + '.png' #你希望将标注图片存储的路径
#print('11111%s' % save_path)
io.imsave(save_path, dst)
注意,代码中的路径换成自己的,都是\\,有的还要注意路径的末尾是否加\\,否则报错:SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 9-10: truncated \UXXXXXXXX escape。
(4)转成8位图,https://github.com/xmojiao/deeplab_v2/tree/master/voc2012下载程序:convert_labels.py和utils.py,这里和原博客不一样,原博客代码会报错,推测是版本的问题,修改了部分代码,执行下面的代码即可,注意改成自己的路径。代码保存路径下,建name.txt中,每一行记录一个图片名。
#!/usr/bin/env python
# Martin Kersner, m.kersner@gmail.com
# 2016/01/25
from __future__ import print_function
import os
import sys
from skimage.io import imread, imsave
from utils import convert_from_color_segmentation
def main():
ext = '.png'
#path, txt_file, path_converted = process_arguments(sys.argv)
path = 'E:\\testFCNvgg\\prepic\\1111\\'
txt_file='E:\\testFCNvgg\\prepic\\FCN-ColorLabel-master\\FCN-ColorLabel-master\\name.txt'
path_converted = 'E:\\testFCNvgg\\prepic\\11111'
# Create dir for converted labels
if not os.path.isdir(path_converted):
os.makedirs(path_converted)
with open(txt_file, 'rb') as f:
for img_name in f:
img_base_name = img_name.strip()
img_name = os.path.join(path, img_base_name.decode()) + ext
#img_name ='%s.png'%(path+ img_base_name)
img = imread(img_name)
if (len(img.shape) > 2):
img = convert_from_color_segmentation(img)
imsave(os.path.join(path_converted, img_base_name.decode()) + ext, img)
else:
print(img_name + " is not composed of three dimensions, therefore "
"shouldn't be processed by this script.\n"
"Exiting." , file=sys.stderr)
exit()
def process_arguments(argv):
if len(argv) != 4:
help()
path = argv[1]
list_file = argv[2]
new_path = argv[3]
return path, list_file, new_path
def help():
print('Usage: python convert_labels.py PATH LIST_FILE NEW_PATH\n'
'PATH points to directory with segmentation image labels.\n'
'LIST_FILE denotes text file containing names of images in PATH.\n'
'Names do not include extension of images.\n'
'NEW_PATH points to directory where converted labels will be stored.'
, file=sys.stderr)
exit()
if __name__ == '__main__':
main()
注:忘记在哪步了,报错:cannot import name '_validate_lengths',是因为numpy版本不符合导致的,重新安装新的版本:conda install numpy==1.15.0。