Python: how to create a submatrix discretizing a c

2019-07-22 15:11发布

In a 2D square grid (matrix) full of zeros, I need to create a submatrix full of ones, with the shape of this submatrix being as close as possible to a circle. I know a circle cannot be precisely represented when you work with cells or pixels, therefore I aim at a discretized circle.

The best thing I could come up with was this code, which produces square submatrices (the blue square in the image below):

from __future__ import division 
import numpy
import matplotlib.pyplot as plt
import matplotlib.colors as mc
import random
import os
import math

n=101 #Grid size
empty_lattice=numpy.zeros((n,n)) #The empty 2D grid
x=int(numpy.random.uniform(0,n-1)) #X coord. top left corner
y=int(numpy.random.uniform(0,n-1)) #Y coord. top left corner
side=int(numpy.random.uniform(15,n)) #Side of the square approximating the circle
max_y=n-y #Checks the distance between the y of the submatrix origin and the matrix vertical boundary
max_x=n-x #Checks the distance between the x of the submatrix origin and the matrix horizontal boundary
max_width=0 #Initializes a maximum width for the loading submatrix
if max_y<max_x: #This assigns the minimum value between max_y and max_x to max_width, so that the submatrix is always a square
    max_width=max_y
else:
    max_width=max_x     
if side>max_width:
    for i in range(0,max_width):
        for j in range(0, max_width):
            empty_lattice[x+i][y+j]=1
else:
    for i in range(0, side):
        for j in range(0, side):
            empty_lattice[x+i][y+j]=1

Now, visually this translates into the following image, but as you know there is a noticeable difference between the blue square and the inscribed circle in terms of area: enter image description here

My question: how could I amend my code in order to be able to "smooth" the corners of my squares so that something which resembles a circle appears?

EDIT

The circles should be drawn even if they do not entirely reside within the grid boundaries (look at the image).

1条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-07-22 15:16

This function fills in a circle of 1s that looks pretty good.

def fill_cell(cell, corner, rad):
    m, n = cell.shape
    ctr = corner[0]+m/2, corner[1]+n/2
    x = np.arange(m) - ctr[0]
    y = np.arange(n) - ctr[1]
    X,Y = np.meshgrid(x, y, order='ij')  # could try order='xy'
    Z = ((X**2 + Y**2)<= rad**2).astype(cell.dtype)
    return Z
empty_lattice[:] = fill_cell(empty_lattice, (x,y),side/2)

Position in empty_lattice is not right - because of a difference in how you are defining the x,y coordinates and my assumptions, but I think you can sort that out.

Radius looks good, though it might be off by an integer.

To fill in multiple circles, you could iterate over the x,y values, and assign lattice values for a slice (view)

xyslice = slice(x,15), slice(y,15)
empty_lattice[xyslice] = fill_cell(empty_lattice[xyslice],...)

For overlapping circles I'd look into some sort of logical assignment

empty_lattice[xyslice] |= fill_cell(...)
查看更多
登录 后发表回答