加入收藏 | 设为首页 | 会员中心 | 我要投稿 温州站长网 (https://www.0577zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

潮科技行业入门指南 | 深度学习理论与实战:提高篇(14)——Mask R-CNN代码简介

发布时间:2019-03-26 00:54:27 所属栏目:教程 来源:36氪
导读:编者按:本文节选自《深度学习理论与实战:提高篇 》一书,原文链接http://fancyerii.github.io/2019/03/14/dl-book/ 。作者李理,环信人工智能研发中心vp,有十多年自然语言处理和人工智能研发经验,主持研发过多款智能硬件的问答和对话系统,负责环信中

def random_image(self, height, width):
"""随机的生成一个specifications
它包括图片的背景演示和一些(最多4个)不同的shape的specifications。
"""
# 随机选择背景颜色
bg_color = np.array([random.randint(0, 255) for _ in range(3)])
# 随机生成一些(最多4个)shape
shapes = []
boxes = []
N = random.randint(1, 4)
for _ in range(N):
# random_shape函数随机产生一个shape(比如圆形),它的颜色和位置
shape, color, dims = self.random_shape(height, width)
shapes.append((shape, color, dims))
# 位置是中心点和大小(正方形,圆形和等边三角形只需要一个值表示大小)
x, y, s = dims
# 根据中心点和大小计算bounding box
boxes.append([y-s, x-s, y+s, x+s])
# 使用non-max suppression去掉重叠很严重的图片
keep_ixs = utils.non_max_suppression(np.array(boxes), np.arange(N), 0.3)
shapes = [s for i, s in enumerate(shapes) if i in keep_ixs]
return bg_color, shapes

随机生成一个shape的函数是random_shape:

def random_shape(self, height, width):
"""随机生成一个shape的specifications,
要求这个shape在height和width的范围内。
返回一个3-tuple:
* shape名字 (square, circle, ...)
* shape的颜色:代表RGB的3-tuple
* shape的大小,一个数值
"""
# 随机选择shape的名字
shape = random.choice(["square", "circle", "triangle"])
# 随机选择颜色
color = tuple([random.randint(0, 255) for _ in range(3)])
# 随机选择中心点位置,在范围[buffer, height/widht - buffer -1]内随机选择
buffer = 20
y = random.randint(buffer, height - buffer - 1)
x = random.randint(buffer, width - buffer - 1)
# 随机的大小size
s = random.randint(buffer, height//4)
return shape, color, (x, y, s)

上面的函数是我们为了生成(或者读取磁盘的图片)而写的代码。接下来我们需要重写上面的三个函数,我们首先来看load_image:

def load_image(self, image_id):
"""根据specs生成实际的图片
如果是实际的数据集,通常是从一个文件读取。
"""
info = self.image_info[image_id]
bg_color = np.array(info['bg_color']).reshape([1, 1, 3])
# 首先填充背景色
image = np.ones([info['height'], info['width'], 3], dtype=np.uint8)
image = image * bg_color.astype(np.uint8)
# 分别绘制每一个shape
for shape, color, dims in info['shapes']:
image = self.draw_shape(image, shape, dims, color)
return image

上面的函数会调用draw_shape来绘制一个shape:

def draw_shape(self, image, shape, dims, color):
"""根据specs绘制shape"""
# 获取中心点x, y和size s
x, y, s = dims
if shape == 'square':
cv2.rectangle(image, (x-s, y-s), (x+s, y+s), color, -1)
elif shape == "circle":
cv2.circle(image, (x, y), s, color, -1)
elif shape == "triangle":
points = np.array([[(x, y-s),
(x-s/math.sin(math.radians(60)), y+s),
(x+s/math.sin(math.radians(60)), y+s),
]], dtype=np.int32)
cv2.fillPoly(image, points, color)
return image

这个函数很直白,使用opencv的函数在image上绘图,正方形和圆形都很简单,就是等边三角形根据中心点和size(中心点到顶点的距离)求3个顶点的坐标需要一些平面几何的知识。

接下来是load_mask函数,这个函数需要返回图片中的目标物体的mask。这里需要稍作说明。通常的实例分隔数据集同时提供Bounding box和Mask(Bounding的某个像素是否属于目标物体)。为了更加通用,这里假设我们值提供Mask(也就是物体包含的像素),而Bounding box就是包含这些Mask的最小的长方形框,因此不需要提供。

对于我们随机生成的性质,只要知道哪种shape以及中心点和size,我们可以计算出这个物体(shape)到底包含哪些像素。对于真实的数据集,这通常是人工标注出来的。

def load_mask(self, image_id):
"""生成给定图片的mask
"""
info = self.image_info[image_id]
shapes = info['shapes']
count = len(shapes)
# 每个物体都有一个mask矩阵,大小是height x width
mask = np.zeros([info['height'], info['width'], count], dtype=np.uint8)
for i, (shape, _, dims) in enumerate(info['shapes']):
# 绘图函数draw_shape已经把mask绘制出来了。我们只需要传入特殊颜色值1。
mask[:, :, i:i+1] = self.draw_shape(mask[:, :, i:i+1].copy(),
shape, dims, 1)
# 处理遮挡(occlusions)
occlusion = np.logical_not(mask[:, :, -1]).astype(np.uint8)
for i in range(count-2, -1, -1):
mask[:, :, i] = mask[:, :, i] * occlusion
occlusion = np.logical_and(occlusion, np.logical_not(mask[:, :, i]))
# 类名到id
class_ids = np.array([self.class_names.index(s[0]) for s in shapes])
return mask.astype(np.bool), class_ids.astype(np.int32)

处理遮挡的代码可能有些tricky,不过这都不重要,因为通常的训练数据都是人工标注的,我们只需要从文件读取就行。这里我们值需要知道返回值的shape和含义就足够了。最后是image_reference函数,它的输入是image_id,输出是正确的分类。

def image_reference(self, image_id):
info = self.image_info[image_id]
if info["source"] == "shapes":
return info["shapes"]
else:
super(self.__class__).image_reference(self, image_id)

上面的代码还判断了一些info[“source”],如果是”shapes”,说明是我们生成的图片,直接返回shape的名字,否则调用基类的image_reference。下面我们来生成一些图片看看。

(编辑:温州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读