This is a small collection of tools that we use with Pupil. The tools are not part of the main repository, as they are mostly stand-alone convience scripts.
-
-
Save anr2me/57145fca590eb6cf9ea81f97e3b729b3 to your computer and use it in GitHub Desktop.
Control your Mouse using your Eye Movement
This file contains hidden or 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 | |
| import numpy as np | |
| def encode_marker(mId): | |
| marker_id_str = "%02d"%mId | |
| # marker is based on grid of black (0) /white (1) pixels | |
| # b|b|b|b|b | |
| # b|o|m|o|b b = black border feature | |
| # b|m|m|m|b o = orientation feature | |
| # b|o|m|o|b m = message feature | |
| # b|b|b|b|b | |
| grid = 5 | |
| m_with_b = np.zeros((grid,grid),dtype=np.uint8) | |
| m = m_with_b[1:-1,1:-1] | |
| #bitdepth = grid-border squared - 3 for orientation (orientation still yields one bit) | |
| bitdepth = ((5-2)**2)-3 | |
| if mId>=(2**bitdepth): | |
| raise Exception("ERROR: ID overflow, this marker can only hold %i bits of information" %bitdepth) | |
| msg = [0]*bitdepth | |
| for i in range(len(msg))[::-1]: | |
| msg[i] = mId%2 | |
| mId = mId >>1 | |
| # out first bit is encoded in the orientation corners of the marker: | |
| # MSB = 0 MSB = 1 | |
| # W|*|*|W ^ B|*|*|B ^ | |
| # *|*|*|* / \ *|*|*|* / \ | |
| # *|*|*|* | UP *|*|*|* | UP | |
| # B|*|*|W | W|*|*|B | | |
| msb = msg.pop(0) | |
| if msb: | |
| orientation = 0,1,0,0 | |
| else: | |
| orientation = 1,0,1,1 | |
| m[0,0], m[-1,0], m[-1,-1], m[0,-1] = orientation | |
| msg_mask = np.ones(m.shape,dtype=np.bool) | |
| msg_mask[0,0], msg_mask[-1,0], msg_mask[-1,-1], msg_mask[0,-1] = 0,0,0,0 | |
| m[msg_mask] = msg[::-1] | |
| # print "Marker: \n", m_with_b | |
| return m_with_b | |
| def write_marker_png(mId,size): | |
| marker_id_str = "%02d"%mId | |
| m = encode_marker(mId)*255 | |
| m = cv2.resize(m,(size,size),interpolation=cv2.INTER_NEAREST) | |
| m = cv2.cvtColor(m,cv2.COLOR_GRAY2BGR) | |
| cv2.imwrite('marker '+marker_id_str+'.png',m) | |
| def write_all_markers_png(size): | |
| rows,cols,m_size = 8,8,7 | |
| canvas = np.ones((m_size*rows,m_size*cols),dtype=np.uint8) | |
| for mid in range(64): | |
| marker_with_padding = np.ones((7,7)) | |
| marker_with_padding[1:-1,1:-1] = encode_marker(mid) | |
| m_size = marker_with_padding.shape[0] | |
| r = (mid%rows) * m_size | |
| c = (mid/cols) * m_size | |
| canvas[r:r+m_size,c:c+m_size] = marker_with_padding*255 | |
| canvas = cv2.resize(canvas,(size,size),interpolation=cv2.INTER_NEAREST) | |
| canvas = cv2.cvtColor(canvas,cv2.COLOR_GRAY2BGR) | |
| cv2.imwrite('all_markers.png',canvas) | |
| if __name__ == '__main__': | |
| write_all_markers_png(2000) | |
| write_marker_png(8,800) |
This file contains hidden or 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 zmq | |
| from pymouse import PyMouse | |
| #mouse setup | |
| m = PyMouse() | |
| x_dim, y_dim = m.screen_size() | |
| #network setup | |
| context = zmq.Context() | |
| socket = context.socket(zmq.SUB) | |
| socket.connect("tcp://127.0.0.1:5000") | |
| #filter by messages by stating string 'STRING'. '' receives all messages | |
| socket.setsockopt(zmq.SUBSCRIBE, '') | |
| smooth_x, smooth_y= 0.5, 0.5 | |
| surface_name = "screen" | |
| while True: | |
| msg = socket.recv() | |
| items = msg.split("\n") | |
| msg_type = items.pop(0) | |
| items = dict([i.split(':') for i in items[:-1] ]) | |
| if msg_type == 'Pupil': | |
| try: | |
| gaze_on_screen = items["realtime gaze on "+surface_name] | |
| raw_x,raw_y = map(float,gaze_on_screen[1:-1].split(',')) | |
| # smoothing out the gaze so the mouse has smoother movement | |
| smooth_x += 0.5 * (raw_x-smooth_x) | |
| smooth_y += 0.5 * (raw_y-smooth_y) | |
| x = smooth_x | |
| y = smooth_y | |
| y = 1-y # inverting y so it shows up correctly on screen | |
| x *= x_dim | |
| y *= y_dim | |
| # PyMouse or MacOS bugfix - can not go to extreme corners because of hot corners? | |
| x = min(x_dim-10, max(10,x)) | |
| y = min(y_dim-10, max(10,y)) | |
| m.move(x,y) | |
| except KeyError: | |
| pass | |
| else: | |
| # process non gaze position events from plugins here | |
| pass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment