def apply_gabor(image) -> np.array: lg = LogGabor("parameters.py") lg.set_size(image) image[:, :, 0] = image[:, :, 0]*lg.mask image[:, :, 1] = image[:, :, 1]*lg.mask image[:, :, 2] = image[:, :, 2]*lg.mask return image
def theta_E(self, im, X_, Y_, w): try: assert (self.slip.N_X == im.shape[1]) except: from NeuroTools.parameters import ParameterSet from SLIP import Image from LogGabor import LogGabor self.slip = Image( ParameterSet({ 'N_X': im.shape[1], 'N_Y': im.shape[0] })) self.lg = LogGabor(self.slip) im_ = im.sum(axis=-1) im_ = im_ * np.exp(-.5 * ((.5 + .5 * self.slip.x - Y_)**2 + (.5 + .5 * self.slip.y - X_)**2) / w**2) E = np.zeros((self.N_theta, )) for i_theta, theta in enumerate(self.thetas): params = { 'sf_0': self.sf_0, 'B_sf': self.B_sf, 'theta': theta, 'B_theta': np.pi / self.N_theta } FT_lg = self.lg.loggabor(0, 0, **params) E[i_theta] = np.sum( np.absolute( self.slip.FTfilter(np.rot90(im_, -1), FT_lg, full=True))**2) return E
def theta_E(self, im, X_, Y_, w): try: assert(self.slip.N_X==im.shape[1]) except: from NeuroTools.parameters import ParameterSet from SLIP import Image from LogGabor import LogGabor self.slip = Image(ParameterSet({'N_X':im.shape[1], 'N_Y':im.shape[0]})) self.lg = LogGabor(self.slip) im_ = im.sum(axis=-1) im_ = im_ * np.exp(-.5*((.5 + .5*self.slip.x-Y_)**2+(.5 + .5*self.slip.y-X_)**2)/w**2) E = np.zeros((self.N_theta,)) for i_theta, theta in enumerate(self.thetas): params= {'sf_0':self.sf_0, 'B_sf':self.B_sf, 'theta':theta, 'B_theta': np.pi/self.N_theta} FT_lg = self.lg.loggabor(0, 0, **params) E[i_theta] = np.sum(np.absolute(self.slip.FTfilter(np.rot90(im_, -1), FT_lg, full=True))**2) return E
def get_shape_of_filtered_image(image_file_path): image = imread(image_file_path) lg = LogGabor('default_param.py') lg.set_size(image) i_level = 0 theta = 0 params = { 'sf_0': 1. / (2**i_level), 'B_sf': lg.pe.B_sf, 'theta': theta, 'B_theta': lg.pe.B_theta } FT_lg = lg.loggabor(0, 0, **params) filtered_img_mat = lg.FTfilter(image, FT_lg, full=True) return filtered_img_mat.shape
def get_gabor_features(image_file_path, num_levels, num_orientations): image = imread(image_file_path) opts = { 'vmin': 0., 'vmax': 1., 'interpolation': 'nearest', 'origin': 'upper' } # image = skimage.io.imread lg = LogGabor('default_param.py') lg.set_size(image) # num_features = num_levels*num_orientations*2 # feature_vec = np.zeros((num_features,1)) # phi = (np.sqrt(5) +1.)/2. # golden number # fig = plt.figure(figsize=(fig_width, fig_width/phi)) # xmin, ymin, size = 0, 0, 1. i = 0 for i_level in range(num_levels): # for theta in np.linspace(0, np.pi, num_orientations, endpoint=False): for theta in np.linspace(0, np.pi, num_orientations, endpoint=False): params = { 'sf_0': 1. / (2**i_level), 'B_sf': lg.pe.B_sf, 'theta': theta, 'B_theta': lg.pe.B_theta } # loggabor takes as args: u, v, sf_0, B_sf, theta, B_theta) FT_lg = lg.loggabor(0, 0, **params) filtered_img_mat = lg.FTfilter(image, FT_lg, full=True) # print "SHAPE OF FILTERED IMAGE IS (%s, %s)" % filtered_img_mat.shape im_abs_feature = np.absolute(filtered_img_mat).flatten() # im_abs_feature = np.sum(np.absolute(filtered_img_mat)) # im_sqr_feature = np.sum(np.square(np.real(filtered_img_mat))) # im_sqr_feature = np.sum(np.square(filtered_img_mat)) if i == 0: feature_vec = im_abs_feature else: feature_vec = np.hstack((feature_vec, im_abs_feature)) i += 1 print return feature_vec
0, '/home/qiang/QiangLi/Python_Utils_Functional/FirstVersion-BioMulti-L-NL-Model-ongoing/SLIP/SLIP' ) from SLIP import Image #LogGabor can be install in the first time but when you second time install it, #It will cause error. Here for how to fix it. #!pip3 install --upgrade pip setuptools wheel #!sudo apt-get install libpq-dev sys.path.insert( 0, '/home/qiang/QiangLi/Python_Utils_Functional/FirstVersion-BioMulti-L-NL-Model-ongoing/LogGabor/LogGabor' ) from LogGabor import LogGabor parameterfile = '/home/qiang/QiangLi/Python_Utils_Functional/FirstVersion-BioMulti-L-NL-Model-ongoing/LogGabor/default_param.py' lg = LogGabor(parameterfile) print('It works on 23 April2020') #DWT wavelet filters sys.path.insert( 0, '/home/qiang/QiangLi/Python_Utils_Functional/FirstVersion-BioMulti-L-NL-Model-ongoing/' ) from nt_toolbox.general import * from nt_toolbox.signal import * from nt_toolbox.compute_wavelet_filter import * print('It works on 27 April2020') warnings.filterwarnings('ignore') #%matplotlib inline
def vectorization(N_theta=N_theta, N_azimuth=N_azimuth, N_eccentricity=N_eccentricity, N_phase=N_phase, N_X=N_X, N_Y=N_Y, rho=rho, ecc_max=.8, B_sf=.4, B_theta=np.pi / N_theta / 2, figure_type='', save=False): retina = np.zeros((N_theta, N_azimuth, N_eccentricity, N_phase, N_X * N_Y)) parameterfile = 'https://raw.githubusercontent.com/bicv/LogGabor/master/default_param.py' lg = LogGabor(parameterfile) lg.set_size((N_X, N_Y)) # params = {'sf_0': .1, 'B_sf': lg.pe.B_sf, # 'theta': np.pi * 5 / 7., 'B_theta': lg.pe.B_theta} # phase = np.pi/4 # edge = lg.normalize(lg.invert(lg.loggabor( # N_X/3, 3*N_Y/4, **params)*np.exp(-1j*phase))) for i_theta in range(N_theta): for i_azimuth in range(N_azimuth): for i_eccentricity in range(N_eccentricity): ecc = ecc_max * (1 / rho)**(N_eccentricity - i_eccentricity) r = np.sqrt(N_X**2 + N_Y**2) / 2 * ecc # radius sf_0 = 0.5 * 0.03 / ecc x = N_X/2 + r * \ np.cos((i_azimuth+(i_eccentricity % 2)*.5)*np.pi*2 / N_azimuth) y = N_Y/2 + r * \ np.sin((i_azimuth+(i_eccentricity % 2)*.5)*np.pi*2 / N_azimuth) for i_phase in range(N_phase): params = { 'sf_0': sf_0, 'B_sf': B_sf, 'theta': i_theta * np.pi / N_theta, 'B_theta': B_theta } phase = i_phase * np.pi / 2 # print(r, x, y, phase, params) retina[i_theta, i_azimuth, i_eccentricity, i_phase, :] = lg.normalize( lg.invert( lg.loggabor(x, y, **params) * np.exp(-1j * phase))).ravel() if figure_type == 'retina': FIG_WIDTH = 10 fig, ax = plt.subplots(figsize=(FIG_WIDTH, FIG_WIDTH)) for i_theta in range(N_theta): for i_azimuth in range(N_azimuth): for i_eccentricity in range(N_eccentricity): env = np.sqrt(retina[i_theta, i_azimuth, i_eccentricity, 0, :]**2 + retina[i_theta, i_azimuth, i_eccentricity, 1, :]**2).reshape((N_X, N_Y)) ax.contourf(env, levels=[env.max() / 1.2, env.max() / 1.00001], lw=1, colors=[plt.cm.viridis(i_theta / (N_theta))], alpha=.1) fig.suptitle('Tiling of visual space using the retinal filters') ax.set_xlabel(r'$Y$') ax.set_ylabel(r'$X$') ax.axis('equal') if save: plt.savefig('retina_filter.pdf') plt.tight_layout() return fig, ax elif figure_type == 'colliculus': FIG_WIDTH = 10 fig, ax = plt.subplots(figsize=(FIG_WIDTH, FIG_WIDTH)) for i_azimuth in range(N_azimuth): for i_eccentricity in range(N_eccentricity): env = np.sqrt(colliculus[i_azimuth, i_eccentricity, :]**2.5).reshape( (N_X, N_Y)) #ax.contour(colliculus[i_azimuth, i_eccentricity, :].reshape((N_X, N_Y)), levels=[env.max()/2], lw=1, colors=[plt.cm.viridis(i_theta/(N_theta))]) ax.contourf( env, levels=[env.max() / 1.2, env.max() / 1.00001], lw=1, colors=[plt.cm.viridis(i_eccentricity / (N_eccentricity))], alpha=.1) fig.suptitle('Tiling of visual space using energy') ax.set_xlabel(r'$Y$') ax.set_ylabel(r'$X$') ax.axis('equal') plt.tight_layout() if save: plt.savefig('colliculus_filter.pdf') return fig, ax else: return retina
import numpy as np import cv2 from matplotlib import pyplot as plt from LogGabor import LogGabor lg = LogGabor("default_param.py") exit(0) lg.set_size(image) fig_width = 512 phi = (np.sqrt(5) +1.)/2. # golden number fig = plt.figure(figsize=(fig_width, fig_width/phi)) xmin, ymin, size = 0, 0, 1. for i_level in range(8): a = fig.add_axes((xmin/phi, ymin, size/phi, size), axisbg='w') a.axis(c='b', lw=0) plt.setp(a, xticks=[]) plt.setp(a, yticks=[]) im_RGB = np.zeros((lg.N_X, lg.N_Y, 3)) for theta in np.linspace(0, np.pi, 8, endpoint=False): params = {'sf_0':1./(2**i_level), 'B_sf':lg.pe.B_sf, 'theta':theta, 'B_theta':lg.pe.B_theta} # loggabor takes as args: u, v, sf_0, B_sf, theta, B_theta) FT_lg = lg.loggabor(0, 0, **params) im_abs = np.absolute(lg.FTfilter(image, FT_lg, full=True)) RGB = np.array([.5*np.sin(2*theta + 2*i*np.pi/3)+.5 for i in range(3)]) im_RGB += im_abs[:,:, np.newaxis] * RGB[np.newaxis, np.newaxis, :] im_RGB /= im_RGB.max()
class EdgeGrid(): def __init__( self, N_lame=8 * 72, N_lame_X=None, figsize=13, line_width=4., grid_type='hex', structure=False, struct_angles=[-15., -65., -102.], verb=False, mode='both', filename=None, period=None, #**kw_args ): self.t0 = self.time(True) self.t = self.time() self.dt = self.t - self.t0 self.verb = verb self.display = (mode == 'display') or (mode == 'both') self.stream = (mode == 'stream') or (mode == 'display') #if mode=='display': self.stream = True self.filename = filename self.serial = ( mode == 'serial' ) # converting a stream to the serial port to control the arduino if self.serial: self.verb = True # self.desired_fps = 750. self.desired_fps = 30. self.structure = structure self.screenshot = True # saves a screenshot after the rendering self.port = "5556" # moteur: self.serial_port, self.baud_rate = '/dev/ttyUSB0', 115200 # 1.8 deg par pas (=200 pas par tour) x 32 divisions de pas # demultiplication : pignon1= 14 dents, pignon2 = 60 dents self.n_pas = 200. * 32. * 60 / 14 # TODO : Vitesse Max moteur = 1 tour en 3,88 self.n_pas_max = 148 # 150 # taille installation self.total_width = 8 # en mètres self.lames_width = 5 # en mètres self.lames_height = 3 # en mètres self.background_depth = 100 # taille du 104 en profondeur self.f = .1 self.struct_N = 6 self.struct_position = [0., 3.5] self.struct_longueur = 3. self.struct_angles = struct_angles self.figsize = figsize self.line_width = line_width self.grid_type = grid_type self.grid(N_lame=N_lame, N_lame_X=N_lame_X) # self.lames[2, :] = np.pi*np.random.rand(self.N_lame) self.N_particles_per_lame = 2**3 self.N_particles = self.struct_N * self.N_particles_per_lame if structure: self.sample_structure() # enregistrement / playback self.period = period self.load() self.vext = '.mp4' self.figpath = '../files/figures/elasticite/' self.fps = 25 def load(self): if not self.filename is None: if os.path.isfile(self.filename): # le fichier existe, on charge self.z = np.load(self.filename) self.period = self.z[:, 0].max() def time(self, init=False): if init: return time.time() else: return time.time() - self.t0 def grid(self, N_lame, N_lame_X): """ The coordinates of the screen are centered on the (0, 0) point and axis are the classical convention: y ^ | +---> x angles are from the horizontal, then in trigonometric order (anticlockwise) """ self.DEBUG = True self.DEBUG = False self.N_lame = N_lame #if N_lame_X is None: if self.grid_type == 'hex': self.N_lame_X = np.int(np.sqrt(self.N_lame)) #*np.sqrt(3) / 2) self.lames = np.zeros((4, self.N_lame)) self.lames[0, :] = np.mod(np.arange(self.N_lame), self.N_lame_X) self.lames[0, :] += np.mod( np.floor(np.arange(self.N_lame) / self.N_lame_X), 2) / 2 self.lames[1, :] = np.floor(np.arange(self.N_lame) / self.N_lame_X) self.lames[1, :] *= np.sqrt(3) / 2 self.lames[0, :] /= self.N_lame_X self.lames[1, :] /= self.N_lame_X self.lames[0, :] += .5 / self.N_lame_X - .5 self.lames[ 1, :] += 1.5 / self.N_lame_X # TODO : prove analytically self.lames[0, :] *= self.total_width self.lames[1, :] *= self.total_width self.lames[1, :] -= self.total_width / 2 self.lame_length = .99 / self.N_lame_X * self.total_width * np.ones( self.N_lame) self.lame_width = .03 / self.N_lame_X * self.total_width * np.ones( self.N_lame) elif self.grid_type == 'line': self.N_lame_X = self.N_lame self.lames = np.zeros((4, self.N_lame)) self.lames[0, :] = np.linspace(-self.lames_width / 2, self.lames_width / 2, self.N_lame, endpoint=True) #self.lames[1, :] = self.total_width/2 self.lame_length = .12 * np.ones(self.N_lame) # en mètres self.lame_width = .042 * np.ones(self.N_lame) # en mètres if self.structure: self.add_structure() self.lames_minmax = np.array([ self.lames[0, :].min(), self.lames[0, :].max(), self.lames[1, :].min(), self.lames[1, :].max() ]) def do_structure(self): structure_ = np.zeros((3, self.struct_N)) chain = np.zeros((2, 4)) chain[:, 0] = np.array(self.struct_position).T for i, angle in enumerate(self.struct_angles): chain[0, i + 1] = chain[0, i] + self.struct_longueur * np.cos( angle * np.pi / 180.) chain[1, i + 1] = chain[1, i] + self.struct_longueur * np.sin( angle * np.pi / 180.) structure_[2, 3 + i] = +angle * np.pi / 180. structure_[2, i] = np.pi - angle * np.pi / 180 structure_[0, 3:] = .5 * (chain[0, 1:] + chain[0, :-1]) structure_[0, :3] = -.5 * (chain[0, 1:] + chain[0, :-1]) structure_[1, 3:] = .5 * (chain[1, 1:] + chain[1, :-1]) structure_[1, :3] = .5 * (chain[1, 1:] + chain[1, :-1]) return structure_ def add_structure(self): self.N_lame += self.struct_N self.lames = np.hstack((self.lames, np.zeros((4, self.struct_N)))) self.lames[:3, -self.struct_N:] = self.do_structure() self.lame_length = np.hstack( (self.lame_length, self.struct_longueur * np.ones(self.struct_N))) # en mètres self.lame_width = np.hstack( (self.lame_width, .042 * np.ones(self.struct_N))) # en mètres def sample_structure(self, N_mirror=0, alpha=.8): struct = self.lames[:3, -self.struct_N:] self.particles = np.ones((3, self.N_particles)) N_particles_ = self.N_particles / self.struct_N for i, vec in enumerate(struct.T.tolist()): x0, x1 = vec[0] - .5 * self.struct_longueur * np.cos( vec[2]), vec[0] + .5 * self.struct_longueur * np.cos(vec[2]) y0, y1 = vec[1] - .5 * self.struct_longueur * np.sin( vec[2]), vec[1] + .5 * self.struct_longueur * np.sin(vec[2]) self.particles[0, int(i * N_particles_):int((i + 1) * N_particles_)] = np.linspace( x0, x1, N_particles_) self.particles[1, int(i * N_particles_):int((i + 1) * N_particles_)] = np.linspace( y0, y1, N_particles_) # duplicate according to mirrors for i in range(N_mirror): particles = self.particles.copy( ) # the current structure to mirror particles_mirror = particles.copy( ) # the new set of particles with their mirror image for segment in self.structure_as_segments(): particles_mirror = np.hstack((particles_mirror, mirror(particles, segment, alpha**(i + 1)))) # print(alpha**(i+1), particles_mirror[-1, -1]) self.particles = particles_mirror def structure_as_segments(self): struct = self.lames[:3, -self.struct_N:] segments = [] for i, vec in enumerate(struct.T.tolist()): x0, x1 = vec[0] - .5 * self.struct_longueur * np.cos( vec[2]), vec[0] + .5 * self.struct_longueur * np.cos(vec[2]) y0, y1 = vec[1] - .5 * self.struct_longueur * np.sin( vec[2]), vec[1] + .5 * self.struct_longueur * np.sin(vec[2]) segments.append(np.array([[x0, y0], [x1, y1]]).T) return segments def theta_E(self, im, X_, Y_, w): try: assert (self.slip.N_X == im.shape[1]) except: from NeuroTools.parameters import ParameterSet from SLIP import Image from LogGabor import LogGabor self.slip = Image( ParameterSet({ 'N_X': im.shape[1], 'N_Y': im.shape[0] })) self.lg = LogGabor(self.slip) im_ = im.sum(axis=-1) im_ = im_ * np.exp(-.5 * ((.5 + .5 * self.slip.x - Y_)**2 + (.5 + .5 * self.slip.y - X_)**2) / w**2) E = np.zeros((self.N_theta, )) for i_theta, theta in enumerate(self.thetas): params = { 'sf_0': self.sf_0, 'B_sf': self.B_sf, 'theta': theta, 'B_theta': np.pi / self.N_theta } FT_lg = self.lg.loggabor(0, 0, **params) E[i_theta] = np.sum( np.absolute( self.slip.FTfilter(np.rot90(im_, -1), FT_lg, full=True))**2) return E def theta_max(self, im, X_, Y_, w): E = self.theta_E(im, X_, Y_, w) return self.thetas[np.argmax(E)] - np.pi / 2 def theta_sobel(self, im, N_blur): im_ = im.copy() sobel = np.array([[ 1, 2, 1, ], [ 0, 0, 0, ], [ -1, -2, -1, ]]) if im_.ndim == 3: im_ = im_.sum(axis=-1) from scipy.signal import convolve2d im_X = convolve2d(im_, sobel, 'same') im_Y = convolve2d(im_, sobel.T, 'same') N_X, N_Y = im_.shape x, y = np.mgrid[0:1:1j * N_X, 0:1:1j * N_Y] mask = np.exp(-.5 * ((x - .5)**2 + (y - .5)**2) / w**2) im_X = convolve2d(im_X, mask, 'same') im_Y = convolve2d(im_Y, mask, 'same') blur = np.array([[1, 2, 1], [2, 8, 2], [1, 2, 1]]) for i in range(N_blur): im_X = convolve2d(im_X, blur, 'same') im_Y = convolve2d(im_Y, blur, 'same') angle = np.arctan2(im_Y, im_X) bord = .1 angles = np.empty(self.N_lame) N_X, N_Y = im_.shape for i in range(self.N_lame): angles[i] = angle[int( (bord + self.lames[0, i] * (1 - 2 * bord)) * N_X), int((bord + self.lames[1, i] * (1 - 2 * bord)) * N_Y)] return angles - np.pi / 2 def pos_rel(self, do_torus=False): def torus(x, w=1.): """ center x in the range [-w/2., w/2.] To see what this does, try out: >> x = np.linspace(-4,4,100) >> pylab.plot(x, torus(x, 2.)) """ return np.mod(x + w / 2., w) - w / 2. dx = self.lames[0, :, np.newaxis] - self.lames[0, np.newaxis, :] dy = self.lames[1, :, np.newaxis] - self.lames[1, np.newaxis, :] if do_torus: return torus(dx), torus(dy) else: return dx, dy def distance(self, do_torus=False): dx, dy = self.pos_rel(do_torus=do_torus) return np.sqrt(dx**2 + dy**2) def angle_relatif(self): return self.lames[2, :, np.newaxis] - self.lames[2, np.newaxis, :] def angle_cocir(self, do_torus=False): dx, dy = self.pos_rel(do_torus=do_torus) theta = self.angle_relatif() return np.arctan2(dy, dx) - np.pi / 2 - theta def champ(self): if self.structure: N_lame = self.N_lame - self.struct_N else: N_lame = self.N_lame force = np.zeros_like(self.lames[2, :N_lame]) noise = lambda t: 0.2 * np.exp((np.cos(2 * np.pi * (t - 0.) / 6.) - 1.) / 1.5**2) damp = lambda t: 0.01 #* np.exp(np.cos(t / 6.) / 3.**2) colin_t = lambda t: -.1 * np.exp((np.cos(2 * np.pi * (t - 2.) / 6.) - 1.) / .3**2) cocir_t = lambda t: -4. * np.exp((np.cos(2 * np.pi * (t - 4.) / 6.) - 1.) / .5**2) cocir_d = lambda d: np.exp(-d / .05) colin_d = lambda d: np.exp(-d / .2) force += colin_t( self.t) * np.sum(np.sin(2 * (self.angle_relatif()[:N_lame])) * colin_d(self.distance()[:N_lame]), axis=1) force += cocir_t( self.t) * np.sum(np.sin(2 * (self.angle_cocir()[:N_lame])) * cocir_d(self.distance()[:N_lame]), axis=1) force += noise(self.t) * np.pi * np.random.randn(N_lame) force -= damp(self.t) * self.lames[3, :N_lame] / self.dt return 42. * force def update(self): if self.structure: N_lame = self.N_lame - self.struct_N else: N_lame = self.N_lame self.lames[2, :N_lame] += self.lames[3, :N_lame] * self.dt / 2 self.lames[3, :N_lame] += self.champ() * self.dt self.lames[2, :N_lame] += self.lames[3, :N_lame] * self.dt / 2 # angles are defined as non oriented between -pi/2 and pi/2 self.lames[2, :N_lame] = np.mod(self.lames[2, :N_lame] + np.pi / 2, np.pi) - np.pi / 2 def receive(self): if not self.filename is None: if os.path.isfile(self.filename): if self.structure: N_lame = self.N_lame - self.struct_N else: N_lame = self.N_lame self.t = self.time() i_t = np.argmin(self.z[:, 0] < np.mod(self.t, self.period)) if self.verb: print("playback at t=", np.mod(self.t, self.period), i_t) self.lames[2, :N_lame] = self.z[i_t, 1:] return if self.stream: if self.verb: print("Sending request") self.socket.send(b"Hello") if self.verb: print("Received reply ", message) self.lames[2, :] = recv_array(self.socket) if self.verb: print("Received reply ", Theta.shape) else: self.dt = self.time() - self.t self.update() self.t = self.time() # if not self.filename is None: # if not os.path.isfile(self.filename): # # recording # if self.verb: print("recording at t=", self.t) # self.z = np.vstack((self.z, np.hstack((np.array(self.t), self.lames[2, :] )))) return def render(self, fps=10, W=1000, H=618, location=[0, 1.75, -5], head_size=.4, light_intensity=1.2, reflection=1., look_at=[0, 1.5, 0], fov=75, antialiasing=0.001, duration=5, fname='/tmp/temp.mp4'): def scene(t): """ Returns the scene at time 't' (in seconds) """ head_location = np.array(location) - np.array([0, 0, head_size]) import vapory light = vapory.LightSource([15, 15, 1], 'color', [light_intensity] * 3) background = vapory.Box( [0, 0, 0], [1, 1, 1], vapory.Texture( vapory.Pigment( vapory.ImageMap('png', '"../files/VISUEL_104.png"', 'once')), vapory.Finish('ambient', 1.2)), 'scale', [self.background_depth, self.background_depth, 0], 'translate', [ -self.background_depth / 2, -.45 * self.background_depth, -self.background_depth / 2 ]) me = vapory.Sphere( head_location, head_size, vapory.Texture(vapory.Pigment('color', [1, 0, 1]))) self.t = t self.update() objects = [background, me, light] for i_lame in range(self.N_lame): #print(i_lame, self.lame_length[i_lame], self.lame_width[i_lame]) objects.append( vapory.Box( [ -self.lame_length[i_lame] / 2, 0, -self.lame_width[i_lame] / 2 ], [ self.lame_length[i_lame] / 2, self.lames_height, self.lame_width[i_lame] / 2 ], vapory.Pigment('color', [1, 1, 1]), vapory.Finish('phong', 0.8, 'reflection', reflection), 'rotate', (0, -self.lames[2, i_lame] * 180 / np.pi, 0), #HACK? 'translate', (self.lames[0, i_lame], 0, self.lames[1, i_lame]))) objects.append(light) return vapory.Scene(vapory.Camera('angle', fov, "location", location, "look_at", look_at), objects=objects, included=["glass.inc"]) import moviepy.editor as mpy if not os.path.isfile(fname): self.dt = 1. / fps def make_frame(t): return scene(t).render(width=W, height=H, antialiasing=antialiasing) clip = mpy.VideoClip(make_frame, duration=duration) clip.write_videofile(fname, fps=fps) return mpy.ipython_display(fname, fps=fps, loop=1, autoplay=1) def plot_structure(self, W=1000, H=618, fig=None, ax=None, border=0.0, opts=dict(vmin=-1, vmax=1., linewidths=0, cmap=None, alpha=.1, s=5.), scale='auto'): # opts.update(cmap=plt.cm.hsv) if fig is None: fig = plt.figure(figsize=(self.figsize, self.figsize * H / W)) if ax is None: ax = fig.add_axes((border, border, 1. - 2 * border, 1. - 2 * border)) #, axisbg='w') scat = ax.scatter(self.particles[0, ::-1], self.particles[1, ::-1], c=self.particles[2, ::-1], **opts) if type(scale) is float: ax.set_xlim([-scale, scale]) ax.set_ylim([-scale * H / W, scale * H / W]) elif not scale is 'auto': ax.set_xlim([-self.total_width, self.total_width]) ax.set_ylim([-self.total_width * H / W, self.total_width * H / W]) else: ax.set_xlim([ min(self.particles[0, :].min(), self.particles[1, :].min() / H * W), max(self.particles[0, :].max(), self.particles[1, :].max() / H * W) ]) ax.set_ylim([ min(self.particles[1, :].min(), self.particles[0, :].min() * H / W), max(self.particles[1, :].max(), self.particles[0, :].max() * H / W) ]) ax.axis('off') return fig, ax def animate(self, fps=10, W=1000, H=618, duration=20, scale='auto', fname=None): if fname is None: import tempfile fname = tempfile.mktemp() + '.mp4' import matplotlib.pyplot as plt self.dt = 1. / fps inches_per_pt = 1.0 / 72.27 from moviepy.video.io.bindings import mplfig_to_npimage import moviepy.editor as mpy def make_frame_mpl(t): self.t = t self.update() fig = plt.figure(figsize=(W * inches_per_pt, H * inches_per_pt)) fig, ax = self.plot_structure(fig=fig, ax=None, scale=scale) #ax.clear() ax.axis('off') #fig, ax = self.plot_structure(fig=fig, ax=ax) return mplfig_to_npimage(fig) # RGB image of the figure animation = mpy.VideoClip(make_frame_mpl, duration=duration) plt.close('all') animation.write_videofile(fname, fps=fps) return mpy.ipython_display(fname, fps=fps, loop=1, autoplay=1, width=W) def show_edges(self, fig=None, a=None): self.N_theta = 12 self.thetas = np.linspace(0, np.pi, self.N_theta) self.sf_0 = .3 self.B_sf = .3 """ Shows the quiver plot of a set of edges, optionally associated to an image. """ import pylab import matplotlib.cm as cm if fig == None: fig = pylab.figure(figsize=(self.figsize, self.figsize)) if a == None: border = 0.0 a = fig.add_axes( (border, border, 1. - 2 * border, 1. - 2 * border), axisbg='w') else: self.update_lines() marge = self.lame_length * 3. a.axis(self.lames_minmax + np.array([-marge, +marge, -marge, +marge])) a.add_collection(self.lines) a.axis(c='b', lw=0) pylab.setp(a, xticks=[]) pylab.setp(a, yticks=[]) pylab.draw() return fig, a #def set_lines(self): #from matplotlib.collections import LineCollection #import matplotlib.patches as patches # draw the segments #segments, colors, linewidths = list(), list(), list() # #X, Y, Theta = self.lames[0, :], self.lames[1, :].real, self.lames[2, :] #for x, y, theta in zip(X, Y, Theta): #u_, v_ = np.cos(theta)*self.lame_length, np.sin(theta)*self.lame_length #segments.append([(x - u_, y - v_), (x + u_, y + v_)]) #colors.append((0, 0, 0, 1))# black #linewidths.append(self.line_width) #return LineCollection(segments, linewidths=linewidths, colors=colors, linestyles='solid') def update_lines(self): from matplotlib.collections import LineCollection import matplotlib.patches as patches X, Y, Theta = self.lames[0, :], self.lames[1, :], self.lames[2, :] segments = list() for i, (x, y, theta) in enumerate(zip(X, Y, Theta)): u_, v_ = np.cos(theta) * self.lame_length, np.sin( theta) * self.lame_length segments.append([(x - u_, y - v_), (x + u_, y + v_)]) self.lines.set_segments(segments) def fname(self, name): return os.path.join(self.figpath, name + self.vext) def make_anim(self, name, make_lames, duration=3., redo=False): if redo or not os.path.isfile(self.fname(name)): import matplotlib.pyplot as plt from moviepy.video.io.bindings import mplfig_to_npimage import moviepy.editor as mpy fig_mpl, ax = plt.subplots(1, figsize=(self.figsize, self.figsize), facecolor='white') def make_frame_mpl(t): # on ne peut changer que l'orientation des lames: self.t = t self.lames[2, :] = make_lames(self) self.update_lines() fig_mpl, ax = self.show_edges() #fig_mpl, ax) self.t_old = t return mplfig_to_npimage(fig_mpl) # RGB image of the figure animation = mpy.VideoClip(make_frame_mpl, duration=duration) animation.write_videofile(self.fname(name), fps=self.fps)
def generate_spectrum_from_RDC(filename, numFrames=500, numADCSamples=128, numTxAntennas=3, numRxAntennas=4, numLoopsPerFrame=128, numAngleBins=64, chirpPeriod=0.06, logGabor=False, accumulate=True, save_full=False): numChirpsPerFrame = numTxAntennas * numLoopsPerFrame # ============================================================================= # numADCSamples = number of range bins # numLoopsPerFrame = number of doppler bins # ============================================================================= range_resolution, bandwidth = dsp.range_resolution(numADCSamples) doppler_resolution = dsp.doppler_resolution(bandwidth) if filename[-4:] != '.bin': filename += '.bin' adc_data = np.fromfile(filename, dtype=np.int16) adc_data = adc_data.reshape(numFrames, -1) adc_data = np.apply_along_axis(DCA1000.organize, 1, adc_data, num_chirps=numChirpsPerFrame, num_rx=numRxAntennas, num_samples=numADCSamples) print("Data Loaded!") dataCube = adc_data micro_doppler_data = np.zeros((numFrames, numLoopsPerFrame, numADCSamples), dtype=np.float64) theta_data = np.zeros((numFrames, numLoopsPerFrame, numTxAntennas * numRxAntennas, numADCSamples), dtype=np.complex) for i, frame in enumerate(dataCube): # (2) Range Processing from mmwave.dsp.utils import Window radar_cube = dsp.range_processing(frame, window_type_1d=Window.BLACKMAN) assert radar_cube.shape == ( numChirpsPerFrame, numRxAntennas, numADCSamples), "[ERROR] Radar cube is not the correct shape!" # (3) Doppler Processing det_matrix, theta_data[i] = dsp.doppler_processing( radar_cube, num_tx_antennas=3, clutter_removal_enabled=True, window_type_2d=Window.HAMMING) # --- Shifts & Store det_matrix_vis = np.fft.fftshift(det_matrix, axes=1) micro_doppler_data[i, :, :] = det_matrix_vis # Data should now be ready. Needs to be in micro_doppler_data, a 3D-numpy array with shape [numDoppler, numRanges, numFrames] # LOG GABOR if logGabor: if accumulate: image = micro_doppler_data.sum(axis=1).T else: image = micro_doppler_data.T from LogGabor import LogGabor import holoviews as hv lg = LogGabor("default_param.py") lg.set_size(image) lg.pe.datapath = 'database/' image = lg.normalize(image, center=True) # display input image # hv.Image(image) # display log gabor'd image image = lg.whitening(image) * lg.mask hv.Image(image) uDoppler = image elif accumulate: uDoppler = micro_doppler_data.sum(axis=1).T else: uDoppler = micro_doppler_data.T if save_full: return range_resolution, doppler_resolution, uDoppler, theta_data else: return range_resolution, doppler_resolution, uDoppler
from LogGabor import LogGabor import cv2 parameterfile = './lg_para.py' lg = LogGabor(parameterfile) image = cv2.imread("example1.jpg") gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) lg.set_size(gray)
def generate_gabors_coordinates(theta, params, N_X, N_Y, centers_coordinates, B_theta=15, sf_0=.05, B_sf=.5, distrib_size=8, grid_res=3, on_thresh=.1, off_thresh=-.1, verbose=True): ''' Given some gabor parameters, a set of coordinates for centering gabors, returns a set of coordinates for filters belonging into the gabors Params : theta : gabor theta angle params : the default parameters dictionnary for the gabor generation N_X, N_Y : Gabor size, usually the same as the video centers_coordinates : a 2D array giving the centers of each gabor B_theta, sf_0, B_sf : Parameters for the LogGabor shape B_theta is the opening of the gabor, sf_0 is the spatial frequency b_sf is the bandwidth frequency distrib_size : the size of each group of filters, in image coordinates grid_res : resolution of the group of filters, passed in a np.mgrid on_thresh, off_thresh : threshold at which a filter is selected to be on/off, by scanning the Gabor phi-space verbose : display the filter size as a sanity check ''' xs = centers_coordinates[0] ys = centers_coordinates[1] nbr_gabors = len(xs) N_X = int(N_X) N_Y = int(N_Y) N_phase = 2 lg = LogGabor(params) lg.set_size((N_X, N_Y)) B_theta = B_theta / 180 * np.pi params = {'sf_0': sf_0, 'B_sf': B_sf, 'B_theta': B_theta} params.update(theta=theta) phi = np.zeros((1, N_phase, N_X, N_Y)) filters_per_gab = [] for gab in range(nbr_gabors): x = xs[gab] y = ys[gab] for i_phase in range(N_phase): phase = i_phase * np.pi/2 kernel = lg.invert(lg.loggabor( x, y, **params)*np.exp(-1j*phase)) phi[0, i_phase, :] = lg.normalize(kernel) fx_min = x - distrib_size fx_max = x + distrib_size fy_min = y - distrib_size fy_max = y + distrib_size filters_coordinates = np.mgrid[fx_min:fx_max:grid_res, fy_min:fy_max:grid_res].reshape(2, -1).T if verbose and gab == 0: print('Thread started !\nFilter grid shape', filters_coordinates.shape, '\n') filters_in_gabor = gabor_connectivity(filters=filters_coordinates, phi=phi, theta=0, threshold=on_thresh) off_filters_in_gabor = gabor_connectivity(filters=filters_coordinates, phi=phi, theta=0, threshold=off_thresh, on=False) filters_per_gab.append((filters_in_gabor, off_filters_in_gabor)) return filters_per_gab
# LOG GABOR if logGabor: if accumulate: image = micro_doppler_data.sum(axis=1).T else: image = micro_doppler_data[:,120,:].T from LogGabor import LogGabor import holoviews as hv import os fig_width = 12 figsize=(fig_width, .618*fig_width) lg = LogGabor("default_param.py") lg.set_size(image) lg.pe.datapath = 'database/' image = lg.normalize(image, center=True) # display input image # hv.Image(image) # display log gabor'd image image = lg.whitening(image)*lg.mask hv.Image(image) uDoppler = image elif accumulate: uDoppler = micro_doppler_data.sum(axis=1).T
def get_gabor_features_texture_classification(image_file_path, num_levels, num_orientations): # image = imread(image_file_path) # image = skimage.io.imread(image_file_path) print 'length of image' print len(image_file_path.shape) if (len(image_file_path.shape) == 3): image = image_file_path[:, :, 0] else: image = image_file_path[:, :] opts = { 'vmin': 0., 'vmax': 1., 'interpolation': 'nearest', 'origin': 'upper' } print image.shape # image = image_file_path # image = image[30:70,30:70] sum_sqr_num_feat = num_levels * num_orientations sum_sqr_feat_vec = np.zeros((1, sum_sqr_num_feat)) print 'shape of sum sqr vec is:' print sum_sqr_feat_vec.shape lg = LogGabor('default_param.py') lg.set_size(image) # num_features = num_levels*num_orientations*2 # feature_vec = np.zeros((num_features,1)) # phi = (np.sqrt(5) +1.)/2. # golden number # fig = plt.figure(figsize=(fig_width, fig_width/phi)) # xmin, ymin, size = 0, 0, 1. i = 0 first_response = None for i_level in range(num_levels): # for theta in np.linspace(0, np.pi, num_orientations, endpoint=False): for theta in np.linspace(0, np.pi, num_orientations, endpoint=False): params = { 'sf_0': 1. / (2**i_level), 'B_sf': lg.pe.B_sf, 'theta': theta, 'B_theta': lg.pe.B_theta } # loggabor takes as args: u, v, sf_0, B_sf, theta, B_theta) FT_lg = lg.loggabor(0, 0, **params) filtered_img_mat = lg.FTfilter(image, FT_lg, full=True) # print "SHAPE OF FILTERED IMAGE IS (%s, %s)" % filtered_img_mat.shape im_abs_feature = np.absolute(filtered_img_mat).flatten() # im_abs_feature = np.sum(np.absolute(filtered_img_mat)) # im_sqr_feature = np.sum(np.square(np.real(filtered_img_mat))) # im_sqr_feature = np.sum(np.square(filtered_img_mat)) if i == 0: first_response = im_abs_feature.reshape( 1, im_abs_feature.shape[0]) # print type(im_abs_feature) # print im_abs_feature.shape # print im_abs_feature # print LA.norm(im_abs_feature.reshape(1, im_abs_feature.shape[0])) sum_sqr_feat_vec[0, i] = LA.norm( im_abs_feature.reshape(1, im_abs_feature.shape[0])) # print 'L2 norm squared is:' # print sum_sqr_feat_vec[0,i] # if i == 0: # feature_vec = im_abs_feature # else: # feature_vec = np.hstack((feature_vec, im_abs_feature)) i += 1 print return sum_sqr_feat_vec
class EdgeGrid(): def __init__(self, N_lame = 8*72, N_lame_X = None, figsize = 13, line_width = 4., grid_type = 'hex', structure = True, struct_angles = [-15., -65., -102.], verb = False, mode = 'both', filename = None, period = None, #**kw_args ): self.t0 = self.time(True) self.t = self.time() self.dt = self.t - self.t0 self.verb = verb self.display = (mode=='display') or (mode=='both') self.stream = (mode=='stream') or (mode=='display') #if mode=='display': self.stream = True self.filename = filename self.serial = (mode=='serial') # converting a stream to the serial port to control the arduino if self.serial: self.verb=True # self.desired_fps = 750. self.desired_fps = 30. self.structure = structure self.screenshot = True # saves a screenshot after the rendering self.port = "5556" # moteur: self.serial_port, self.baud_rate = '/dev/ttyUSB0', 115200 # 1.8 deg par pas (=200 pas par tour) x 32 divisions de pas # demultiplication : pignon1= 14 dents, pignon2 = 60 dents self.n_pas = 200. * 32. * 60 / 14 # TODO : Vitesse Max moteur = 1 tour en 3,88 self.n_pas_max = 148 # 150 # taille installation self.total_width = 8 # en mètres self.lames_width = 5 # en mètres self.lames_height = 3 # en mètres self.background_depth = 100 # taille du 104 en profondeur self.f = .1 self.struct_N = 6 self.struct_position = [0., 3.5] self.struct_longueur = 3. self.struct_angles = struct_angles self.figsize = figsize self.line_width = line_width self.grid_type = grid_type self.grid(N_lame=N_lame, N_lame_X=N_lame_X) # self.lames[2, :] = np.pi*np.random.rand(self.N_lame) self.N_particles_per_lame = 2**3 self.N_particles = self.struct_N * self.N_particles_per_lame if structure: self.sample_structure() # enregistrement / playback self.period = period self.load() def load(self): if not self.filename is None: if os.path.isfile(self.filename): # le fichier existe, on charge self.z = np.load(self.filename) self.period = self.z[:, 0].max() def time(self, init=False): if init: return time.time() else: return time.time() - self.t0 def grid(self, N_lame, N_lame_X): """ The coordinates of the screen are centered on the (0, 0) point and axis are the classical convention: y ^ | +---> x angles are from the horizontal, then in trigonometric order (anticlockwise) """ self.DEBUG = False self.DEBUG = True self.N_lame = N_lame #if N_lame_X is None: if self.grid_type=='hex': self.N_lame_X = np.int(np.sqrt(self.N_lame))#*np.sqrt(3) / 2) self.lames = np.zeros((4, self.N_lame)) self.lames[0, :] = np.mod(np.arange(self.N_lame), self.N_lame_X) self.lames[0, :] += np.mod(np.floor(np.arange(self.N_lame)/self.N_lame_X), 2)/2 self.lames[1, :] = np.floor(np.arange(self.N_lame)/self.N_lame_X) self.lames[1, :] *= np.sqrt(3) / 2 self.lames[0, :] /= self.N_lame_X self.lames[1, :] /= self.N_lame_X self.lames[0, :] += .5/self.N_lame_X - .5 self.lames[1, :] += 1.5/self.N_lame_X # TODO : prove analytically self.lames[0, :] *= self.total_width self.lames[1, :] *= self.total_width self.lame_length = .99/self.N_lame_X*self.total_width*np.ones(self.N_lame) self.lame_width = .03/self.N_lame_X*self.total_width*np.ones(self.N_lame) elif self.grid_type=='line': self.N_lame_X = self.N_lame self.lames = np.zeros((4, self.N_lame)) self.lames[0, :] = np.linspace(-self.lames_width/2, self.lames_width/2, self.N_lame, endpoint=True) #self.lames[1, :] = self.total_width/2 self.lame_length = .12*np.ones(self.N_lame) # en mètres self.lame_width = .042*np.ones(self.N_lame) # en mètres if self.structure: self.add_structure() self.lames_minmax = np.array([self.lames[0, :].min(), self.lames[0, :].max(), self.lames[1, :].min(), self.lames[1, :].max()]) def do_structure(self): structure_ = np.zeros((3, self.struct_N)) chain = np.zeros((2, 4)) chain[:, 0] = np.array(self.struct_position).T for i, angle in enumerate(self.struct_angles): chain[0, i+1] = chain[0, i] + self.struct_longueur*np.cos(angle*np.pi/180.) chain[1, i+1] = chain[1, i] + self.struct_longueur*np.sin(angle*np.pi/180.) structure_[2, 3+i] = +angle*np.pi/180. structure_[2, i] = np.pi-angle*np.pi/180 structure_[0, 3:] = .5*(chain[0, 1:]+chain[0, :-1]) structure_[0, :3] = -.5*(chain[0, 1:]+chain[0, :-1]) structure_[1, 3:] = .5*(chain[1, 1:]+chain[1, :-1]) structure_[1, :3] = .5*(chain[1, 1:]+chain[1, :-1]) return structure_ def add_structure(self): self.N_lame += self.struct_N self.lames = np.hstack((self.lames, np.zeros((4, self.struct_N)))) self.lames[:3, -self.struct_N:] = self.do_structure() self.lame_length = np.hstack((self.lame_length, self.struct_longueur*np.ones(self.struct_N))) # en mètres self.lame_width = np.hstack((self.lame_width, .042*np.ones(self.struct_N))) # en mètres def sample_structure(self, N_mirror=0, alpha = .8): struct = self.lames[:3, -self.struct_N:] self.particles = np.ones((3, self.N_particles)) N_particles_ = self.N_particles/self.struct_N for i, vec in enumerate(struct.T.tolist()): x0, x1 = vec[0] - .5*self.struct_longueur*np.cos(vec[2]), vec[0] + .5*self.struct_longueur*np.cos(vec[2]) y0, y1 = vec[1] - .5*self.struct_longueur*np.sin(vec[2]), vec[1] + .5*self.struct_longueur*np.sin(vec[2]) self.particles[0, i*N_particles_:(i+1)*N_particles_] = np.linspace(x0, x1, N_particles_) self.particles[1, i*N_particles_:(i+1)*N_particles_] = np.linspace(y0, y1, N_particles_) # duplicate according to mirrors for i in range(N_mirror): particles = self.particles.copy() # the current structure to mirror particles_mirror = particles.copy() # the new set of particles with their mirror image for segment in self.structure_as_segments(): particles_mirror = np.hstack((particles_mirror, mirror(particles, segment, alpha**(i+1)))) # print(alpha**(i+1), particles_mirror[-1, -1]) self.particles = particles_mirror def structure_as_segments(self): struct = self.lames[:3, -self.struct_N:] segments = [] for i, vec in enumerate(struct.T.tolist()): x0, x1 = vec[0] - .5*self.struct_longueur*np.cos(vec[2]), vec[0] + .5*self.struct_longueur*np.cos(vec[2]) y0, y1 = vec[1] - .5*self.struct_longueur*np.sin(vec[2]), vec[1] + .5*self.struct_longueur*np.sin(vec[2]) segments.append(np.array([[x0, y0], [x1, y1]]).T) return segments def theta_E(self, im, X_, Y_, w): try: assert(self.slip.N_X==im.shape[1]) except: from NeuroTools.parameters import ParameterSet from SLIP import Image from LogGabor import LogGabor self.slip = Image(ParameterSet({'N_X':im.shape[1], 'N_Y':im.shape[0]})) self.lg = LogGabor(self.slip) im_ = im.sum(axis=-1) im_ = im_ * np.exp(-.5*((.5 + .5*self.slip.x-Y_)**2+(.5 + .5*self.slip.y-X_)**2)/w**2) E = np.zeros((self.N_theta,)) for i_theta, theta in enumerate(self.thetas): params= {'sf_0':self.sf_0, 'B_sf':self.B_sf, 'theta':theta, 'B_theta': np.pi/self.N_theta} FT_lg = self.lg.loggabor(0, 0, **params) E[i_theta] = np.sum(np.absolute(self.slip.FTfilter(np.rot90(im_, -1), FT_lg, full=True))**2) return E def theta_max(self, im, X_, Y_, w): E = self.theta_E(im, X_, Y_, w) return self.thetas[np.argmax(E)] - np.pi/2 def theta_sobel(self, im, N_blur): im_ = im.copy() sobel = np.array([[1, 2, 1,], [0, 0, 0,], [-1, -2, -1,]]) if im_.ndim==3: im_ = im_.sum(axis=-1) from scipy.signal import convolve2d im_X = convolve2d(im_, sobel, 'same') im_Y = convolve2d(im_, sobel.T, 'same') N_X, N_Y = im_.shape x, y = np.mgrid[0:1:1j*N_X, 0:1:1j*N_Y] mask = np.exp(-.5*((x-.5)**2+(y-.5)**2)/w**2) im_X = convolve2d(im_X, mask, 'same') im_Y = convolve2d(im_Y, mask, 'same') blur = np.array([[1, 2, 1], [2, 8, 2], [1, 2, 1]]) for i in range(N_blur): im_X = convolve2d(im_X, blur, 'same') im_Y = convolve2d(im_Y, blur, 'same') angle = np.arctan2(im_Y, im_X) bord = .1 angles = np.empty(self.N_lame) N_X, N_Y = im_.shape for i in range(self.N_lame): angles[i] = angle[int((bord+self.lames[0, i]*(1-2*bord))*N_X), int((bord+self.lames[1, i]*(1-2*bord))*N_Y)] return angles - np.pi/2 def pos_rel(self, do_torus=False): def torus(x, w=1.): """ center x in the range [-w/2., w/2.] To see what this does, try out: >> x = np.linspace(-4,4,100) >> pylab.plot(x, torus(x, 2.)) """ return np.mod(x + w/2., w) - w/2. dx = self.lames[0, :, np.newaxis]-self.lames[0, np.newaxis, :] dy = self.lames[1, :, np.newaxis]-self.lames[1, np.newaxis, :] if do_torus: return torus(dx), torus(dy) else: return dx, dy def distance(self, do_torus=False): dx, dy = self.pos_rel(do_torus=do_torus) return np.sqrt(dx **2 + dy **2) def angle_relatif(self): return self.lames[2, :, np.newaxis]-self.lames[2, np.newaxis, :] def angle_cocir(self, do_torus=False): dx, dy = self.pos_rel(do_torus=do_torus) theta = self.angle_relatif() return np.arctan2(dy, dx) - np.pi/2 - theta def champ(self): if self.structure: N_lame = self.N_lame-self.struct_N else: N_lame = self.N_lame force = np.zeros_like(self.lames[2, :N_lame]) noise = lambda t: 0.2 * np.exp((np.cos(2*np.pi*(t-0.) / 6.)-1.)/ 1.5**2) damp = lambda t: 0.01 #* np.exp(np.cos(t / 6.) / 3.**2) colin_t = lambda t: -.1*np.exp((np.cos(2*np.pi*(t-2.) / 6.)-1.)/ .3**2) cocir_t = lambda t: -4.*np.exp((np.cos(2*np.pi*(t-4.) / 6.)-1.)/ .5**2) cocir_d = lambda d: np.exp(-d/.05) colin_d = lambda d: np.exp(-d/.2) force += colin_t(self.t) * np.sum(np.sin(2*(self.angle_relatif()[:N_lame]))*colin_d(self.distance()[:N_lame]), axis=1) force += cocir_t(self.t) * np.sum(np.sin(2*(self.angle_cocir()[:N_lame]))*cocir_d(self.distance()[:N_lame]), axis=1) force += noise(self.t)*np.pi*np.random.randn(N_lame) force -= damp(self.t) * self.lames[3, :N_lame]/self.dt return 42.*force def update(self): if self.structure: N_lame = self.N_lame-self.struct_N else: N_lame = self.N_lame self.lames[2, :N_lame] += self.lames[3, :N_lame]*self.dt/2 self.lames[3, :N_lame] += self.champ() * self.dt self.lames[2, :N_lame] += self.lames[3, :N_lame]*self.dt/2 # angles are defined as non oriented between -pi/2 and pi/2 self.lames[2, :N_lame] = np.mod(self.lames[2, :N_lame] + np.pi/2, np.pi) - np.pi/2 def receive(self): if not self.filename is None: if os.path.isfile(self.filename): if self.structure: N_lame = self.N_lame-self.struct_N else: N_lame = self.N_lame self.t = self.time() i_t = np.argmin(self.z[:, 0] < np.mod(self.t, self.period)) if self.verb: print("playback at t=", np.mod(self.t, self.period), i_t) self.lames[2, :N_lame] = self.z[i_t, 1:] return if self.stream: if self.verb: print("Sending request") self.socket.send (b"Hello") if self.verb: print( "Received reply ", message) self.lames[2, :] = recv_array(self.socket) if self.verb: print("Received reply ", Theta.shape) else: self.dt = self.time() - self.t self.update() self.t = self.time() # if not self.filename is None: # if not os.path.isfile(self.filename): # # recording # if self.verb: print("recording at t=", self.t) # self.z = np.vstack((self.z, np.hstack((np.array(self.t), self.lames[2, :] )))) return def render(self, fps=10, W=1000, H=618, location=[0, 1.75, -5], head_size=.4, light_intensity=1.2, reflection=1., look_at=[0, 1.5, 0], fov=75, antialiasing=0.001, duration=5, fname='/tmp/temp.webm'): def scene(t): """ Returns the scene at time 't' (in seconds) """ head_location = np.array(location) - np.array([0, 0, head_size]) import vapory light = vapory.LightSource([15, 15, 1], 'color', [light_intensity]*3) background = vapory.Box([0, 0, 0], [1, 1, 1], vapory.Texture(vapory.Pigment(vapory.ImageMap('png', '"../files/VISUEL_104.png"', 'once')), vapory.Finish('ambient', 1.2) ), 'scale', [self.background_depth, self.background_depth, 0], 'translate', [-self.background_depth/2, -.45*self.background_depth, -self.background_depth/2]) me = vapory.Sphere( head_location, head_size, vapory.Texture( vapory.Pigment( 'color', [1, 0, 1] ))) self.t = t self.update() objects = [background, me, light] for i_lame in range(self.N_lame): #print(i_lame, self.lame_length[i_lame], self.lame_width[i_lame]) objects.append(vapory.Box([-self.lame_length[i_lame]/2, 0, -self.lame_width[i_lame]/2], [self.lame_length[i_lame]/2, self.lames_height, self.lame_width[i_lame]/2], vapory.Pigment('color', [1, 1, 1]), vapory.Finish('phong', 0.8, 'reflection', reflection), 'rotate', (0, -self.lames[2, i_lame]*180/np.pi, 0), #HACK? 'translate', (self.lames[0, i_lame], 0, self.lames[1, i_lame]) ) ) objects.append(light) return vapory.Scene( vapory.Camera('angle', fov, "location", location, "look_at", look_at), objects = objects, included=["glass.inc"] ) import moviepy.editor as mpy if not os.path.isfile(fname): self.dt = 1./fps def make_frame(t): return scene(t).render(width=W, height=H, antialiasing=antialiasing) clip = mpy.VideoClip(make_frame, duration=duration) clip.write_videofile(fname, fps=fps) return mpy.ipython_display(fname, fps=fps, loop=1, autoplay=1) def plot_structure(self, W=1000, H=618, fig=None, ax=None, border = 0.0, opts = dict(vmin=-1, vmax=1., linewidths=0, cmap=None, alpha=.1, s=5.), scale='auto'): # opts.update(cmap=plt.cm.hsv) if fig is None: fig = plt.figure(figsize=(self.figsize, self.figsize*H/W)) if ax is None: ax = fig.add_axes((border, border, 1.-2*border, 1.-2*border), axisbg='w') scat = ax.scatter(self.particles[0,::-1], self.particles[1,::-1], c=self.particles[2,::-1], **opts) if type(scale) is float: ax.set_xlim([-scale, scale]) ax.set_ylim([-scale*H/W, scale*H/W]) elif not scale is 'auto': ax.set_xlim([-self.total_width, self.total_width]) ax.set_ylim([-self.total_width*H/W, self.total_width*H/W]) else: ax.set_xlim([min(self.particles[0, :].min(), self.particles[1, :].min()/H*W), max(self.particles[0, :].max(), self.particles[1, :].max()/H*W)]) ax.set_ylim([min(self.particles[1, :].min(), self.particles[0, :].min()*H/W), max(self.particles[1, :].max(), self.particles[0, :].max()*H/W)]) ax.axis('off') return fig, ax def animate(self, fps=10, W=1000, H=618, duration=20, scale='auto', fname=None): if fname is None: import tempfile fname = tempfile.mktemp() + '.webm' import matplotlib.pyplot as plt self.dt = 1./fps inches_per_pt = 1.0/72.27 from moviepy.video.io.bindings import mplfig_to_npimage import moviepy.editor as mpy def make_frame_mpl(t): self.t = t self.update() fig = plt.figure(figsize=(W*inches_per_pt, H*inches_per_pt)) fig, ax = self.plot_structure(fig=fig, ax=None, scale=scale) #ax.clear() ax.axis('off') #fig, ax = self.plot_structure(fig=fig, ax=ax) return mplfig_to_npimage(fig) # RGB image of the figure animation = mpy.VideoClip(make_frame_mpl, duration=duration) plt.close('all') animation.write_videofile(fname, fps=fps) return mpy.ipython_display(fname, fps=fps, loop=1, autoplay=1, width=W)