一种简单的随机多边形生成方法

文章目录

搞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()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值