Skip to content

Instantly share code, notes, and snippets.

@soravux
Last active February 18, 2022 04:00
Show Gist options
  • Save soravux/c0dd721414e0b36aef28582f906dc7de to your computer and use it in GitHub Desktop.
Save soravux/c0dd721414e0b36aef28582f906dc7de to your computer and use it in GitHub Desktop.
import cv2
#from scipy.ndimage import gaussian_filter, uniform_filter
from cupyx.scipy.ndimage import gaussian_filter, uniform_filter
#import numpy as np
import cupy as np # don't laugh
# inspired by https://www.youtube.com/watch?v=X-iSQQgOd1A
speed = 2
damping = 0.03
steering = 0.9
turn_randomness = 0.3
straight_randomness = 0.1
#sense_angle = 0.33333*np.pi
sense_angle = 0.3*np.pi
img = np.zeros((1080, 2048, 3), dtype=np.float32)
# representation [y, x, angle, c] columns
agents = np.zeros((300_000, 3, 3), dtype=np.float32)
agents[:,0,:] = np.random.randint(0, img.shape[0] - 1, size=(agents.shape[0], 3))
agents[:,1,:] = np.random.randint(0, img.shape[1] - 1, size=(agents.shape[0], 3))
agents[:,2,:] = 2*np.pi*np.random.rand(agents.shape[0], 3)
def step(agents):
"""Move agents forward, bounce on the border"""
for c in range(3):
agents[:,2,c] = agents[:,2,c] % (2*np.pi)
dy = speed*np.sin(agents[:,2,c])
dx = speed*np.cos(agents[:,2,c])
bounce_top = (agents[:,0,c] + dy) < 0
bounce_bottom = (agents[:,0,c] + dy) >= img.shape[0]
bounce_right = (agents[:,1,c] + dx) >= img.shape[1]
bounce_left = (agents[:,1,c] + dx) < 0
agents[bounce_top,2,c] = -agents[bounce_top,2,c]
agents[bounce_bottom,2,c] = -agents[bounce_bottom,2,c]
agents[bounce_right,2,c] = (-(agents[bounce_right,2,c] - np.pi/2) + np.pi/2)
agents[bounce_left,2,c] = (-(agents[bounce_left,2,c] - np.pi/2) + np.pi/2)
agents[:,2,c] = agents[:,2,c] % (2*np.pi)
agents[:,0,c] += speed*np.sin(agents[:,2,c])
agents[:,1,c] += speed*np.cos(agents[:,2,c])
def getVal(img, pos, angle, step, c):
dir_y = np.round(np.sin(angle))
dir_x = np.round(np.cos(angle))
direction = np.vstack((dir_y, dir_x)).T
new_pos = (pos + step*direction).astype('int16')
new_pos[:,0] = np.clip(new_pos[:,0], 0, img.shape[0] - 1)
new_pos[:,1] = np.clip(new_pos[:,1], 0, img.shape[1] - 1)
return img[new_pos[:,0], new_pos[:,1], c], np.sum(img[new_pos[:,0], new_pos[:,1], :], axis=1)
ta = sense_angle
def sense(img, agents):
for c in range(3):
pos = agents[:,:2,c].astype('int16')
front = left = right = 0
for i in range(4):
front, front_total = getVal(img, pos, agents[:,2,c], (i+1), c)
left, left_total = getVal(img, pos, agents[:,2,c] + ta, (i+1), c)
right, right_total = getVal(img, pos, agents[:,2,c] - ta, (i+1), c)
if c == 2:
front /= front_total
left /= left_total
right /= right_total
else:
front = front_total - front
left = left_total - left
right = right_total - right
left_most = np.logical_and(left > right, left > front)
right_most = np.logical_and(right > left, right > front)
rot = np.zeros_like(agents[:,2,c])
rot[left_most] = ta*((1 - turn_randomness) + 2*turn_randomness*np.random.rand(int(left_most.sum().item())))
rot[right_most] = -ta*((1 - turn_randomness) + 2*turn_randomness*np.random.rand(int(right_most.sum().item())))
center = np.logical_and(~left_most, ~right_most)
rot[center] = 2*straight_randomness*(np.random.rand(int(center.sum().item())) - 0.5)
agents[:,2,c] = (1-steering)*agents[:,2,c] + steering*(agents[:,2,c] + rot)
print("press q to quit")
overall_step = 0
while True:
step(agents)
sense(img, agents)
img = np.maximum(img - damping, 0)
#img = np.clip(img - damping, 0, 10)
e = 1/1000*(-abs(overall_step - 1000) + 1000) + 0.2
for c in range(3):
img[agents[:,0,c].astype('int16'),agents[:,1,c].astype('int16'),c] = 1 # + 1 also gives interesting results
img[:,:,c] = uniform_filter(img[:,:,c], 3)
if hasattr(np, 'asnumpy'):
cv2.imshow('image', np.asnumpy(img**e))
else:
cv2.imshow('image', img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
overall_step = (overall_step + 1) % 2000
cv2.destroyAllWindows()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment