Visualizzazione post con etichetta Impress. Mostra tutti i post
Visualizzazione post con etichetta Impress. Mostra tutti i post

martedì 18 marzo 2014

Comandare Impress con Raspberry + HC-SR04 + Python

Sulla base del precedente post  mi sono chiesto se era possibile ridurre al minimo la spesa (ed il consumo di corrente). In questa ottica ho provato a montare una Raspberry che si interfaccia direttamente con l'HC-SR04 per fare una presentazione. In questo caso si ha la comodita' di poter far girare la presentazione anche su televisori di generose dimensioni vista l'uscita HDMI (nel test e' stato usato un mini monitor ma solo perche' il televisore di casa era occupato)



Il collegamento tra le porte GPIO e la Raspberry e' il seguente
VCC 5 V
GND
GPIO 17 connesso a Trigger
GPIO 27 connesso a Echo con con una resistenza da 1 KOhm


Dato che la prova e' stata fatta con PiBang e non Raspbian c'e' da montare la libreria Gpio per Python che non e' inclusa di default
Per fare cio'
apt-get install build-essential python-dev python-pip
pip install rpi.gpio

il comando xdotool invece e' gia' compreso in PiBanf
lo script che ho utilizzato deriva da questo sito leggermente modificato
Quando la distanza risulta inferiore a 30 cm viene cambiata la diapositiva 
------------------------------------------------------------

#!/usr/bin/python
import os

contatore = 1

def reading(sensor):
    import time
    import RPi.GPIO as GPIO
    
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    
    if sensor == 0:
        GPIO.setup(17,GPIO.OUT)
        GPIO.setup(27,GPIO.IN)
        GPIO.output(17, GPIO.LOW)
        time.sleep(0.3)

        GPIO.output(17, True)
        time.sleep(0.00001)
        GPIO.output(17, False)

        while GPIO.input(27) == 0:
          signaloff = time.time()

        while GPIO.input(27) == 1:
          signalon = time.time()
        
        timepassed = signalon - signaloff
        distance = timepassed * 17000
        return distance
        
        GPIO.cleanup()

    else:
        print "Incorrect usonic() function varible."

while True:        
if (reading(0) < 30):
contatore = contatore + 1
print contatore
if (contatore >= 4):
contatore = 1
os.system("xdotool key 1")
os.system("xdotool key Return")
else:
os.system("xdotool key Right")
------------------------------------------------------------
Rispetto al precedente script si vede che i comandi di xdotool sono stati modificati. Non ho chiaro il motivo per cui e' stata necessaria la modifica ma penso che sia attribuibile al WM che e' differente tra Ubuntu (Gnome) e PiBang(OpenBox)

Con questa configurazione il costo dell'hardware (monitor o televisore escluso) e' dell'ordine dei 50 euro


venerdì 14 marzo 2014

Comandare Impress con Arduino + HC-SR04 + Python

Sempre alla ricerca di un sistema semplice e poco costoso per fare una postazione interattiva al Museo di Mineralogia, ho provato la strada Arduino

I difetti dei tentativi precedenti erano che Kinect costa un troppo mentre l'accoppiata Raspberry+Webcam e' troppo soggetta ad errori
In questo caso ho provato ad usare una Arduino accoppiata al sensore di distanza HC-SR04 (il costo finale e' inferiore ai 20 euro)


Nella prova ho usato una Arduino Due (nel caso reale va bene una Arduino Mini) che ho scoperto non avere la compatibilita' con la libreria NewPing. Per questo motivo e' stato usato lo sketch di esempio sul sito Arduino (rimuovendo la sezione relativa ai due led)
le connessioni sono semplici

Vcc
GND
Pin 13 : Echo
Pin 12 : Trigger

lo sketch manda la distanza via seriale ad un script in Python in ascolto. Se la distanza e' inferiore ai 50 cm viene cambiata la diapositiva

Video della prova


Con questa configurazione sono minimizzati i falsi click. In versione definitiva puo' essere utile mettere due sensori ultrasonici per permettere di andare avanti ed indietro nella presentazione

Programma Python
---------------------------------------
import serial,os, time

diapositiva = 1
ser = serial.Serial('/dev/ttyACM0', 9600)
while True:
distanza = int(ser.readline())

if (distanza < 50):
diapositiva = diapositiva + 1
if (diapositiva == 5):
os.system("xdotool key --window $(xdotool search --name 'presentazione.odp - LibreOffice Impress') 1")
os.system("xdotool key --window $(xdotool search --name 'presentazione.odp - LibreOffice Impress') KP_Enter")
diapositiva = 1
else:
os.system("xdotool key --window $(xdotool search --name 'presentazione.odp - LibreOffice Impress') Right")
----------------------------------------

Sketch Arduino
----------------------------------------
/*
 HC-SR04 Ping distance sensor]
 VCC to arduino 5v GND to arduino GND
 Echo to Arduino pin 13 Trig to Arduino pin 12
 Red POS to Arduino pin 11
 Green POS to Arduino pin 10
 560 ohm resistor to both LED NEG and GRD power rail
 More info at: http://goo.gl/kJ8Gl
 Original code improvements to the Ping sketch sourced from Trollmaker.com
 Some code and wiring inspired by http://en.wikiversity.org/wiki/User:Dstaub/robotcar
 */

#define trigPin 13
#define echoPin 12

void setup() {
  Serial.begin (9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop() {
  long duration, distance;
  digitalWrite(trigPin, LOW);  // Added this line
  delayMicroseconds(2); // Added this line
  digitalWrite(trigPin, HIGH);
//  delayMicroseconds(1000); - Removed this line
  delayMicroseconds(10); // Added this line
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
  if (distance < 4) {  // This is where the LED On/Off happens
}
  else {
  }
  if (distance >= 200 || distance <= 0){
    Serial.println(200);
  }
  else {
    Serial.println(distance);
  }
  delay(500);
}


martedì 11 marzo 2014

Cambiare diapositiva su Impress mediante gesture a webcam

Un amico mi ha chiesto se era possibile sviluppare una piccola applicazione interattiva per il museo di Scienze Geologiche del Dipartimento di Scienze della Terra di Firenze
L'idea di base era quella di usare Kinect per cambiare la slide ad una presentazione a video

L'idea mi sembrava carina ma piuttosto costosa in quanto necessita di un Kinect e di un computer discretamente potente per fare processare i dati (Kinect di suo non interpreta le gesture, e' solo un insieme di sensori)..volevo vedere se era possibile fare la stessa cosa usando solo una Raspberry ed una normale Webcam




L'idea di base e' stata rubata a questo sito semplificando di molto per cio' che non mi occorre. In pratica sull'immagine della Webcam sono state create due aree sensibili (i due cerchietti in alto, per essere precisi vengono letti solo due pixel), se l'utente passa la mano sui cerchietti (o meglio se viene individuata una variazione dell'immagine in corrispondenza dei pixel sensibili) viene generato un evento.
Per evitare falsi allarmi e' stato impostato una distanza minima di 1.5 secondi tra due eventi
Il programma processa i dati della webcam, crea una immagine differenza tra le immagini in sequenza e crea una immagine maschera dei pixel che risultano cambiati (si puo' vedere premendo il tasto d durante l'esecuzione). La condizione di pixel non cambiato e' 0, la condizione di cambiato e' 255

Se viene generato un evento allora mediante il programma xdotool viene inviato un segnale Freccia Destra/ Freccia Sinistra alla finestra che ha per nome "'presentazione.odp - LibreOffice Impress"

Ovviamente ci sono dei limiti all'utilizzo (del tipo la webcam non deve essere orientata verso il corridoio del museo altrimenti vengono generati eventi ogni volta che passa una persona) ma considerando il costo dell'applicazione e le possibili applicazioni (si puo' fare per esempio un quiz interattivo per bambini) direi che e' abbastanza interessante

-----------------------------------------------------------------------------
#!/usr/bin/env python

import cv
import time

from scipy import *
from scipy.cluster import vq
import numpy
import sys, os, random#, hashlib

from math import *


class Target:
def __init__(self):

if len( sys.argv ) > 1:
self.writer = None
self.capture = cv.CaptureFromFile( sys.argv[1] )
frame = cv.QueryFrame(self.capture)
frame_size = cv.GetSize(frame)
else:
fps=15
is_color = True


self.capture = cv.CaptureFromCAM(0)
cv.SetCaptureProperty( self.capture, cv.CV_CAP_PROP_FRAME_WIDTH, 640 );
cv.SetCaptureProperty( self.capture, cv.CV_CAP_PROP_FRAME_HEIGHT, 480 );
frame = cv.QueryFrame(self.capture)
frame_size = cv.GetSize(frame)

self.writer = None

frame = cv.QueryFrame(self.capture)
cv.NamedWindow("Museo", 1)



def run(self):

frame = cv.QueryFrame( self.capture )
frame_size = cv.GetSize( frame )

contatore = 0
tempo_d = 0
tempo_s = 0

# Capture the first frame from webcam for image properties
display_image = cv.QueryFrame( self.capture )

# Greyscale image, thresholded to create the motion mask:
grey_image = cv.CreateImage( cv.GetSize(frame), cv.IPL_DEPTH_8U, 1 )

# The RunningAvg() function requires a 32-bit or 64-bit image...
running_average_image = cv.CreateImage( cv.GetSize(frame), cv.IPL_DEPTH_32F, 3 )
# ...but the AbsDiff() function requires matching image depths:
running_average_in_display_color_depth = cv.CloneImage( display_image )

# The difference between the running average and the current frame:
difference = cv.CloneImage( display_image )

#t0 = time.time()

# For toggling display:
image_list = [ "camera", "difference", "threshold"]
image_index = 0   # Index into image_list


# Prep for text drawing:
text_font = cv.InitFont(cv.CV_FONT_HERSHEY_COMPLEX, .5, .5, 0.0, 1, cv.CV_AA )


while True:
# Capture frame from webcam
camera_image = cv.QueryFrame( self.capture )

frame_t0 = time.time()

# Create an image with interactive feedback:
display_image = cv.CloneImage( camera_image )

# Create a working "color image" to modify / blur
color_image = cv.CloneImage( display_image )

# Smooth to get rid of false positives
cv.Smooth( color_image, color_image, cv.CV_GAUSSIAN, 19, 0 )

# Use the Running Average as the static background
# a = 0.020 leaves artifacts lingering way too long.
# a = 0.320 works well at 320x240, 15fps.  (1/a is roughly num frames.)
cv.RunningAvg( color_image, running_average_image, 0.320, None )

# Convert the scale of the moving average.
cv.ConvertScale( running_average_image, running_average_in_display_color_depth, 1.0, 0.0 )

# Subtract the current frame from the moving average.
cv.AbsDiff( color_image, running_average_in_display_color_depth, difference )

# Convert the image to greyscale.
cv.CvtColor( difference, grey_image, cv.CV_RGB2GRAY )

# Threshold the image to a black and white motion mask:
cv.Threshold( grey_image, grey_image, 2, 255, cv.CV_THRESH_BINARY )
# Smooth and threshold again to eliminate "sparkles"
cv.Smooth( grey_image, grey_image, cv.CV_GAUSSIAN, 19, 0 )
cv.Threshold( grey_image, grey_image, 240, 255, cv.CV_THRESH_BINARY )

grey_image_as_array = numpy.asarray( cv.GetMat( grey_image ) )




c = cv.WaitKey(7) % 0x100
if c == 27 or c == 10:
break

# Toggle which image to show
if chr(c) == 'd':
image_index = ( image_index + 1 ) % len( image_list )

image_name = image_list[ image_index ]


# Display frame to user
if image_name == "camera":
image = camera_image
cv.PutText( image, "O", (50,50), text_font, cv.CV_RGB(255,0,0) )
cv.PutText( image, "O", (590,50), text_font, cv.CV_RGB(0,255,0) )
elif image_name == "difference":
image = difference
cv.PutText( image, "O", (50,50), text_font, cv.CV_RGB(255,0,0) )
cv.PutText( image, "O", (590,50), text_font, cv.CV_RGB(0,255,0) )

elif image_name == "threshold":
# Convert the image to color.
cv.CvtColor( grey_image, display_image, cv.CV_GRAY2RGB )
image = display_image  # Re-use display image here
cv.PutText( image, "O", (50,50), text_font, cv.CV_RGB(255,0,0) )
cv.PutText( image, "O", (590,50), text_font, cv.CV_RGB(0,255,0) )

cv.PutText( image, str(contatore), (320,50), text_font, cv.CV_RGB(0,0,255) )

cv.ShowImage( "Museo", image )

#print grey_image_as_array.item((50,50))

if ((grey_image_as_array.item(50,50) == 255) and ((time.time()-tempo_d) > 1.5)):
#print time.time()-tempo_d
tempo_d = time.time()
contatore = contatore + 1
#print "destra"
os.system("xdotool key --window $(xdotool search --name 'presentazione.odp - LibreOffice Impress') Left")


if ((grey_image_as_array.item(50,590) == 255) and ((time.time()-tempo_s) > 1.5)):
#print time.time()-tempo_s
tempo_s = time.time()
contatore = contatore - 1
#print "sinistra"
os.system("xdotool key --window $(xdotool search --name 'presentazione.odp - LibreOffice Impress') Right")



if self.writer:
cv.WriteFrame( self.writer, image );



if __name__=="__main__":
t = Target()
t.run()




Geologi

  E so anche espatriare senza praticamente toccare strada asfaltata