#!/usr/bin/python3 # -*- coding: utf-8 -*- # -*- mode: Python -*- ''' trckr Work with clmtrackr-dev and www/trckr/trckr.html v0.1.0 LICENCE : CC by Sam Neurohack To test the examples locally, you need to run a local server. One easy way to do this is to install http-server, a small node.js utility: npm install -g http-server. Then run http-server in the root of clmtrackr and go to - read a video : http://localhost:8080/examples/trckr.html - webcam clmtrackr : https://github.com/auduno/clmtrackr/tree/dev/examples ''' import sys import os print() ljpath = r'%s' % os.getcwd().replace('\\','/') # import from shell sys.path.append(ljpath +'/../libs3/') #import from LJ import log print ("") log.infog("Trckr Plugin v0.1") sys.path.append('../libs3') sys.path.append(ljpath +'/../../libs3') from OSC3 import OSCServer, OSCClient, OSCMessage import lj import redis import math import time import argparse OSCinPort = 8017 print ("") print ("Arguments parsing if needed...") argsparser = argparse.ArgumentParser(description="trckr example for LJ") argsparser.add_argument("-r","--redisIP",help="IP of the Redis server used by LJ (127.0.0.1 by default) ",type=str) argsparser.add_argument("-s","--scene",help="LJ scene number (0 by default)",type=int) #argsparser.add_argument("-l","--laser",help="Laser number to be displayed (0 by default)",type=int) argsparser.add_argument("-v","--verbose",help="Verbosity level (0 by default)",type=int) argsparser.add_argument("-m","--myIP",help="Local IP (127.0.0.1 by default) ",type=str) args = argsparser.parse_args() if args.scene: ljscene = args.scene else: ljscene = 0 ''' if args.laser: plnumber = args.laser else: plnumber = 0 ''' # Redis Computer IP if args.redisIP != None: redisIP = args.redisIP else: redisIP = '127.0.0.1' print("redisIP",redisIP) # myIP if args.myIP != None: myIP = args.myIP else: myIP = '127.0.0.1' print("myIP",myIP) if args.verbose: debug = args.verbose else: debug = 0 # Useful variables init. white = lj.rgb2int(255,255,255) red = lj.rgb2int(255,0,0) blue = lj.rgb2int(0,0,255) green = lj.rgb2int(0,255,0) # 3D to 2D projection parameters fov = 256 viewer_distance = 2.2 width = 800 height = 600 centerX = width / 2 centerY = height / 2 TrckrPts = [[0,0]] * 70 # # LJ inits # layer = 0 # Setup LJ library mandatory properties for this layerugin lj.Config(redisIP, ljscene, "trckr") # Define properties for each drawn "element" : name, intensity, active, xy, color, red, green, blue, layer , closed FaceForm = lj.FixedObject('Face', True, 255, [], red, 255, 0, 0, layer , False) # 'Destination' for given layer : name, number, active, layer , scene, laser Dest0 = lj.DestObject('0', 0, True, 0 , 0, 0) # Dest0 will send layer 0 points to scene 0, laser 0 # # OSC # oscserver = OSCServer( (myIP, OSCinPort) ) oscserver.timeout = 0 # this method of reporting timeouts only works by convention # that before calling handle_request() field .timed_out is # set to False def handle_timeout(self): self.timed_out = True # funny python's way to add a method to an instance of a class import types oscserver.handle_timeout = types.MethodType(handle_timeout, oscserver) # OSC callbacks # /trckr/ljscene def OSCljscene(path, tags, args, source): print("Got /trckr/ljscene with value", args[0]) lj.WebStatus("trckr to virtual "+ str(args[0])) ljscene = args[0] lj.Ljscene(ljscene) # /trckr/layer def OSClayer(path, tags, args, source): print() print() print("Got /trckr/layer with value", args[0]) lj.WebStatus("trckr to layer "+ str(args[0])) FaceForm.layer = int(args[0]) Dest0.layer = int(args[0]) Dest0.laser = int(args[0]) # /trckr/frame def OSCtrckr(path, tags, args, source): global TrckrPts #print("trckr got frame", args[0]) if debug != 0: print("trckr plugin got frame", args[0]) print(len(args),"args", args) counter =0 TrckrPts = [] for dot in range(1,len(args)-1,2): TrckrPts.append([float(args[dot]), float(args[dot+1])]) print(TrckrPts) # /trckr/frame layernumber framenumber points def OSCTrckrframe(path, tags, args, source): global TrckrPts if debug != 0: print("trckr plugin got frame", args[1], "for layer", args[0], "with path", path) print(len(args),"args", args) TrckrPts[args[0]] = [] for dot in range(2,len(args)-1,2): TrckrPts[args[0]].append([float(args[dot]), float(args[dot+1])]) #/trckr/color/0 red ? def OSColor(): global FaceForm if debug != 0: print("trckr color got ", args[1], "for layer", args[0], "with path", path) print(len(args),"args", args) FaceForm.color = args[1] # default handler def OSChandler(path, tags, args, source): oscaddress = ''.join(path.split("/")) print() print("trckr default OSC Handler :", path, "from Client :" + str(source[0])) # # Face Tracking # # get absolute face position points def getPART(pose_points): dots = [] for dot in pose_points: dots.append((TrckrPts[dot][0], TrckrPts[dot][1],0)) return dots # Face keypoints def face(): pose_points = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14] return getPART(pose_points) def browL(): pose_points = [15,16,17,18] return getPART(pose_points) def browR(): pose_points = [22,21,20,19] return getPART(pose_points) def eyeR(): pose_points = [25,64,24,63,23,66,26,65,25] return getPART(pose_points) def eyeL(): pose_points = [28,67,29,68,30,69,31,28] return getPART(pose_points) def pupR(): pose_points = [27] return getPART(pose_points) def pupL(): pose_points = [32] return getPART(pose_points) def nose1(): pose_points = [62,41,33] return getPART(pose_points) def nose2(): pose_points = [40,39,38,43,37,42,36,35,34] return getPART(pose_points) def mouth(): pose_points = [50,49,48,47,46,45,44,55,54,53,52,51,50] return getPART(pose_points) def mouthfull(): pose_points = [50,49,48,47,46,45,44,55,54,53,52,51,50,59,60,61,44,56,57,58,50] return getPART(pose_points) def Proj(x,y,z,angleX,angleY,angleZ): rad = angleX * math.pi / 180 cosa = math.cos(rad) sina = math.sin(rad) y2 = y y = y2 * cosa - z * sina z = y2 * sina + z * cosa rad = angleY * math.pi / 180 cosa = math.cos(rad) sina = math.sin(rad) z2 = z z = z2 * cosa - x * sina x = z2 * sina + x * cosa rad = angleZ * math.pi / 180 cosa = math.cos(rad) sina = math.sin(rad) x2 = x x = x2 * cosa - y * sina y = x2 * sina + y * cosa """ Transforms this 3D point to 2D using a perspective projection. """ factor = fov / (viewer_distance + z) x = x * factor + centerX y = - y * factor + centerY return (x,y) # # Main # def Run(): Facepts = [] counter =0 lj.WebStatus("trckr") lj.SendLJ("/trckr/start 1") # OSC Server callbacks print("Starting OSC server at",myIP," port",OSCinPort,"...") oscserver.addMsgHandler( "/trckr/ljscene", OSCljscene) oscserver.addMsgHandler( "/trckr/layer", OSClayer) oscserver.addMsgHandler( "/trckr/frame", OSCtrckr) oscserver.addMsgHandler( "/trckr/color", OSColor) # Add OSC generic layerugins commands : 'default", /ping, /quit, /pluginame/obj, /pluginame/var, /pluginame/adddest, /pluginame/deldest lj.addOSCdefaults(oscserver) oscserver.addMsgHandler( "default", OSChandler ) try: while lj.oscrun: lj.OSCframe() #print("browL", browL(), "browR", browR(), "nose1", nose1(), "mouth", mouth()) lj.rPolyLineOneColor(browL(), c = FaceForm.color, layer = FaceForm.layer, closed = FaceForm.closed, xpos = -300, ypos = -300, resize = 3.6, rotx = 0, roty = 0, rotz = 0) lj.rPolyLineOneColor(eyeL(), c = FaceForm.color, layer = FaceForm.layer, closed = FaceForm.closed, xpos = -300, ypos = -300, resize = 3.6, rotx = 0, roty = 0, rotz = 0) lj.rPolyLineOneColor(browR(), c = FaceForm.color, layer = FaceForm.layer, closed = FaceForm.closed, xpos = -300, ypos = -300, resize = 3.6, rotx = 0, roty = 0, rotz = 0) lj.rPolyLineOneColor(eyeR(), c = FaceForm.color, layer = FaceForm.layer, closed = FaceForm.closed, xpos = -300, ypos = -300, resize = 3.6, rotx = 0, roty = 0, rotz = 0) lj.rPolyLineOneColor(pupL(), c = FaceForm.color, layer = FaceForm.layer, closed = FaceForm.closed, xpos = -300, ypos = -300, resize = 3.6, rotx = 0, roty = 0, rotz = 0) lj.rPolyLineOneColor(pupR(), c = FaceForm.color, layer = FaceForm.layer, closed = FaceForm.closed, xpos = -300, ypos = -300, resize = 3.6, rotx = 0, roty = 0, rotz = 0) lj.rPolyLineOneColor(nose1(), c = FaceForm.color, layer = FaceForm.layer, closed = FaceForm.closed, xpos = -300, ypos = -300, resize = 3.6, rotx = 0, roty = 0, rotz = 0) lj.rPolyLineOneColor(nose2(), c = FaceForm.color, layer = FaceForm.layer, closed = FaceForm.closed, xpos = -300, ypos = -300, resize = 3.6, rotx = 0, roty = 0, rotz = 0) lj.rPolyLineOneColor(mouthfull(), c = FaceForm.color, layer = FaceForm.layer, closed = FaceForm.closed, xpos = -300, ypos = -300, resize = 3.6, rotx = 0, roty = 0, rotz = 0) lj.DrawDests() time.sleep(0.005) counter += 1 if counter > 360: counter = 0 except KeyboardInterrupt: pass # Gently stop on CTRL C finally: lj.ClosePlugin() Run() ''' // // a template for receiving face tracking osc messages from // Kyle McDonald's trckr https://github.com/kylemcdonald/ofxFaceTracker // // 2012 Dan Wilcox danomatika.com // for the IACD Spring 2012 class at the CMU School of Art // // adapted from from Greg Borenstein's 2011 example // http://www.gregborenstein.com/ // https://gist.github.com/1603230 // //Xavier Apostol //Generative Faces: Plotter Project Concept import oscP5.*; OscP5 oscP5; // num faces found int found; // pose float poseScale; PVector posePosition = new PVector(); PVector poseOrientation = new PVector(); // gesture float mouthHeight; float mouthWidth; float eyeLeft; float eyeRight; float eyebrowLeft; float eyebrowRight; float jaw; float nostrils; float sz = 1; float spacing = 100; float genSz = spacing/4; float fcOff = genSz/2; //Initialization of Colors float R = random(255); float G = random(255); float B = random(255); //Initialization of Head float rotInt = 15; float hdX = cos(sz) + random(genSz, 3*genSz); float hdY = sin(sz) + random(genSz, 3*genSz); float rotAngle = random(-rotInt,rotInt); //Initialization of Eyes float lEyeX1 = sin(sz*0) + random(genSz); float lEyeY1 = cos(sz*0) + random(genSz); float rEyeX1 = sin(sz*0) + random(genSz); float rEyeY1 = cos(sz*0) + random(genSz); float lEyeX2 = sin(sz*1) + random(genSz); float lEyeY2 = cos(sz*1) + random(genSz); float rEyeX2 = sin(sz*1) + random(genSz); float rEyeY2 = cos(sz*1) + random(genSz); float ranREye = random(7, 9); float ranLEye = random(7, 9); //Initialization of Mouth float mthX = cos(sz) + random(genSz); float mthY = sin(sz) + random(genSz); float ranM = random(-0.1, 1.5); //Initialization of Spine float hdOffset = hdY/1.5; float spineSz = random(genSz/2); float spXOff1 = random(-8, 8); float spYOff1 = hdOffset + random(genSz/3); float spXOff2 = random(-8, 8)+spXOff1; float spYOff2 = random(genSz/3)+spYOff1; float spXOff3 = random(-8, 8)+spXOff2; float spYOff3 = random(genSz/3)+spYOff2; float spXOff4 = random(-8, 8)+spXOff3; float spYOff4 = random(genSz/3)+spYOff3; float spXOff5 = random(-8, 8)+spXOff4; float spYOff5 = random(genSz/3)+spYOff4; void setup() { size(800, 600, OPENGL); frameRate(30); oscP5 = new OscP5(this, 8338); oscP5.plug(this, "found", "/found"); oscP5.plug(this, "poseScale", "/pose/scale"); oscP5.plug(this, "posePosition", "/pose/position"); oscP5.plug(this, "poseOrientation", "/pose/orientation"); oscP5.plug(this, "mouthWidthReceived", "/gesture/mouth/width"); oscP5.plug(this, "mouthHeightReceived", "/gesture/mouth/height"); oscP5.plug(this, "eyeLeftReceived", "/gesture/eye/left"); oscP5.plug(this, "eyeRightReceived", "/gesture/eye/right"); oscP5.plug(this, "eyebrowLeftReceived", "/gesture/eyebrow/left"); oscP5.plug(this, "eyebrowRightReceived", "/gesture/eyebrow/right"); oscP5.plug(this, "jawReceived", "/gesture/jaw"); oscP5.plug(this, "nostrilsReceived", "/gesture/nostrils"); } void keyPressed() { if (key == CODED) { if (keyCode == UP) { //Create an entirely new character. //For Eyes lEyeX1 = sin(sz*0) + random(genSz); lEyeY1 = cos(sz*0) + random(genSz); rEyeX1 = sin(sz*0) + random(genSz); rEyeY1 = cos(sz*0) + random(genSz); lEyeX2 = sin(sz*1) + random(genSz); lEyeY2 = cos(sz*1) + random(genSz); rEyeX2 = sin(sz*1) + random(genSz); rEyeY2 = cos(sz*1) + random(genSz); ranREye = random(7, 9); ranLEye = random(7, 9); //For Mouth mthX = cos(sz) + random(genSz); mthY = sin(sz) + random(genSz); ranM = random(-0.1, 1.5); //For Spine spineSz = random(genSz/2); spXOff1 = random(-8, 8); spYOff1 = hdOffset + random(genSz/3); spXOff2 = random(-8, 8) + spXOff1; spYOff2 = random(genSz/3) + spYOff1; spXOff3 = random(-8, 8) + spXOff2; spYOff3 = random(genSz/3) + spYOff2; spXOff4 = random(-8, 8) + spXOff3; spYOff4 = random(genSz/3) + spYOff3; spXOff5 = random(-8, 8) + spXOff4; spYOff5 = random(genSz/3) + spYOff4; //For Head hdX = cos(sz) + random(genSz, 3*genSz); hdY = sin(sz) + random(genSz, 3*genSz); rotAngle = random(-rotInt,rotInt); //For Colors R = random(255); G = random(255); B = random(255); draw(); } } } void draw() { background(0); strokeWeight(1); noFill(); if(found != 0) { pushMatrix(); translate(posePosition.x, posePosition.y); //Scales head and allows for rotations scale(poseScale*2); rotateY(0 - poseOrientation.y); rotateX(0 - poseOrientation.x); rotateZ(poseOrientation.z); rotate(radians(rotAngle)); ellipse(0,0, hdX,hdY); popMatrix(); //FACE translate(posePosition.x, posePosition.y); scale(poseScale); noFill(); //Eyes float eyeFac = 1; float eyeBL = eyebrowLeft * 2; float eyeBR = eyebrowRight * 2; ellipse(-20,eyeLeft * -ranLEye, lEyeX1*eyeFac + eyeBL,lEyeY1*eyeFac + eyeBL); ellipse(20,eyeRight * -ranREye, rEyeX1*eyeFac + eyeBR,rEyeY1*eyeFac + eyeBR); ellipse(-20,eyeLeft * -ranLEye, lEyeX2*eyeFac + eyeBL,lEyeY2*eyeFac + eyeBL); ellipse(20,eyeRight * -ranREye, rEyeX2*eyeFac + eyeBR,rEyeY2*eyeFac + eyeBR); //Mouth ellipse(0, 20*ranM, mouthWidth* mthX/3, mouthHeight * mthY); //BODY/BUBBLES stroke(R,G,B); ellipse(spXOff1,spYOff1, spineSz,spineSz); ellipse(spXOff2,spYOff2, spineSz,spineSz); ellipse(spXOff3,spYOff3, spineSz,spineSz); ellipse(spXOff4,spYOff4, spineSz,spineSz); ellipse(spXOff5,spYOff5, spineSz,spineSz); } } // OSC CALLBACK FUNCTIONS public void found(int i) { println("found: " + i); found = i; } public void poseScale(float s) { println("scale: " + s); poseScale = s; } public void posePosition(float x, float y) { println("pose position\tX: " + x + " Y: " + y ); posePosition.set(x, y, 0); } public void poseOrientation(float x, float y, float z) { println("pose orientation\tX: " + x + " Y: " + y + " Z: " + z); poseOrientation.set(x, y, z); } public void mouthWidthReceived(float w) { println("mouth Width: " + w); mouthWidth = w; } public void mouthHeightReceived(float h) { println("mouth height: " + h); mouthHeight = h; } public void eyeLeftReceived(float f) { println("eye left: " + f); eyeLeft = f; } public void eyeRightReceived(float f) { println("eye right: " + f); eyeRight = f; } public void eyebrowLeftReceived(float f) { println("eyebrow left: " + f); eyebrowLeft = f; } public void eyebrowRightReceived(float f) { println("eyebrow right: " + f); eyebrowRight = f; } public void jawReceived(float f) { println("jaw: " + f); jaw = f; } public void nostrilsReceived(float f) { println("nostrils: " + f); nostrils = f; } // all other OSC messages end up here void oscEvent(OscMessage m) { if(m.isPlugged() == false) { println("UNPLUGGED: " + m); } } '''