文章目录
搞CNN训练时候有时需要生成一些随机多变形的mask来用用,比如在分类算法中我们有时会随机将图像的一部分区域扣掉或填充为其他内容以模拟遮挡
的情况。某些文章中可能会用比较规则的形状,比如矩形或者圆形,这显然就有点太缺少随机性了。
所以有必要搞一些随机形状生成方法,多边形属于比较简单易实现的随机形状,本文档的实现思路比较简单:使用一系列随机的角度配合同样数目的随机半径生成一些列随机的点,其中角度应当按大小顺序排列,然后将这些点依次连接起来就可以生成随机多边形。
这样的多边形有一些特点:
- 边数多的时候总是很像一个充满毛刺的圆形,所以随机性可能不是那么强
- 完全不能保证是凸的,只有当边数比较少的时候有一定运气成分得到凸多边形
- 单连通域
程序如下,生成多边形的顶点后可以使用opencv一个函数cv2.fillpoly
将其画出来看一下。这个函数的原型是fillPoly(img, pts, color, lineType=None, shift=None, offset=None)
,其中pts
参数比较诡异,它代表了多个多边形,而由于每个多边形由一个2D数组表示,所以pts应当是一个list(list中元素是二维数组),或者一个三维数组。推荐使用list,因为三维数组的话就意味着每个多边形边数都得是相同的,而list不用受此约束。
效果如下:
image1
:
image2
:
# -*- coding: utf-8 -*-
import cv2
import numpy as np
def uniform_random(left, right, size=None):
"""
generate uniformly distributed random numbers in [left, right)
Parameters:
-----------
left: a number
left border of random range
right: a number
right border of random range
size: a number or a list/tuple of numbers
size of output
Returns:
--------
rand_nums: ndarray
uniformly distributed random numbers
"""
rand_nums = (right - left) * np.random.random(size) + left
return rand_nums
def random_polygon(edge_num, center, radius_range):
"""
generate points to construct a random polygon
Parameters:
-----------
edge_num: a number
edge numbers of polygon
center: a list/tuple contain two numbers
center of polygon
radius_range: a list/tuple containing two numbers
range of distances from center to polygon vertices
Returns:
--------
points: ndarray
points that can construct a random polygon
"""
angles = uniform_random(0, 2 * np.pi, edge_num)
angles = np.sort(angles)
random_radius = uniform_random(radius_range[0], radius_range[1], edge_num)
x = np.cos(angles) * random_radius
y = np.sin(angles) * random_radius
x = np.expand_dims(x, 1)
y = np.expand_dims(y, 1)
points = np.concatenate([x, y], axis=1)
points += np.array(center)
points = np.round(points).astype(np.int32)
return points
def draw_polygon(image_size, points, color):
"""
draw polygon(s) on a image
Parameters:
-----------
image_size: a list/tuple of numbers
image size = [image_height, image_width, image_channel]
points: 2D ndarray or a list of 2D ndarray
points that can construct a random polygon, also can be a list of
points that can construct random polygons
color: a list/tuple of numbers, whose length is same as image channel
color of polygon
Returns:
--------
image: ndarray
image with polygon(s) on it
"""
image = np.zeros(image_size, dtype=np.uint8)
if type(points) is np.ndarray and points.ndim == 2:
image = cv2.fillPoly(image, [points], color)
else:
image = cv2.fillPoly(image, points, color)
return image
if __name__ == '__main__':
points1 = random_polygon(10, [80, 80], [20, 50])
points2 = random_polygon(10, [80, 180], [20, 50])
points3 = random_polygon(3, [180, 80], [20, 50])
points4 = random_polygon(5, [180, 180], [20, 50])
pts = [points1, points2, points3, points4]
image1 = draw_polygon((256, 256, 3), points1, (255, 255, 255))
image2 = draw_polygon((256, 256, 3), pts, (255, 255, 255))
cv2.imshow('a', image1)
cv2.imshow('b', image2)
cv2.waitKey(0)
cv2.destroyAllWindows()