我们使用coco数据集来训练我们的cornernet,首先下载数据集,存放路径为D:/dataset\coco\annotations\instances_train2017.json
我们主要是使用的.json文件。这里可以参考-----来了解.json文件的存储形式。
我们使用from pycocotools.coco import COCO这个工具来读取.json文件
1.首先我们要拿到所有的detection,也就是每张图片中有多少个detection,这些detection属于哪张图片,属于哪个类,这些detection的坐标是什么,
##cat_ids 对应关系表
_cat_ids = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13,
14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 27, 28, 31, 32, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 62, 63, 64, 65, 67, 70,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
82, 84, 85, 86, 87, 88, 89, 90
]
_classes = {
ind + 1: cat_id for ind, cat_id in enumerate(_cat_ids)
}
_coco_to_class_map = {
value: key for key, value in _classes.items()
}
label_file = 'D:/dataset\coco\annotations\instances_train2017.json'
def create_detection(label_file):
#创建对象
coco = COCO(label_file)
#返回共有多少个类 [1,2,3,4,5,...90]
cat_ids = coco.getCatIds()
#返回图片的id(这个id是在.json中存储的图片id)
image_ids = coco.getImgIds()
#返回在image中存储的图片的名称
image_ids_names = [coco.load(image_id)[0]['file_name'] for image_id in image_ids]
#接下来开始找每张图片的对应的detection
detection = dict()
for image_name in image_ids_names:
bboxes = []
categories = []
#这里是按照cat_ids共90个来存储的。
for cat_id in cat_ids:
#从这张图片中找到cat_id这个类的annotation_ids
annotation_ids = coco.getAnnIds(imgIds=image_name['id'],catIds=cat_id)
#这一步才找到了这张图片中,这个cat_id下所有的检测框
annotations = coco.loadAnns(annotation_ids)
#这个category是真正的类别
category = _coco_to_class_map[cat_id]
for annotation in annotations:
bbox = np.array(annotation['bbox'])
bbox[[2,3]] += bbox[[0,1]]
bboxes.append(bbox)
categories.append(category)
bboxes = np.array(bboxes,dtype=float)
categories = np.array(categories,dtype=float)
if bboxes.size == 0 or categories.size == 0:
detection[image_name] = np.zeros((0,5),dtype=float32)
else:
detection[image_name] = np.hstack(bboxes,categories[:None])
2.将选出来的detection持久化
import pickle
#新建一个.pkl文件
pkl_path = ''
with open(pkl_path,'rb'):
pickle.dump([detection,image_ids_names],f)
#重新读取.pkl文件
with open(pkl_path,'rb'):
detection,image_ids_names = pickle.load(f)
3.利用tf队列对images进行加工
#创建一个对了,这里结合训练的时候的coord = tf.train.Coordinator()一起使用,这里传入是所有的#image_ids_names
queue = tf.train.slice_input_producer([image_ids_names],shuffle=True)
#使用tf.py_func()来暂时对queue中的数据进行加工,这个函数,输入是一个tensor,在内部转化为numpy,然后结构再转化为tensor返回,这里需要定义返回数据的类型
images, tags_tl, tags_br,heatmaps_tl, heatmaps_br, tags_mask, offsets_tl, offsets_br,boxes,ratio=tf.py_func(read_from_disk,[queue],
[tf.float32,tf.int64,tf.int64,tf.float32,tf.float32,tf.float32,tf.float32,tf.float32,tf.int64,tf.float32])
#创建函数,这里由于使用了queue,s
def read_freom_disk(queue):
#创建一些存放数据的numpy
max_tag_len = 128
image = np.zeros((self.input_size[0], self.input_size[1],3), dtype=np.float32) #(511,511,3)
heatmaps_tl = np.zeros((self.output_size[0], self.output_size[1],self.categories), dtype=np.float32) #(128,128,80)
heatmaps_br = np.zeros((self.output_size[0], self.output_size[1],self.categories), dtype=np.float32) #(128,128,80)
offsets_tl = np.zeros((max_tag_len, 2), dtype=np.float32) #(128,2)
offsets_br = np.zeros((max_tag_len, 2), dtype=np.float32) #(128,2)
tags_tl = np.zeros((max_tag_len), dtype=np.int64) #(128)
tags_br = np.zeros((max_tag_len), dtype=np.int64) #(128)
tags_mask = np.zeros((max_tag_len), dtype=np.float32) #(128)
boxes = np.zeros((max_tag_len,4), dtype=np.int64) #(128,4)
ratio = np.ones((max_tag_len,2), dtype=np.float32) #(128,2)
#image_path coco数据集中保存图片的路径
image_path = ''
image_path = os.path.join(image_path,queue[0])
img = cv2.imread(image_path)
img.astype(np.float32)
#这里detection就是之前.pkl的detection
detections = detection[byte.decode(queue[0])]
#将图片统一为Config.input_size(512,512,3)
img,detections = resize_image(img,detections,Config.input_size)
#由输入到输出的缩放比例,输出为128*128
width_ratio = Config.out_size[1] / Config.input_size[1]
height_ratio = Config.out_size[0] / Config.input_size[0]
#易于训练
img = img / 255.
#########接下来对detection进行处理detection :[xl,yl,xr,yr,category]
for ind,detection in enumerate(detections):
i = 0
categoriy = int(detection[-1]) - 1
#原始的detection坐标
xtl_ori,ytl_ori = detection[0],detection[1]
xbr_ori,ybr_ori = detection[2],detection[3]
if Config.gussian_is:
#转换高斯分布的函数,见。。。
draw_gaussian(heatmaps_tl[:,:,category], [xtl, ytl], radius)
draw_gaussian(heatmaps_br[:,:,category], [xbr, ybr], radius)
else:
heatmaps_tl[ytl,xtl,category] = 1
heatmaps_br[ybr,xbr,category] = 1
fxtl = (xtl_ori * width_ratio)
fytl = (ytl_ori * height_ratio)
fxbr = (xbr_ori * width_ratio)
fybr = (ybr_ori * height_ratio)
xtl = int(fxtl)
ytl = int(fytl)
xbr = int(fxbr)
ybr = int(fybr)
offsets_tl[i,:] = [fxtl - xtl,fytl - ytl]
offsets_br[i,:] = [fxbr - xbr,fybr - ybr]
boxes[i] = [xtl_ori,ytl_ori,xbr_ori,ybr_ori]
ratio[i] = [width_ratio,height_ratio]
#这个是一个索引indx,用来decode到对应的位置。
tags_tl[i] = ytl * Config_output_size[1] + xtl
tags_br[i] = ybr * Config_output_size[1] + ybr
i += 1
#有多少个detection,就有多少个1
tags_mask[:i] = 1
return img , tags_tl, tags_br,heatmaps_tl, heatmaps_br, tags_mask, offsets_tl, offsets_br,boxes,ratio
4.制作bachdata
def get_batch_data():
#这些image这些就是之前tf.py_fun()返回的那些
batch_size = Config.batch_size
images, tags_tl, tags_br,heatmaps_tl, heatmaps_br, tags_mask, offsets_tl, offsets_br,boxes,ratio=tf.train.shuffle_batch(
[images,tags_tl, tags_br,heatmaps_tl, heatmaps_br, tags_mask, offsets_tl, offsets_br,boxes,ratio]
,batch_size=batch_size,
shapes=[(Config.input_size[0], Config.input_size[1],3),(128),(128),(Config.output_size[0], Config.output_size[1],Config.categories),(Config.output_size[0], Config.output_size[1],Config.categories),
(128),(128,2),(128,2),(128,4),(128,2)]
,capacity=100
,min_after_dequeue=batch_size
,num_threads=16)
return images, tags_tl, tags_br,heatmaps_tl, heatmaps_br, tags_mask, offsets_tl, offsets_br,boxes,ratio
5.通过get_batch_data返回的tensor就可以之间feed到网络中,当然,如果使用计算梯度的方式那么不需要feed,只需要run(train_op)就可以。
6.在这里,在数据集上可以使用裁剪,等对数据进行增强,以及使用到的高斯变化函数,在数据集制作2中会根据源码进行解释
#代码参考github上使用tensorflow复现cornernet的项目代码https://github.com/makalo/CornerNet.