Talk at Sheffield Ruby User Group
14 Jun 2010
I am going to give a presentation about Hornetseye at the Sheffield Ruby User Group (ShRUG). The meeting is on Monday June 14th from 7pm to 9pm at the GIST Lab in Sheffield Workstation. For more details see corresponding page on ShRUG website . Please register here if you want to attend.
I hope people will find the GIST lab. It’s the first side entrance to the Workstation when you walk down the small alley to the right of the building (as seen from Brown street). Also see Google Streetview .
Here is the source code of the main program
#!/usr/bin/env ruby
require 'hornetseye'
require 'x11test'
include Hornetseye
SHAPE = [ 320 , 240 ]
DISPLAY = [ 320 , 240 ]
SIZE = SHAPE [ 0 ] * SHAPE [ 1 ]
SIGMA = 1.5
ERROR = 1.0 / 32.0
THRESHOLD = 10
SKIP = 10
CAPTION = [ 'pointer' ]
RANGE = 0.001 .. 0.25
TIME = 0.3
ACCEL = 5
SPEED0 = 4
SPEED1 = 20
old_x , old_y = nil , nil
display = X11Display . new
output = ( 0 ... CAPTION . size ). collect { XImageOutput . new }
window = output . collect { | out | X11Window . new display , out , * DISPLAY }
window . zip ( CAPTION ). each { | win , cap | win . title = cap }
window . each { | win | win . show }
input = DC1394Input . new '' , 0 , 0 ,
DC1394Input :: FORMAT_VGA_NONCOMPRESSED ,
DC1394Input :: MODE_320x240_YUV422
index = MultiArray . int ( * SHAPE ). indgen!
x , y = index % SHAPE [ 0 ], index / SHAPE [ 0 ]
border = MultiArray . int ( * SHAPE ). fill! 1
border [ 1 ... SHAPE [ 0 ] - 1 , 1 ... SHAPE [ 1 ] - 1 ] = 0
SKIP . times { input . read }
bg = input . read_sint
t_on , t_off = 0 , 0
a = 0
while display . status?
img = input . read_ubyte
binary = img - bg <= THRESHOLD
components = binary . components
n_components = components . max + 1
area = components . hist n_components
mask_area = area . between? RANGE . min * SIZE ,
RANGE . max * SIZE
mask_border = components .
hist_weighted ( n_components , border ). eq 0
mask = mask_area . and mask_border
map = mask . to_ubyte . integral * mask . to_ubyte
target = components . map map
output [ 0 ]. write target . normalise ( 0 .. 127 ) + img / 2
n_targets = target . max + 1
t = Time . new . to_f
if n_targets == 2
sum_target = target . sum . to_f
x_target = x . mask ( target . to_bool ). sum / sum_target
y_target = y . mask ( target . to_bool ). sum / sum_target
if old_x and old_y
d_x , d_y = old_x - x_target , old_y - y_target
if d_x . abs + d_y . abs < ACCEL
d_x *= SPEED0
d_y *= SPEED0
else
d_x *= SPEED1
d_y *= SPEED1
end
display .
fake_relative_motion_event d_x . to_i , d_y . to_i , 0
else
t_on = t
end
if t_off + TIME >= t
display . fake_button_event 1 , true , 0
t_off = - 1
end
else
x_target , y_target = nil , nil
if old_x and old_y
display . fake_button_event 1 , false , 0 if t_off == - 1
t_off = t
end
if t_on + TIME >= t
display . fake_button_event 1 , true , 0
display . fake_button_event 1 , false , 100
t_on = 0
end
end
old_x , old_y = x_target , y_target
display . processEvents
end
And below follows the source code of the Ruby extension for adding pointer control to the HornetsEye library
#include <X11/extensions/XTest.h>
#define HAVE_X11
#include "rubytools.hh"
#include "x11display.hh"
using namespace Hornetseye ;
VALUE wrapFakeButtonEvent ( VALUE rbSelf ,
VALUE rbButton ,
VALUE rbPress ,
VALUE rbDelay )
{
Display * display = XOpenDisplay ( NULL );
XTestFakeButtonEvent ( display , NUM2INT ( rbButton ),
rbPress != Qfalse ? True : False ,
NUM2INT ( rbDelay ) );
XCloseDisplay ( display );
return rbSelf ;
}
VALUE wrapFakeRelativeMotionEvent ( VALUE rbSelf ,
VALUE rbX ,
VALUE rbY ,
VALUE rbDelay )
{
Display * display = XOpenDisplay ( NULL );
XTestFakeRelativeMotionEvent ( display ,
NUM2INT ( rbX ),
NUM2INT ( rbY ),
NUM2INT ( rbDelay ) );
XCloseDisplay ( display );
return rbSelf ;
}
extern "C" {
void Init_x11test ( void )
{
rb_require ( "hornetseye" );
VALUE mHornetseye = rb_define_module ( "Hornetseye" );
VALUE cX11Display =
rb_define_class_under ( mHornetseye , "X11Display" , rb_cObject );
rb_define_method ( cX11Display , "fake_button_event" ,
RUBY_METHOD_FUNC ( wrapFakeButtonEvent ), 3 );
rb_define_method ( cX11Display , "fake_relative_motion_event" ,
RUBY_METHOD_FUNC ( wrapFakeRelativeMotionEvent ),
3 );
}
}
See also: