def _get_wrapped_cells(cells, cell, grid_size, scale=1.0): ''' Returns: Cells which are the wrapped counterpart of the given `cell`. >>> g = grid((4,4)) >>> g = wrap(g, (4,4), 4) >>> cells = voronoi_polygons(g) >>> len(_get_wrapped_cells(cells, cells[6], (4,4))) 3 ''' wrapped_cells = [] epsilon = 0.1 cc = cell.center for test_cell in cells: tc = test_cell.center same = abs(tc - cc) plus_gridsize = abs(tc - (cc + (Point2d(*grid_size) * scale))) minus_gridsize = abs(tc - (cc - (Point2d(*grid_size) * scale))) if ((plus_gridsize.x < epsilon and same.y < epsilon) or (minus_gridsize.x < epsilon and same.y < epsilon) or (plus_gridsize.y < epsilon and same.x < epsilon) or (minus_gridsize.y < epsilon and same.x < epsilon) or (plus_gridsize.x < epsilon and plus_gridsize.y < epsilon) or (plus_gridsize.x < epsilon and minus_gridsize.y < epsilon) or (minus_gridsize.x < epsilon and plus_gridsize.y < epsilon) or (minus_gridsize.x < epsilon and minus_gridsize.y < epsilon)): wrapped_cells.append(test_cell) return wrapped_cells
def generate_cracks(texture_img, defects_img, depth_img, crack_length, crack_width, number_of_cracks): ''' Generate a given number of cracks. Args: texture_img (PIL.Image.Image): The texture of the street defects_img (PIL.Image.Image): A black-or-white image marking the extent and shape of defects depth_img (PIL.Image.Image): Depth_Img contains the depth of the defects as RGB format crack_length (float): Size of the crack relative to image width crack_width (int) : Crack width number_of_cracks (int): Maximal number of the cracks in a Image ''' img_width = texture_img.size[0] img_height = texture_img.size[1] max_steps = round(5 * crack_length * img_width / crack_width) for j in range(number_of_cracks): direction = random.randint(0, 7) # Set starting point of the crack in the opposite direction p = Point2d( random.randint(0, img_width//2) - DIR_V[direction][0] * (img_width//2), random.randint(0, img_height//2) - DIR_V[direction][1] * (img_height//2), ) crack_points = draw_crack(p, direction, max_steps, crack_width, texture_img, defects_img, depth_img) for k in range(random.randint(1,5)): position = random.choice(crack_points) side_direction = (direction + random.choice([-3, -2, -1, 1, 2, 3]) + 8) % 8 draw_crack(position, side_direction, round(max_steps * (random.random() * 0.5 + 0.1)), 3, texture_img, defects_img, depth_img)
def draw_crack(p, direction, max_steps, crack_width, texture_img, defects_img, depth_img): ''' Draw a crack in the given images. The width of the crack is relative to the picture width. Args: p (Point2d): Starting point direction (int): The crack direction in one of eight cardinal directions max_steps (int): Crack length in steps crack_width (int) : Crack width relative to the image width. texture_img (PIL.Image.Image): The texture for our ground(Street). defects_img (PIL.Image.Image): Defect_img contains the exact defects depth_img (PIL.Image.Image): Depth_Img contains the depth of the defects as RGB format Returns: (List of Points): Each Point contains the x,y coordinates of the cracks ''' start_direction = direction step_size = round(crack_width * 0.2) crack_points = [] for i in range(max_steps): if not (0 <= direction <= 8): raise ValueError("Unknown direction: {}".format(direction)) p += Point2d(*DIR_V[direction]) * step_size if not (0 <= p.x <= texture_img.size[0]): p.x = p.x - texture_img.size[0]*(-1 if p.x < 0 else 1) if not (0 <= p.y <= texture_img.size[1]): p.y = p.y - texture_img.size[1]*(-1 if p.y < 0 else 1) dynamic_width_crack(p, crack_width, max_steps, i, texture_img, defects_img, depth_img) crack_points.append(p) new_dir = random.randint(-1,1) direction = (start_direction + new_dir + 8) % 8 return crack_points
def point_randrange(p, min_max, direction=(1,1)): ''' Return a point with a random offset within range of `min_max` in `direction`. Args: min_max ((float, float) | ((float, float), (float, float))): Minimum and maximum for both directions at once, or for each direction separately. ''' try: r_offset = Point2d( random.uniform(min_max[0][0], min_max[1][0]), random.uniform(min_max[0][1], min_max[1][1]), ) except TypeError: r_offset = Point2d( random.uniform(min_max[0], min_max[1]), random.uniform(min_max[0], min_max[1]), ) return p + r_offset * direction
def random_2d(size, scale=1.0, seed=None): ''' Generates a size[0]*size[1]-length array with [-.5 - 0.5) valued tuples. >>> random_2d((2,2), 1.5, seed=0) [Point2d(0.5166327772875722, 0.3869316044104537), Point2d(-0.1191426287537325, -0.361624874560555), Point2d(0.01691208205291278, -0.14259879382437857), Point2d(0.42569788355215893, -0.2950309108816088)] ''' points = [] random.seed(seed) for p in range(int(size[0] * size[1])): points.append( Point2d((random.random() - 0.5) * scale, (random.random() - 0.5) * scale)) return points
def pothole_generater(p, texture_img, defects_img, depth_img, min_max, radius): """ Draws a pothole into the given images Args: p (Point2d): x,y coordinates of a point texture_img (PIL.Image.Image): The texture for our ground(Street)s defects_img (PIL.Image.Image): Defect_img contains the exact defects depth_img (PIL.Image.Image): Depth_Img contains the depth of the defects as RGB format min_max ([int, int]): Min, Max width of the quad radius (int): Max radius of the pothole starting at the given point p """ tempP = p for d in range(len(DIR_V)): p = tempP n = round(random.uniform(3, radius)) for r in range(n): draw_quad(p, texture_img, defects_img, depth_img, min_max) p = p+Point2d(*DIR_V[d])
def slant_polygon(polygon, center, direction, slant, z_displace): ''' Slant a single polygon relative to its center in the direction given. Note that this is a shearing operation, not a rotation. If the z-coordinate becomes negative (i.e. *higher* than 0) the whole polygon will be offset in positive z-direction to compensate. Args: polygon (list[(float, float, float)]): A float polygon in 3D. center ((float, float, float)): Center point around which to shear. direction (float): Angle in radians, counter-clockwise from the positive x-axis, with the vertices along the direction receiving the greatest positive offset, the ones opposite the direction receiving the greatest negative offset and vertices at 90° from it not changing in z-direction at all. slant (float): The shearing amount. z_displace (float): An additional z-offset to add to all points in the polygon. ''' slanted = [] min_z = Point3d(0, 0, 1e9) # larger than any sensible z-location for point in polygon: distance = point.xy - center.xy slant_dir = Point2d(m.cos(direction), m.sin(direction)) * slant slant_offset = distance.x * slant_dir.x + distance.y * slant_dir.y slanted_point = point + Point3d(z=round(slant_offset)) if min_z.z > slanted_point.z: min_z = slanted_point slanted.append(slanted_point) slant_compensation = -min_z.z if min_z.z < 0 else 0 displaced = [] for point in slanted: displaced_point = point + Point3d(z=round(z_displace + slant_compensation)) displaced.append(displaced_point) return displaced
def generate_asphalt(resolution, asphalt_type, img_destination, img_defects_destination, img_depth_destination, crack_length, number_of_cracks, crack_width): ''' Generate 3 kinds of images: texture image, defects image and depth image, and save them to files. Args: resolution ([int, int]): Resolution contains the image width and height asphalt_type (int): Type of the asphalt .. TODO:: Testen img_destination (str): Asphalt texture path img_defects_destination (str): Path of the image containing the defects img_depth_destination (str): Path of the image containing the depth information. crack_length (float): Size of the crack relative to image width number_of_cracks (int): Maximal number of the cracks in a image crack_width (int) : Crack width ''' width, height = resolution texture_img = Image.new('RGB', resolution, 'white') depth_img = Image.new('RGB', resolution, 'white') defects_img = Image.new('RGB', resolution, 'black') draw = ImageDraw.Draw(texture_img) for x in range (texture_img.size[0]): for y in range(texture_img.size[1]): if asphalt_type == 1: rgb_color= random.choice(COLOR_LIST[30:len(COLOR_LIST)]) draw.point((x,y),rgb_color) elif asphalt_type == 2: rgb_color = random.choice(COLOR_LIST[3:45]) draw.point((x,y),rgb_color) else: rgb_color = random.choice([BLACK, WHITE]) draw.point((x,y),rgb_color) #draw asphalt shapes shape_number = 6000 for z in range(shape_number): #generate random center point coordinates for the shapes min_max = 1, 3 p = Point2d( random.randint(min_max[1], texture_img.size[0]-min_max[1]), random.randint(min_max[1], texture_img.size[1]-min_max[1]), ) inlay_darkening = random.randint(0, 80) shape_colors = [( v + random.randint(-10, 10), v + random.randint(-15, 10), v + random.randint(-20, 10), ) for v in _int_ramp(169 - inlay_darkening, 220 - inlay_darkening, 4)] draw_asphalt_shape(p, texture_img, defects_img, depth_img, shape_colors, min_max) ################### generates potholes################################ #min_max = 9,21 #for n in range(number_of_cracks): #px = random.randint(0,width) #py = random.randint(0,height) #p = Point2d(px, py) #pothole_generater(p, texture_img, defects_img, depth_img, min_max, 30) ####################################################################### generate_cracks(texture_img, defects_img, depth_img, crack_length, crack_width, number_of_cracks) texture_img.save(img_destination) defects_img.save(img_defects_destination) depth_img.save(img_depth_destination)