Last active
February 18, 2022 04:00
-
-
Save soravux/c0dd721414e0b36aef28582f906dc7de to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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