I want to draw evenly distributed random lines on a image.
My thought is to generate evenly distributed points on the image, and connect each two of them randomly. (Please ignore the bug of lacking coordinates on the 2 edges. I will fix them at last.)
from PIL import Image, ImageDraw
import random
# set attrs
gap = 170 # gap between points
err = 10 # volatility of coordinates
linewidth = 20 # line width
img = Image.open("img2.png", mode="r")
# initiation data/var
draw = ImageDraw.Draw(img)
width, height = img.size
class Coord:
def __init__(self, x, y):
self.x = x
self.y = y
currx = 0
curry = 0
coordlist = []
# generate the set of points
while currx <= width:
while curry <= height:
coordlist.append(Coord( \
currx + random.randint(-err,err), \
curry + random.randint(-err,err) \
))
curry += gap
curry = gap
currx += gap
# draw line between each two random points
while len(coordlist) >= 2:
# pick indices
index1 = random.randint(0, len(coordlist)-1)
index2 = random.randint(0, len(coordlist)-1)
while index1 == index2:
index2 = random.randint(0, len(coordlist)-1)
# draw line
draw.line((coordlist[index1].x,coordlist[index1].y, coordlist[index2].x,coordlist[index2].y), fill='black', width=linewidth)
# remove elements
coordlist = [v for i,v in enumerate(coordlist) if i not in frozenset((index1, index2))]
img.show()
However, this method is too inconsistent and sometimes some lines will stick together, causing some areas to be much more dense than other areas:
I figured it out myself with help from the comments.
The idea is to set those evenly distributed grid points as the start points, and use a random angle with sin/cos to generate random lines.
async def process_img(gap: int, err: int, linewidth: int, url: str):
with urllib.request.urlopen(url) as webimg:
with open('temp.jpg', 'wb') as f:
f.write(webimg.read())
img = Image.open('temp.jpg')
# initiation data/var
draw = ImageDraw.Draw(img)
width, height = img.size
class Coord:
def __init__(self, x, y):
self.x = x
self.y = y
currx = 0
curry = 0
coordlist = []
# generate the set of points
while currx <= width:
while curry <= height:
coordlist.append(Coord( \
currx + random.randint(0,err), \
curry + random.randint(0,err) \
))
curry += gap
curry = gap
currx += gap
# calculate endpoint with angle/length
def calcEnd(x, y, angle, length):
endx = int(x - (math.cos(math.radians(angle)) * length))
endy = int(y - (math.sin(math.radians(angle)) * length))
return endx, endy
# draw line with random angle/length
for c in coordlist:
length = LENGTH
randangle = random.randint(0,359)
endx, endy = calcEnd(c.x, c.y, randangle, length)
draw.line((c.x, c.y, endx, endy), fill='black', width=linewidth)
img.convert('RGB').save('outtemp.jpg')
img_path = Path() / "outtemp.jpg"
return img_path.resolve()