From: Hector Martin Date: Thu, 9 Dec 2010 04:48:41 +0000 (+0100) Subject: Add laser harp example X-Git-Url: https://gitweb.tyo.aptx.org/?a=commitdiff_plain;h=b9bc02acc58b07a0dad42687f6b3f0900479de7a;p=openlase-old.git Add laser harp example --- diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 1056656..00b9f7f 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -31,3 +31,6 @@ target_link_libraries(pong openlase) find_package(ALSA REQUIRED) add_executable(midiview midiview.c) target_link_libraries(midiview openlase ${ALSA_LIBRARIES}) + +add_executable(harp harp.c) +target_link_libraries(harp openlase) diff --git a/examples/harp.c b/examples/harp.c new file mode 100644 index 0000000..f641b47 --- /dev/null +++ b/examples/harp.c @@ -0,0 +1,90 @@ +/* + OpenLase - a realtime laser graphics toolkit + +Copyright (C) 2009-2010 Hector Martin "marcan" + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 or version 3. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +// This is the laser harp projection, which is just a simple OpenLase app */ + +#include "libol.h" + +#include +#include +#include +#include +#include +#include + +int offs[12] = { + 0,1,0,1,0,0,1,0,1,0,1,0 +}; +float pos[12] = { + 0,0.5,1,1.5,2,3,3.5,4,4.5,5,5.5,6 +}; + +int main (int argc, char *argv[]) +{ + OLRenderParams params; + + memset(¶ms, 0, sizeof params); + params.rate = 48000; + params.on_speed = 2.0/100.0; + params.off_speed = 2.0/30.0; + params.start_wait = 4; + params.start_dwell = 3; + params.curve_dwell = 0; + params.corner_dwell = 4; + params.curve_angle = cosf(30.0*(M_PI/180.0)); // 30 deg + params.end_dwell = 2; + params.end_wait = 5; + params.snap = 1/100000.0; + params.render_flags = RENDER_GRAYSCALE; + + if(olInit(3, 30000) < 0) + return 1; + + olSetRenderParams(¶ms); + + float time = 0; + float ftime; + int i; + + int frames = 0; + + int points = 25; + + while(1) { + olLoadIdentity(); + + int total_y = (points / 12.0 * 7.0 + 1); + + for (i=0; i +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 or version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# This is the laser harp sensing portion, which has nothing to do with OpenLase. +# You need OpenCV (2.2.0) and PyALSA installed +# Pass the destination ALSA MIDI client:port pair as an argument. + +# You may need to edit some constants here + +THRESHOLD=200 +WIDTH=320 +HEIGHT=240 + +NOTE_OFFSET=47 + +VELOCITY=90 + +import sys, math +import cv + +from pyalsa import alsaseq + +seq = alsaseq.Sequencer(name="default", clientname=sys.argv[0], streams = alsaseq.SEQ_OPEN_DUPLEX, mode = alsaseq.SEQ_NONBLOCK) +port = seq.create_simple_port( + name='out', + type = alsaseq.SEQ_PORT_TYPE_MIDI_GENERIC | alsaseq.SEQ_PORT_TYPE_APPLICATION, + caps = alsaseq.SEQ_PORT_CAP_READ | alsaseq.SEQ_PORT_CAP_SUBS_READ) + +def note(n, state=False): + if state: + etype = alsaseq.SEQ_EVENT_NOTEON + else: + etype = alsaseq.SEQ_EVENT_NOTEOFF + event = alsaseq.SeqEvent(type=etype) + event.set_data({'note.channel': 0, 'note.note': n, 'note.velocity': 90}) + seq.output_event(event) + seq.drain_output() + +if len(sys.argv) > 1: + toport = seq.parse_address(sys.argv[1]) + seq.connect_ports((seq.client_id, port), toport) + +camera = cv.CreateCameraCapture(0) +cv.SetCaptureProperty(camera, cv.CV_CAP_PROP_FRAME_WIDTH, WIDTH) +cv.SetCaptureProperty(camera, cv.CV_CAP_PROP_FRAME_HEIGHT, HEIGHT) +cv.SetCaptureProperty(camera, cv.CV_CAP_PROP_BRIGHTNESS, 0) + +image = cv.QueryFrame(camera) +grey = cv.CreateImage(cv.GetSize(image), cv.IPL_DEPTH_8U, 1) +grey2 = cv.CreateImage(cv.GetSize(image), cv.IPL_DEPTH_8U, 1) + +def getpoints(image): + points = [] + cv.CvtColor(image, grey, cv.CV_RGB2GRAY) + cv.Threshold(grey, grey, THRESHOLD, 255, cv.CV_THRESH_BINARY) + cv.Copy(grey, grey2) + + storage = cv.CreateMemStorage(0) + contour = cv.FindContours(grey, storage, cv.CV_RETR_CCOMP, cv.CV_CHAIN_APPROX_SIMPLE) + while contour: + bound_rect = cv.BoundingRect(list(contour)) + contour = contour.h_next() + + pt = (bound_rect[0] + bound_rect[2]/2, bound_rect[1] + bound_rect[3]/2) + #cv.Circle(image, pt, 2, cv.CV_RGB(255,0,0), 1) + points.append(pt) + return points + +def near(p1, p2, d): + x,y = (p1[0]-p2[0],p1[1]-p2[1]) + dist = math.sqrt(x**2+y**2) + return dist < d + +refpoints = getpoints(image) +refpoints.sort(key=lambda x: x[1]) + +oldstate = None + +while True: + image = cv.QueryFrame(camera) + cpoints = getpoints(image) + state = [False]*len(refpoints) + for i, rp in enumerate(refpoints): + for cp in cpoints: + if near(rp,cp,3): + break + else: + state[i] = True + + if oldstate is not None: + for i,(j,k) in enumerate(zip(oldstate, state)): + if j != k: + note(NOTE_OFFSET+len(oldstate)-i, k) + if k: + print "PRESSED: %d"%i + else: + print "RELEASED: %d"%i + oldstate = state + + cv.ShowImage("thresholded", grey2) + if cv.WaitKey(10)&0xfff == 27: + break