forked from protonphoton/LJ
conf template and bugfixs
This commit is contained in:
parent
93a5bf7fe5
commit
71bcd8ba68
47
LJ.conf
47
LJ.conf
@ -1,5 +1,5 @@
|
||||
[General]
|
||||
lasernumber = 1
|
||||
lasernumber = 4
|
||||
debug = 0
|
||||
ljayserverip = 0.0.0.0
|
||||
wwwip = 192.168.2.43
|
||||
@ -13,13 +13,13 @@ type = DS1000
|
||||
ip = 192.168.2.4
|
||||
kpps = 25000
|
||||
centerx = 0
|
||||
centery = 0
|
||||
centery = 765
|
||||
zoomx = 45.0
|
||||
zoomy = 45.0
|
||||
sizex = 32000
|
||||
sizey = 32000
|
||||
finangle = 0.0
|
||||
swapx = 1
|
||||
swapx = -1
|
||||
swapy = -1
|
||||
lsteps = [ (1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]
|
||||
warpdest = [[-1500., 1500.],
|
||||
@ -32,20 +32,20 @@ color = -1
|
||||
type = LOCAL
|
||||
ip = 192.168.2.43
|
||||
kpps = 25000
|
||||
centerx = 0
|
||||
centery = 0
|
||||
zoomx = 45.0
|
||||
zoomy = 45.0
|
||||
centerx = -11970
|
||||
centery = -6510
|
||||
zoomx = 30.0
|
||||
zoomy = 30.0
|
||||
sizex = 32000
|
||||
sizey = 32000
|
||||
finangle = -30.0
|
||||
finangle = 0.0
|
||||
swapx = -1
|
||||
swapy = -1
|
||||
lsteps = [ (1.0, 2),(0.25, 1), (0.75, 1), (1.0, 5)]
|
||||
warpdest = [[-1500., 1500.],
|
||||
[ 1500., 1500.],
|
||||
[ 1500.,-1500.],
|
||||
[-1500.,-1500.]]
|
||||
[ 1500., 1500.],
|
||||
[ 1500.,-1500.],
|
||||
[-1500.,-1500.]]
|
||||
|
||||
[laser2]
|
||||
color = -1
|
||||
@ -63,14 +63,14 @@ swapx = -1
|
||||
swapy = -1
|
||||
lsteps = [(1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]
|
||||
warpdest = [[-1500., 1500.],
|
||||
[ 1500., 1500.],
|
||||
[ 1500.,-1500.],
|
||||
[-1500.,-1500.]]
|
||||
[ 1500., 1500.],
|
||||
[ 1500.,-1500.],
|
||||
[-1500.,-1500.]]
|
||||
|
||||
[laser3]
|
||||
color = -1
|
||||
type = LUKE400
|
||||
ip = 192.168.1.5
|
||||
ip = 192.168.2.3
|
||||
kpps = 25000
|
||||
centerx = 0
|
||||
centery = 0
|
||||
@ -83,19 +83,13 @@ swapx = -1
|
||||
swapy = -1
|
||||
lsteps = [(1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]
|
||||
warpdest = [[-1500., 1500.],
|
||||
[ 1500., 1500.],
|
||||
[ 1500.,-1500.],
|
||||
[-1500.,-1500.]]
|
||||
[ 1500., 1500.],
|
||||
[ 1500.,-1500.],
|
||||
[-1500.,-1500.]]
|
||||
|
||||
[plugins]
|
||||
plugins = {
|
||||
"trckr": {"OSC": 8017, "command": "python3 plugins/VJing/trckr.py", "display": True},
|
||||
"aurora": {"OSC": 8090, "command": "python3 plugins/aurora/aurora.py", "display": True},
|
||||
"maxw": {"OSC": 8012, "command": "python3 plugins/maxwell.py", "display": True},
|
||||
"square": {"OSC": 8013, "command": "python3 plugins/square.py", "display": True},
|
||||
"custom1": {"OSC": 8014, "command": "python3 plugins/custom1.py", "display": True},
|
||||
"mitraille": {"OSC": 8015, "command": "python3 plugins/audio/mitraille.py", "display": True},
|
||||
"livecode": {"OSC": 8016, "command": "python3 plugins/livecoding.py", "display": True},
|
||||
"nozoid": {"OSC": 8003, "command": "python3 plugins/audio/nozoids3.py", "display": True},
|
||||
"glyph": {"OSC": 8004, "command": "python3 plugins/laserglyph.py", "display": True},
|
||||
"planet": {"OSC": 8005, "command": "python3 plugins/planetarium/main.py", "display": True},
|
||||
@ -103,6 +97,11 @@ plugins = {
|
||||
"cycl": {"OSC": 8007, "command": "python3 plugins/textcycl.py", "display": True},
|
||||
"simu": {"OSC": 8008, "command": "python plugins/pysimu.py", "display": False},
|
||||
"artnet": {"OSC": 8009, "command": "python3 libs3/artnet.py", "display": False},
|
||||
"trckr": {"OSC": 8017, "command": "python3 plugins/trckr.py", "display": False},
|
||||
"maxw": {"OSC": 8012, "command": "python3 plugins/maxwell.py", "display": True},
|
||||
"square": {"OSC": 8013, "command": "python3 plugins/square.py", "display": True},
|
||||
"custom1": {"OSC": 8014, "command": "python3 plugins/custom1.py", "display": True},
|
||||
"mitraille": {"OSC": 8015, "command": "python3 plugins/audio/mitraille.py", "display": True},
|
||||
"livecode": {"OSC": 8016, "command": "python3 plugins/livecoding.py", "display": True},
|
||||
"ljpong": {"OSC": 8020, "command": "python plugins/games/ljpong/main.py", "display": True},
|
||||
"ljwars": {"OSC": 8021, "command": "python plugins/games/ljsw/main.py", "display": True},
|
||||
|
@ -34,11 +34,11 @@ ip = 192.168.2.43
|
||||
kpps = 25000
|
||||
centerx = 0
|
||||
centery = 0
|
||||
zoomx = 45.0
|
||||
zoomy = 45.0
|
||||
zoomx = 30.0
|
||||
zoomy = 30.0
|
||||
sizex = 32000
|
||||
sizey = 32000
|
||||
finangle = -30.0
|
||||
finangle = 0
|
||||
swapx = -1
|
||||
swapy = -1
|
||||
lsteps = [ (1.0, 2),(0.25, 1), (0.75, 1), (1.0, 5)]
|
||||
@ -89,13 +89,7 @@ warpdest = [[-1500., 1500.],
|
||||
|
||||
[plugins]
|
||||
plugins = {
|
||||
"trckr": {"OSC": 8017, "command": "python3 plugins/VJing/trckr.py", "display": True},
|
||||
"aurora": {"OSC": 8090, "command": "python3 plugins/aurora/aurora.py", "display": True},
|
||||
"maxw": {"OSC": 8012, "command": "python3 plugins/maxwell.py", "display": True},
|
||||
"square": {"OSC": 8013, "command": "python3 plugins/square.py", "display": True},
|
||||
"custom1": {"OSC": 8014, "command": "python3 plugins/custom1.py", "display": True},
|
||||
"mitraille": {"OSC": 8015, "command": "python3 plugins/audio/mitraille.py", "display": True},
|
||||
"livecode": {"OSC": 8016, "command": "python3 plugins/livecoding.py", "display": True},
|
||||
"nozoid": {"OSC": 8003, "command": "python3 plugins/audio/nozoids3.py", "display": True},
|
||||
"glyph": {"OSC": 8004, "command": "python3 plugins/laserglyph.py", "display": True},
|
||||
"planet": {"OSC": 8005, "command": "python3 plugins/planetarium/main.py", "display": True},
|
||||
@ -103,6 +97,11 @@ plugins = {
|
||||
"cycl": {"OSC": 8007, "command": "python3 plugins/textcycl.py", "display": True},
|
||||
"simu": {"OSC": 8008, "command": "python plugins/pysimu.py", "display": False},
|
||||
"artnet": {"OSC": 8009, "command": "python3 libs3/artnet.py", "display": False},
|
||||
"trckr": {"OSC": 8017, "command": "python3 plugins/trckr.py", "display": False},
|
||||
"maxw": {"OSC": 8012, "command": "python3 plugins/maxwell.py", "display": True},
|
||||
"square": {"OSC": 8013, "command": "python3 plugins/square.py", "display": True},
|
||||
"custom1": {"OSC": 8014, "command": "python3 plugins/custom1.py", "display": True},
|
||||
"mitraille": {"OSC": 8015, "command": "python3 plugins/audio/mitraille.py", "display": True},
|
||||
"livecode": {"OSC": 8016, "command": "python3 plugins/livecoding.py", "display": True},
|
||||
"ljpong": {"OSC": 8020, "command": "python plugins/games/ljpong/main.py", "display": True},
|
||||
"ljwars": {"OSC": 8021, "command": "python plugins/games/ljsw/main.py", "display": True},
|
||||
|
16
README.md
16
README.md
@ -28,7 +28,7 @@ Important : for best performance LJ is meant to run in a dedicated computer espe
|
||||
- Some Lasermapping ('alignment') like in videomapping.
|
||||
- OSC and websocket commands. Very cool : LJ can script or be scripted.
|
||||
- Python3
|
||||
- Web User Interface in your browser : open www/index.html. Javascript is needed. By default it connect to localhost. If you want to control remotely, you need to change the uri line in LJ.js.
|
||||
- Web User Interface in your browser : open www/index.html. Javascript is needed. By default it connect to localhost. If you want to control remotely, you need edit webui choice : python3 configure.py
|
||||
- Live WebUI extras : change debug level, restart plugin, rescan DACs,...
|
||||
- Status update every 0.5 seconds : every etherdream DAC state, number of buffer points sent,...
|
||||
- "Optimisation" points automatically added, can be changed live for glitch art. Search "resampler" commands.
|
||||
@ -260,10 +260,14 @@ DrawDests() will take care of all your declared drawn elements/"objects" and Des
|
||||
# Nannou etherdeam simulator aka visualiser
|
||||
#
|
||||
|
||||
2 compiled nannou visualisers are included, one for Linux, one for macOS. It's pretty old version but much more compatible with "old" processors/computer.
|
||||
Nannou visualiser kind of emulate an etherdream and display in a window what a real laser draws.
|
||||
|
||||
2 compiled nannou visualisers are included, one for Linux, one for macOS. It's pretty old versions but much more compatible with "old" processors/computer, as you may want to repurpose an old computer to run LJ.
|
||||
|
||||
To use this visualiser as one of LJ's lasers, in LJ.conf edit one of line ip = someipaddress with the IP of the computer running the visualiser. Relaunch LJ. One visualiser per computer.
|
||||
|
||||
Nannou visualiser emulation is better and better but one can find a few known non-working situations. See it's github repository (https://github.com/nannou-org/ether-dream/tree/master/dac-emulator) for more recent versions.
|
||||
|
||||
#
|
||||
# Todo
|
||||
#
|
||||
@ -349,9 +353,9 @@ About hardware setup, especially if you have several lasers : ILDA cables are in
|
||||
# Ethertools directory
|
||||
#
|
||||
|
||||
2 useful and always working tools from j4cdac github repository : sitter and talk
|
||||
- Sitter will display all real etherdreams available on the network and their state (playing, idle,...). python sitter.py or use the compiled version (for macOS).
|
||||
- Talk : will draw a 4 colors square. python3 talk3.py
|
||||
2 useful and *always working tools* from j4cdac github repository : sitter and talk.
|
||||
- Sitter will display all etherdreams available on the network and their state (playing, idle,...). python sitter.py or use the compiled version (for macOS). May need tkinter : pip3 install tk
|
||||
- Talk : will draw a 4 colors square. Try : python3 talk3.py -h
|
||||
|
||||
#
|
||||
# Links
|
||||
@ -367,6 +371,8 @@ Generic :
|
||||
|
||||
![Laser Faq](https://www.repairfaq.org/sam/lasersam.htm)
|
||||
|
||||
![Etherdream protocol](https://ether-dream.com/protocol.html)
|
||||
|
||||
There is a nice websocket debug tool : websocat.
|
||||
|
||||
#
|
||||
|
@ -9,7 +9,7 @@ BOOM | WIIIIIZ :: PHHHHHRACKRACKRACK ~~ WOOP ~~###~~ WIIT
|
||||
|
||||
## The basic loop
|
||||
```
|
||||
python3 generators/dummy.py -f 2 | filters/kaleidoscope.py | exports/toRedis.py -v
|
||||
python3 generators/dummy.py -f 2 | python3 filters/kaleidoscope.py | python3 exports/toRedis.py -v
|
||||
------------------------------ --------------------- -------------------
|
||||
\/ \/ \/
|
||||
Generator Filter Export
|
||||
|
@ -165,7 +165,7 @@ class DAC(object):
|
||||
return self.readresp("d")
|
||||
|
||||
def prepare(self):
|
||||
self.conn.sendall('p')
|
||||
self.conn.sendall(b'p')
|
||||
return self.readresp('p')
|
||||
|
||||
def stop(self):
|
||||
|
@ -1,4 +1,17 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
|
||||
Improved dac.py and talk.py (by Jacob Potter). Pimped by Sam Neurohack.
|
||||
|
||||
- python3
|
||||
- works with nannou visualisers
|
||||
- can talk to a given etherdream knowing it's IP.
|
||||
|
||||
v0.1.0
|
||||
|
||||
'''
|
||||
|
||||
#
|
||||
# j4cDAC test code
|
||||
#
|
||||
@ -17,6 +30,19 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import dac3 as dac
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
argsparser = argparse.ArgumentParser(description="Draw a square on a laser via Etherdream DAC")
|
||||
|
||||
argsparser.add_argument("-i","--ip",help="Etherdream IP (default : first etherdream broadcast received",default="True",type=str)
|
||||
|
||||
|
||||
|
||||
args = argsparser.parse_args()
|
||||
etherIP = args.ip
|
||||
|
||||
|
||||
|
||||
class SquarePointStream(object):
|
||||
'''
|
||||
@ -88,8 +114,14 @@ class NullPointStream(object):
|
||||
return [(0, 0, 0, 0, 0)] * n
|
||||
|
||||
#dac.find_dac()
|
||||
if etherIP == "True":
|
||||
print("Waiting for the first DAC broadcast...")
|
||||
d = dac.DAC(dac.find_first_dac())
|
||||
|
||||
d = dac.DAC(dac.find_first_dac())
|
||||
#d = dac.DAC("192.168.1.43")
|
||||
else:
|
||||
print("Using Etherdream :", etherIP)
|
||||
d = dac.DAC(etherIP)
|
||||
|
||||
|
||||
print("Sending points...")
|
||||
d.play_stream(SquarePointStream())
|
||||
|
@ -25,15 +25,15 @@ ljpath = r'%s' % os.getcwd().replace('\\','/')
|
||||
|
||||
# import from shell
|
||||
|
||||
sys.path.append(ljpath +'/../libs/')
|
||||
sys.path.append(ljpath +'/../libs3/')
|
||||
|
||||
#import from LJ
|
||||
sys.path.append(ljpath +'/libs/')
|
||||
print(ljpath+'/../libs/')
|
||||
sys.path.append(ljpath +'/libs3/')
|
||||
print(ljpath+'/../libs3/')
|
||||
|
||||
import lj23layers as lj
|
||||
|
||||
sys.path.append('../libs')
|
||||
sys.path.append('../libs3')
|
||||
from OSC3 import OSCServer, OSCClient, OSCMessage
|
||||
import redis
|
||||
import math
|
||||
|
@ -25,15 +25,15 @@ ljpath = r'%s' % os.getcwd().replace('\\','/')
|
||||
|
||||
# import from shell
|
||||
|
||||
sys.path.append(ljpath +'/../libs/')
|
||||
sys.path.append(ljpath +'/../libs3/')
|
||||
|
||||
#import from LJ
|
||||
sys.path.append(ljpath +'/libs/')
|
||||
print(ljpath+'/../libs/')
|
||||
sys.path.append(ljpath +'/libs3/')
|
||||
print(ljpath+'/../libs3/')
|
||||
|
||||
import lj23layers as lj
|
||||
|
||||
sys.path.append('../libs')
|
||||
sys.path.append('../libs3')
|
||||
from OSC3 import OSCServer, OSCClient, OSCMessage
|
||||
import redis
|
||||
import math
|
||||
|
647
plugins/trckr.py
Normal file
647
plugins/trckr.py
Normal file
@ -0,0 +1,647 @@
|
||||
#!/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 lj23layers as 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);
|
||||
}
|
||||
}
|
||||
'''
|
@ -25,6 +25,7 @@ sudo apt install libjack-dev
|
||||
pip3 install python-rtmidi
|
||||
pip3 install mido
|
||||
git clone https://github.com/ptone/pyosc --depth 1 /tmp/pyosc && cd /tmp/pyosc && sudo ./setup.py install
|
||||
pip3 install tk
|
||||
cd ../
|
||||
python3 configure.py
|
||||
# todo : ask for computer ip and run updateUI.py
|
||||
|
@ -21,7 +21,7 @@ brew install libasound2-dev
|
||||
brew install libjack-dev
|
||||
pip3 install python-rtmidi
|
||||
pip3 install mido
|
||||
|
||||
#pip3 install tk
|
||||
cd ../
|
||||
python3 configure.py
|
||||
#sudo cp syncthing.conf to /etc/supervisor/conf.d/
|
||||
|
@ -60,6 +60,7 @@ def www(wwwip):
|
||||
print("Updating www files to use", wwwIP)
|
||||
Updatepage(ljpath+"/www/LJ.js")
|
||||
Updatepage(ljpath+"/www/trckr/trckrcam1.html")
|
||||
Updatepage(ljpath+"/www/trckr/trckr.html")
|
||||
Updatepage(ljpath+"/www/simu.html")
|
||||
Updatepage(ljpath+"/www/align.html")
|
||||
Updatepage(ljpath+"/www/auralls.html")
|
||||
|
@ -1,5 +1,21 @@
|
||||
clmtrackr
|
||||
======
|
||||
= Web Interface
|
||||
|
||||
You can load index.html file from your browser or have a webserver of your choice pointing to this directory.
|
||||
|
||||
Webserver is mandatory if you want :
|
||||
|
||||
- to remotely control LJ : imagine LJ can be installed in a dedicated computer/container with no easy access.
|
||||
- to use the face tracking, say from a smartphone. That's Lasercam (a clmtrackr plugin).
|
||||
|
||||
== Simu
|
||||
|
||||
A laser simulator. Choose lasernumber and it will display redis points for current scene/lasernumber
|
||||
|
||||
|
||||
|
||||
|
||||
== clmtrackr
|
||||
|
||||
|
||||
[![npm version](https://img.shields.io/npm/v/clmtrackr.svg)](https://www.npmjs.com/package/clmtrackr)
|
||||
|
||||
|
@ -300,16 +300,6 @@
|
||||
console.log("/laser "+res[1])
|
||||
newlaser(res[1])
|
||||
break;
|
||||
|
||||
case "/lack/":
|
||||
console.log("/lack "+res[1])
|
||||
document.getElementById(res[0].slice(1)).value = res[1];
|
||||
break;
|
||||
|
||||
case "/lstt/":
|
||||
console.log("/lstt "+res[1])
|
||||
document.getElementById(res[0].slice(1)).value = res[1];
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
|
@ -287,17 +287,6 @@
|
||||
case "/plpoi":
|
||||
//console.log("plpoint");
|
||||
break;
|
||||
|
||||
case "/lack/":
|
||||
console.log("/lack "+res[1])
|
||||
document.getElementById(res[0].slice(1)).value = res[1];
|
||||
break;
|
||||
|
||||
case "/lstt/":
|
||||
console.log("/lstt "+res[1])
|
||||
document.getElementById(res[0].slice(1)).value = res[1];
|
||||
break;
|
||||
|
||||
default:
|
||||
//console.log("test "+res[0].slice(1)+" "+res[1]);
|
||||
document.getElementById(res[0].slice(1)).value = res[1];
|
||||
|
BIN
www/trckr.png
BIN
www/trckr.png
Binary file not shown.
Before Width: | Height: | Size: 4.2 KiB |
679
www/trckr/trckr.html
Normal file
679
www/trckr/trckr.html
Normal file
@ -0,0 +1,679 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>LASERCam 1</title>
|
||||
<meta charset="utf-8">
|
||||
<link href="./styles/bootstrap.min.css" rel="stylesheet" type="text/css">
|
||||
<meta name="apple-mobile-web-app-title" content="Tracker">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<link rel="apple-touch-startup-image" href="../launch.png">
|
||||
<link rel="apple-touch-icon" href="../touch-icon-iphone.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="../touch-icon-ipad.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="../touch-icon-iphone-retina.png">
|
||||
<link rel="apple-touch-icon" sizes="167x167" href="../touch-icon-ipad-retina.png">
|
||||
|
||||
<style>
|
||||
|
||||
|
||||
</style>
|
||||
<script>
|
||||
// getUserMedia only works over https in Chrome 47+, so we redirect to https. Also notify user if running from file.
|
||||
if (window.location.protocol == "file:") {
|
||||
alert("You seem to be running this example directly from a file. Note that these examples only work when served from a server or localhost due to canvas cross-domain restrictions.");
|
||||
} else if (window.location.hostname !== "localhost" && window.location.protocol !== "https:"){
|
||||
window.location.protocol = "http";
|
||||
//window.location.protocol = "https";
|
||||
}
|
||||
</script>
|
||||
<!--
|
||||
<script type="text/javascript">
|
||||
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'UA-32642923-1']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
|
||||
</script>
|
||||
-->
|
||||
<!-- Web audio buttons defaults -->
|
||||
<script type="application/javascript" src="../webcomponents-lite.js"></script>
|
||||
<script>
|
||||
WebAudioControlsOptions={
|
||||
useMidi:1,
|
||||
knobSrc:"knobs/simplegray.png",
|
||||
knobSprites:100,
|
||||
switchSrc:"knobs/switch_toggle.png",
|
||||
sliderSrc:"knobs/vsliderbody.png",
|
||||
sliderKnobsrc:"knobs/vsliderknob.png",
|
||||
}
|
||||
</script>
|
||||
<script src="../webaudio-controls.js"></script>
|
||||
<!-- link rel="stylesheet" href="LJgrid.css" / -->
|
||||
<link rel="stylesheet" type="text/css" href="../selector.min.css">
|
||||
<script type="application/javascript" src="../selector.min.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="../css/common.css" />
|
||||
|
||||
</head>
|
||||
<body style="background-color:#222;">
|
||||
<script src="./js/libs/utils.js"></script>
|
||||
<script src="../build/clmtrackr.js"></script>
|
||||
<script src="./js/libs/Stats.js"></script>
|
||||
|
||||
<!--
|
||||
Top Rack
|
||||
|
||||
|
||||
<div align="center">
|
||||
<a href="index.html"><img height="25" width="21" src="../knobs/indexs.png"></a>
|
||||
</div>
|
||||
-->
|
||||
|
||||
<div class="Rackcontent">
|
||||
|
||||
|
||||
<!--
|
||||
Navigation Rack
|
||||
-->
|
||||
|
||||
<div class="content">
|
||||
<div class="buttons-7container">
|
||||
|
||||
<a href="../index.html">
|
||||
<div class="webaudiobut">
|
||||
<div align="center" class="navled">
|
||||
Index
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a href="../align.html">
|
||||
<div class="webaudiobut">
|
||||
<div align="center" class="navled">
|
||||
Align
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a href="../auralls.html">
|
||||
<div class="webaudiobut">
|
||||
<div align="center" class="navled">
|
||||
Aurora
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a href="trckrcam1.html">
|
||||
<div class="webaudiobut">
|
||||
<div align="center" class="navled">
|
||||
Lasercam
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a href="../simu.html">
|
||||
<div class="webaudiobut">
|
||||
<div align="center" class="navled">
|
||||
Simu
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
|
||||
<div class="webaudiobut">
|
||||
<button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/restart lj" >
|
||||
rstrt LJ
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="webaudiobut">
|
||||
<button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/restart aurora" >
|
||||
rstrt AU
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
Lasers & colors Rack
|
||||
-->
|
||||
|
||||
|
||||
<div class="content">
|
||||
<div class="TopRackGrid">
|
||||
<div>
|
||||
<h2>
|
||||
/TL RGY 1
|
||||
<span class="shade"> </span>
|
||||
</h2>
|
||||
<webaudio-switch id="on" value="1" tooltip="Switch-B" height="35" width="85" src="../knobs/switch1.png">
|
||||
</webaudio-switch>
|
||||
</div>
|
||||
<div style="border : #242424 1px solid;background: #000;">
|
||||
<div align="center" id="line1" class="busled">
|
||||
LASERcam 1 : Allow to use your webcam + start
|
||||
</div>
|
||||
<div align="center" id="status" class="busled">
|
||||
/team/laser
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
<div>
|
||||
<div style="margin-top : 30px;">
|
||||
</div>
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!--
|
||||
Colors Rack
|
||||
-->
|
||||
<div class="content">
|
||||
<div class="Rackgrid">
|
||||
<div>
|
||||
<h2>
|
||||
Colors
|
||||
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="webaudiobut"><webaudio-switch id="noteon 24" value="1" tooltip="Switch-B" height="64" width="64" src="../knobs/big0.png"></webaudio-switch></div>
|
||||
<div class="webaudiobut"><webaudio-switch id="noteon 25" value="0" tooltip="Switch-B" height="64" width="64" src=" ../knobs/big1.png"></webaudio-switch></div>
|
||||
<div class="webaudiobut"><webaudio-switch id="noteon 26" value="0" tooltip="Switch-B" height="64" width="64" src="../knobs/big2.png"></webaudio-switch></div>
|
||||
<div class="webaudiobut"><webaudio-switch id="noteon 27" value="0" tooltip="Switch-B" height="64" width="64" src="../knobs/big3.png"></webaudio-switch></div>
|
||||
<div></div>
|
||||
<div class="webaudiobut"><webaudio-switch id="trckr/color/0 red" value="1" tooltip="Switch-B" height="64" width="64" src="knobs/red.png"></webaudio-switch></div>
|
||||
<div class="webaudiobut"><webaudio-switch id="trckr/color/0 yellow" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/yellow.png"></webaudio-switch></div>
|
||||
<div class="webaudiobut"><webaudio-switch id="trckr/color/0 green" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/green.png"></webaudio-switch></div>
|
||||
<div></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!--
|
||||
Webcam Rack
|
||||
-->
|
||||
<div class="content" style="background-image: linear-gradient(174deg, #111,#030303);">
|
||||
<video id="videoel" class="webaudiobut" width="400" height="300" preload="auto" loop playsinline autoplay>
|
||||
</video>
|
||||
<canvas id="overlay" width="400" height="300"></canvas>
|
||||
<input class="btn" type="button" value="wait" style="margin-left: 150px;" disabled="disabled" onclick="startVideo()" id="startbutton"></input>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
Big Display Rack
|
||||
-->
|
||||
|
||||
<div class="content">
|
||||
<div id="text" class="busled" style="font-size:1.5em;border : #242424 1px solid;background: #000;-webkit-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72);-moz-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72);box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72);">
|
||||
<div id="gum" class="gum">
|
||||
<p>To try it out:
|
||||
<ol>
|
||||
<li>Allow the page to use your webcamera</li>
|
||||
<li>Make sure that your face is clearly visible in the video, and click start</li>
|
||||
<li>See the model fitted to your face</li>
|
||||
<ol>
|
||||
</p>
|
||||
</div>
|
||||
<div id="nogum" class="nogum">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!--
|
||||
JS
|
||||
-->
|
||||
|
||||
<script>
|
||||
var vid = document.getElementById('videoel');
|
||||
var vid_width = vid.width;
|
||||
var vid_height = vid.height;
|
||||
var overlay = document.getElementById('overlay');
|
||||
var overlayCC = overlay.getContext('2d');
|
||||
|
||||
/*********** Setup of video/webcam and checking for webGL support *********/
|
||||
|
||||
function enablestart() {
|
||||
var startbutton = document.getElementById('startbutton');
|
||||
startbutton.value = "start";
|
||||
startbutton.disabled = null;
|
||||
}
|
||||
|
||||
var insertAltVideo = function(video) {
|
||||
// insert alternate video if getUserMedia not available
|
||||
if (supports_video()) {
|
||||
if (supports_webm_video()) {
|
||||
video.src = "./media/cap12_edit.webm";
|
||||
} else if (supports_h264_baseline_video()) {
|
||||
video.src = "./media/cap12_edit.mp4";
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
function adjustVideoProportions() {
|
||||
// resize overlay and video if proportions of video are not 4:3
|
||||
// keep same height, just change width
|
||||
var proportion = vid.videoWidth/vid.videoHeight;
|
||||
vid_width = Math.round(vid_height * proportion);
|
||||
vid.width = vid_width;
|
||||
overlay.width = vid_width;
|
||||
}
|
||||
|
||||
function gumSuccess( stream ) {
|
||||
// add camera stream if getUserMedia succeeded
|
||||
if ("srcObject" in vid) {
|
||||
vid.srcObject = stream;
|
||||
} else {
|
||||
vid.src = (window.URL && window.URL.createObjectURL(stream));
|
||||
}
|
||||
vid.onloadedmetadata = function() {
|
||||
adjustVideoProportions();
|
||||
vid.play();
|
||||
}
|
||||
vid.onresize = function() {
|
||||
adjustVideoProportions();
|
||||
if (trackingStarted) {
|
||||
ctrack.stop();
|
||||
ctrack.reset();
|
||||
ctrack.start(vid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function gumFail() {
|
||||
// fall back to video if getUserMedia failed
|
||||
insertAltVideo(vid);
|
||||
document.getElementById('gum').className = "hide";
|
||||
document.getElementById('nogum').className = "nohide";
|
||||
}
|
||||
|
||||
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
|
||||
window.URL = window.URL || window.webkitURL || window.msURL || window.mozURL;
|
||||
|
||||
// set up video
|
||||
if (navigator.mediaDevices) {
|
||||
navigator.mediaDevices.getUserMedia({video : true}).then(gumSuccess).catch(gumFail);
|
||||
} else if (navigator.getUserMedia) {
|
||||
navigator.getUserMedia({video : true}, gumSuccess, gumFail);
|
||||
} else {
|
||||
insertAltVideo(vid);
|
||||
document.getElementById('gum').className = "hide";
|
||||
document.getElementById('nogum').className = "nohide";
|
||||
alert("Your browser does not seem to support getUserMedia, using a fallback video instead.");
|
||||
}
|
||||
|
||||
vid.addEventListener('canplay', enablestart, false);
|
||||
|
||||
/*********** Code for face tracking *********/
|
||||
|
||||
var ctrack = new clm.tracker();
|
||||
ctrack.init();
|
||||
var trackingStarted = false;
|
||||
var counter = 0;
|
||||
var layer = 0;
|
||||
|
||||
function startVideo() {
|
||||
// start video
|
||||
vid.play();
|
||||
// start tracking
|
||||
ctrack.start(vid);
|
||||
trackingStarted = true;
|
||||
// start loop to draw face
|
||||
drawLoop();
|
||||
}
|
||||
|
||||
function drawLoop() {
|
||||
requestAnimFrame(drawLoop);
|
||||
overlayCC.clearRect(0, 0, vid_width, vid_height);
|
||||
//psrElement.innerHTML = "score :" + ctrack.getScore().toFixed(4);
|
||||
var positions = ctrack.getCurrentPosition();
|
||||
// do something with the positions ...
|
||||
// print the positions
|
||||
var positionString = "";
|
||||
var positionFace = 'trckr/frame '+layer+" "+counter+" ";
|
||||
if (positions) {
|
||||
ctrack.draw(overlay);
|
||||
for (var p = 0;p < 71;p++) {
|
||||
positionString += "featurepoint "+p+" : ["+positions[p][0].toFixed(2)+","+positions[p][1].toFixed(2)+"]<br/>";
|
||||
positionFace += positions[p][0].toFixed(2)+" "+positions[p][1].toFixed(2)+" ";
|
||||
}
|
||||
|
||||
//document.getElementById('positions').innerHTML = positionString;
|
||||
_WS.s.send(positionFace);
|
||||
counter +=1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*********** Code for stats **********/
|
||||
|
||||
stats = new Stats();
|
||||
stats.domElement.style.position = 'absolute';
|
||||
stats.domElement.style.top = '0px';
|
||||
document.getElementById('container').appendChild( stats.domElement );
|
||||
|
||||
// update stats on every iteration
|
||||
document.addEventListener('clmtrackrIteration', function(event) {
|
||||
stats.update();
|
||||
}, false);
|
||||
|
||||
</script>
|
||||
|
||||
<!-- LJ style WS : A nettoyer ! -->
|
||||
< |