Sprünge bei Programmausführung

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
mieth
User
Beiträge: 4
Registriert: Samstag 27. Februar 2016, 23:56

Hallo Forummitglieder,

ich bin gerade dabei, ein Photobox für meine Hochzeit selbst zu bauen. Hierbei habe ich mich hieran orientiert:

http://maltekueppers.de/dc/index.php?po ... Photobooth

Das Programm läuft und tut, was es soll. Ein Problem ist allerdings, dass während das Programm läuft, immer wieder kurz zum "Desktop" zurückgeswitcht wird.

Also in etwa so:

-Buzzer wird ausgelöst
-Sprung zurück zum Desktop
-vier Fotos werden gemacht
-Sprung zurück zum Desktop
-Ladebild wird angezeigt
-Sprung zurück zum Desktop
-Die vier Bilder wurden zu einem zusammengefügt. Dieses wird angezeigt
-Sprung zurück zum Desktop
-Jetzt werden in zufälliger Reihenfolge alte Bilder angezeigt, bis der Buzzer erneut ausgelöst wird.

Was mich stört sind wie beschrieben diese Sprünge zurück. Wenn das Programm läuft, soll ja nicht gesehen werden, was im Hintergrund läuft.
Kann mir jemand helfen, diesen "Fehler" zu eliminieren?

Ich hoffe, ich habe mich so ausgedrückt, dass man mich versteht :)

Vielen Dank schon mal im Voraus

Tommy
BlackJack

@mieth: Da kann man ohne Quelltext nicht wirklich etwas zu sagen. Das verlinkte Blog enthält ja nur Bruchstücke. Die im übrigen nicht gut sind, der Autor scheint da irgendwie in einer anderen Programmiersprache arbeiten zu wollen. So oft wie dort `gc.collect()` und ``del`` vorkommt, scheint er komische Vorstellungen von Python's Speicherverwaltung zu haben.

Bei den vielen `os.system()`-Aufrufen frage ich mich ja fast ob das übehaupt ein Python-Programm ist oder nicht doch ein Shell-Programm.Das Programm scheint bereits PIL/Pillow zu verwenden, ruft aber trotzdem für alles mögliche ImageMagick-Programme per `os.system()` auf. Was soll der Unsinn? Und selbst wenn man ImageMagick verwenden möchte: Es gibt eine Python-Anbindung an die `libmagick`, da muss man nicht erst eine Shell und darin dann Konsolenprogramme starten die letztlich die `libmagick` verwenden. Auch für das kopieren und löschen von Dateien muss man nicht die Programme ``cp`` und ``rm`` aufrufen. Wozu dann überhaupt Python?

Vermutlich, wenn ich mir den Blogbeitrag anschaue auf den sich der Autor dort bezieht, könnten die ”Sprünge” zustande kommen weil er nicht einmal ein Pygame-Fenster erstellt und damit dann durchgehend arbeitet, sondern das immer mal wieder schliesst und ein neues erstellt.
mieth
User
Beiträge: 4
Registriert: Samstag 27. Februar 2016, 23:56

hallo blackjack danke für die schnelle antwort

Das komplette python skript steht ganz unten in dem link vor den kommentare

da musste drauf klicken (Der komplette Code: photobooth.py)

ich habe gedacht das eigenlich dieser eintrag im skript das problem beheben sollte: pygame.display.flip() # update the display :K

,das tut es aber leider nicht, kann es sein das ich noch was installieren muss z.b ein modul oder ein teil von einem modul :shock:

(das mit dem löschen und der speicherung auf usb stick habe ich rausgenommen in meinen skript, bei mir findet die speicherung auf der
sd karte (128Gb) statt.)
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@mieth: durch den Spaghetti-Code möchte sich eigentlich niemand durcharbeiten. Der Kommentar in »display_pics« sagt doch schon alles:

Code: Alles auswählen

    # this section is an unbelievable nasty hack - for some reason Pygame
    # needs a keyboardinterrupt to initialise in some limited circs (second time running)
Der Schreiber wundert sich, warum beim zweiten man Initialisieren von Pygame irgendetwas nicht so ganz richtig funktioniert. Ganz einfach, weil man Pygame nur ein mal intitialisieren sollte!
Wenn das Skript läuft, hast Du eigentlich alle Module installiert.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Das Problem was du hast ist nur das Symptom eines viel größeren Problems auf das BlackJack in seinem Beitrag schon teilweise eingegangen ist.

Bei dem Schreiben des Skripts sind soviele schlechte Entscheidungen gefällt worden, sowohl bei einigen Details als auch bei grundlegenden Dingen, dass man dort nicht sinnvoll irgendwas beheben oder verbessern kann.

Man kann eigentlich nur empfehlen dieses Skript zu vergessen und bei Null anzufangen. Vorallem wenn man bedenkt dass dieses Projekt bei deiner Hochzeit verwenden möchtest und du dort sicherlich besseres zu tun hast als dich damit zu beschäftigen dass deine Photobox nicht mehr funktioniert.
mieth
User
Beiträge: 4
Registriert: Samstag 27. Februar 2016, 23:56

Hallo,

vielen Dank für eure Hilfe und eure Mühe.

Die Sache ist ja, dass eigentlich alles super fuktioniert. Es werden Bilder gemacht, die werden richtig zusammengefügt und alles.

Nur das Springen ist irgendwie doof....

Ich habe den Code mal angehängt. Es wäre cool, wenn ihr euch das noch einmal anschauen könntet. Vielleicht gibt es ja doch eine einfache Lösung für mich. Ich bin selbst noch Anfänger, wie ihr sicher gemerkt habt. Und von Neuem beginnen, gibt der Zeitplan eigentlich nicht her...

Code: Alles auswählen

#!/usr/bin/env python
# created by chris@drumminhands.com
# see instructions at http://www.drumminhands.com/2014/06/15/ ... oto-booth/

import traceback
import os
import glob
import time
from time import sleep
import RPi.GPIO as GPIO
import picamera
import atexit
import sys
import random
from PIL import Image
import smtplib
import socket
import pygame
from pygame.locals import *
from signal import alarm, signal, SIGALRM, SIGKILL
import gc
import subprocess



########################
### Variables Config ###
########################
led1_pin = 37 # LED 1 GPIO 26
led2_pin = 15 # LED 2 GPIO 22
led3_pin = 38 # LED 3 GPIO 20
led4_pin = 33 # LED 4 GPIO 13
button1_pin = 16 # GPIO 23 pin Knopf (taster) Bilder machen 
button2_pin = 35 # GPIO 19 pin Knopf (taster) Pi Runterfahren
button3_pin = 36 # GPIO 16 pin Neustart oder programm beenden





total_pics = 4 # Wieviele Bilder gemacht werden
capture_delay = 0.5 # delay between pics
prep_delay = 1 # number of seconds at step 1 as users prep to have photo taken
gif_delay = 100 # How much time between frames in the animated gif
file_path = '/home/pi/Desktop/fotos/' #Speicherort der Bilder

w = 1230 #max.1440
h = 950 #amx.1080

#monitor_w = 800 #Mieth bildschirm weite
#monitor_h = 600 #Mieth bildschirm hohe

hoehe_klein = 1440 #1920 #1440 #variabele von michi montage
breite_klein = 1280 #1280 #1080 #variabele von michi montage


transform_x = 1230 #weite von den bilder die wiedergegen sollen max.1440
transfrom_y = 950 #hoehe von den bilder die wiedergegen sollen max.1080
offset_x = 0 #350 #how far off to left corner to display photos
offset_y = 0 #wie weit von zur linken Ecke, um Fotos zu zeigen 
replay_delay = 3 # how much to wait in-between showing pics on-screen after taking
replay_cycles = 3 # how many times to show each photo on-screen after taking

start_again = False


####################
### Other Config ###
####################

GPIO.setmode(GPIO.BOARD)
GPIO.setup(led1_pin,GPIO.OUT) # LED 1
GPIO.setup(led2_pin,GPIO.OUT) # LED 2
GPIO.setup(led3_pin,GPIO.OUT) # LED 3
GPIO.setup(led4_pin,GPIO.OUT) # LED 4
GPIO.setup(button1_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Prellung des tasters verhindern taster 1
GPIO.setup(button2_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Prellung des tasters verhindern taster 2
GPIO.setup(button3_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Prellung des tasters verhindern taster 3
GPIO.output(led1_pin,False);
GPIO.output(led2_pin,False);
GPIO.output(led3_pin,False);
GPIO.output(led4_pin,False); #for some reason the pin turns on at the beginning of the program. why?????????????????????????????????

#################
### Functions ###
#################

def lightshow(stime):
	GPIO.output(led1_pin,False)
	GPIO.output(led2_pin,False)
	GPIO.output(led3_pin,False)
	sleep(stime)
	GPIO.output(led1_pin,True)
	sleep(stime)
	GPIO.output(led2_pin,True)
	sleep(stime)
	GPIO.output(led3_pin,True)		
	sleep(stime)
		

	
def reset_event_detection_shutdown():
	sleep(0.5)
	GPIO.remove_event_detect(button2_pin)
	sleep(0.1)
	GPIO.add_event_detect(button2_pin, GPIO.FALLING, callback=shut_it_down, bouncetime=300) 
	
def reset_event_detection_reboot():
	sleep(0.5)
	GPIO.remove_event_detect(button3_pin)
	sleep(0.1)
	GPIO.add_event_detect(button3_pin, GPIO.FALLING, callback=exit_photobooth, bouncetime=300) 


def cleanup():
  print('Fotobox Progamm sofort beendet')
  GPIO.cleanup()
atexit.register(cleanup)

def shut_it_down(channel):
	sleep(0.5)
	counter=0
	while GPIO.input(channel) == GPIO.LOW :
		counter=counter+1
		sleep(0.1)
	     
	if (counter >= 8): 
		print str(counter) + "counter"
		print "PI Runterfahren..." 
		GPIO.remove_event_detect(button2_pin)
		lightshow(1)
		#GPIO.output(led1_pin,True);
		#GPIO.output(led2_pin,True);
		#GPIO.output(led3_pin,True);
		#GPIO.output(led4_pin,True);
		time.sleep(3)
		os.system("sudo shutdown now -h")
    	
	else:
		print "Press longer to shutdown!"
		print str(counter) + "counter"
		reset_event_detection_shutdown()


def exit_photobooth(channel):	
    sleep(0.5)
    print "reboot Call"
    counter=0 
    while GPIO.input(channel) == GPIO.LOW :
    	counter=counter+1
    	print "B-Press"
    	sleep(0.1)		
    	
	if (counter >= 2): 
		print str(counter) + "counter"
		print "Rebooting..." 
		GPIO.remove_event_detect(button3_pin)
		lightshow(1)
		#GPIO.output(led1_pin,True);
		#GPIO.output(led2_pin,True);
		#GPIO.output(led3_pin,True);
		#GPIO.output(led4_pin,True);
		time.sleep(3)
		GPIO.cleanup() #mieth
		os.system ("sudo killall python ")#killall python #mieth
    	
	else:
		print "Press longer to reboot!"
		print str(counter) + "counter"
		reset_event_detection_reboot()
    
def clear_pics(foo): #why is this function being passed an arguments?
    #delete files in folder on startup
	files = glob.glob(file_path + '*')
	for f in files:
		os.remove(f) 
	#light the lights in series to show completed
	print "Deleted previous pics"
	GPIO.output(led1_pin,False); #turn off the lights
	GPIO.output(led2_pin,False);
	GPIO.output(led3_pin,False);
	GPIO.output(led4_pin,False)
	pins = [led1_pin, led2_pin, led3_pin, led4_pin]
	for p in pins:
		GPIO.output(p,True); 
		sleep(0.25)
		GPIO.output(p,False);
		sleep(0.25)
       

def display_pics(jpg_group):
    # this section is an unbelievable nasty hack - for some reason Pygame
    # needs a keyboardinterrupt to initialise in some limited circs (second time running)
    class Alarm(Exception):
        pass
    def alarm_handler(signum, frame):
        raise Alarm
    signal(SIGALRM, alarm_handler)
    alarm(3)
    try:
        pygame.init()
        screen = pygame.display.set_mode((w,h),pygame.FULLSCREEN) 
        alarm(0)
    except Alarm:
        raise KeyboardInterrupt
    pygame.display.set_caption('Photo Booth Pics')
    pygame.mouse.set_visible(False) #hide the mouse cursor	
   
    filename = file_path + jpg_group + "-montage.jpg"
    img=pygame.image.load(filename) 
    img = pygame.transform.scale(img,(transform_x,transfrom_y))
    screen.blit(img,(offset_x,offset_y))
    pygame.display.flip() # update the display
    time.sleep(replay_delay*4) # pause 	
	 


def countdown_overlay( camera ):
    n=4
    for i  in range(1,n):
	gc.collect()
	# Load the arbitrarily sized image
    	img = Image.open('/home/pi/Desktop/wait/'+ str(i)+ 'wait.jpg')
    	# Create an image padded to the required size with
    	# mode 'RGB'
    	pad = Image.new('RGB', (
        	((img.size[0] + 31) // 32) * 32,
        	((img.size[1] + 15) // 16) * 16,
        	))
    	# Paste the original image into the padded one
    	pad.paste(img, (0, 0))
	# Add the overlay with the padded image as the source,
    	# but the original image's dimensions
	o = camera.add_overlay(pad.tostring(), size=img.size)
    	# By default, the overlay is in layer 0, beneath the
	# preview (which defaults to layer 2). Here we make
    	# the new overlay semi-transparent, then move it above
	# the preview
	o.alpha = 100 #128
    	o.layer = 3
	sleep(1)
	camera.remove_overlay(o)
   	del img
   	del pad
	
def process_pics(now):
    # this section is an unbelievable nasty hack - for some reason Pygame
    # needs a keyboardinterrupt to initialise in some limited circs (second time running)
    class Alarm(Exception):
        pass
    def alarm_handler(signum, frame):
        raise Alarm
    signal(SIGALRM, alarm_handler)
    alarm(3)
    try:
        pygame.init()
        screen = pygame.display.set_mode((w,h),pygame.FULLSCREEN) 
        alarm(0)
    except Alarm:
        raise KeyboardInterrupt
    pygame.display.set_caption('Photo Booth Pics')
    pygame.mouse.set_visible(False) #hide the mouse cursor	
    filename = "/home/pi/Desktop/wait/wait4.jpg"
    img=pygame.image.load(filename) 
    img = pygame.transform.scale(img,(transform_x,transfrom_y))
    screen.blit(img,(offset_x,offset_y))
    pygame.display.flip() # update the display
    GPIO.output(led3_pin,True) #turn on the LED
    graphicsmagick = "montage "+ file_path + now + "-01.jpg " + file_path + now + "-02.jpg " + file_path + now + "-03.jpg " + file_path + now + "-04.jpg -geometry " + str(hoehe_klein) +"x" + str(breite_klein) + "+2+2 "+ file_path + now + "-montage.jpg "
    os.system(graphicsmagick)
    bilder_wech="cp "+ file_path + now + "-01.jpg " + file_path + now + "-02.jpg " + file_path + now + "-03.jpg " + file_path + now + "-04.jpg "+ file_path + "single/"
    os.system(bilder_wech)
    bilder_wech="rm -f "+ file_path + now + "-01.jpg " + file_path + now + "-02.jpg " + file_path + now + "-03.jpg " + file_path + now + "-04.jpg " 
    os.system(bilder_wech)
    pygame.quit()
     
			
# define the photo taking function for when the big button is pressed 
def start_photobooth(): 
	################################# Begin Step 1 ################################# 
	#print "Los gehts"
        start_again = False 
	GPIO.output(led2_pin,True);
	camera = picamera.PiCamera()

        #pixel_width = 1920  #mieth   
        #pixel_height = monitor_h * pixel_width // monitor_w #mieth
        #camera.resolution = (pixel_width, pixel_height) #mieth
        
        #camera.resolution = (1920, 1080)#bidausgabe und aufloesung aendern von bildern
	camera.framerate = 30 #Standard (24) Bildfrequenz
	camera.vflip = True
	camera.hflip = True # False mieth
	camera.rotation = 180 #180 Quer format und 90 Hochformat (rotation)
	#camera.saturation = -100 #Schwarz Weiss Fotos mieth
	camera.start_preview()
	GPIO.output(led2_pin,False);
	sleep(0.5)
	countdown_overlay(camera)
	i=4 #iterate the blink of the light in prep, also gives a little time for the camera to warm up
	while i < prep_delay :
	  GPIO.output(led1_pin,True); sleep(.5) 
	  GPIO.output(led1_pin,False); sleep(.5); i+=1
	
	################################# Begin Step 2 #################################
	#print "Mache Bilder" 
	now = time.strftime("%Y%m%d%H%M%S") #get the current date and time for the start of the filename
	try: #take the photos
		for i, filename in enumerate(camera.capture_continuous(file_path + now + '-' + '{counter:02d}.jpg')):
			GPIO.output(led2_pin,True) #turn on the LED
			print(filename)
			graphicsmagick = "composite -dissolve 75 -gravity southwest /home/pi/test.png " + filename + " " + filename + "&" # dissolve <prozent> 0 = voll transparent 100 = voll dargestellt
			os.system(graphicsmagick)
			sleep(0.5) #pause the LED on for just a bit
			GPIO.output(led2_pin,False) #turn off the LED
			
			
			if i == total_pics-1:
				break
			else:
				sleep(capture_delay) # pause in-between shots
				countdown_overlay(camera)
	finally:
		camera.stop_preview()
		camera.close()
	########################### Begin Step 3 #################################
	#print "Bearbeite Bilder fuer Montage..."
	
	process_pics(now) 
	GPIO.output(led3_pin,True) #turn on the LED
	GPIO.output(led3_pin,False) #turn off the LED
	########################### Begin Step 4 #################################
	#GPIO.output(led4_pin,True) #turn on the LED
	GPIO.output(led1_pin,True)
	try:
		display_pics(now)
	except Exception, e:
		tb = sys.exc_info()[2]
		traceback.print_exception(e.__class__, e, tb)
	pygame.quit()
	#print "Beendet"
	#GPIO.output(led4_pin,False) #turn off the LED
	#screen.fill((255,255,255))
        GPIO.output(led1_pin,False)
	random_pics(file_path)
        


def random_pics(file_path):
	GPIO.output(led2_pin,True)
	idle = True
	GPIO.add_event_detect(button1_pin, GPIO.FALLING)
	if GPIO.event_detected(button1_pin):
		#pygame.quit()
		print "IDLE set to false"
		idle = False
	class Alarm(Exception):
        	pass
	def alarm_handler(signum, frame):
        	raise Alarm
	signal(SIGALRM, alarm_handler)
	alarm(3)
	try:
        	pygame.init()
	        screen = pygame.display.set_mode((w,h),pygame.FULLSCREEN)
        	alarm(0)
	except Alarm:
        	raise KeyboardInterrupt
        	
	while not GPIO.event_detected(button1_pin) :
		piclist = list()
		x = 0
		for infile in glob.glob(os.path.join(file_path,'*.jpg')):
			piclist.append(infile)
		print random.choice(piclist)
		pygame.display.set_caption('Photo Booth Pics')
		pygame.mouse.set_visible(False) #hide the mouse cursor
		filename = random.choice(piclist)
		del piclist
		img=pygame.image.load(filename)
		img = pygame.transform.scale(img,(transform_x,transfrom_y))
		screen.blit(img,(offset_x,offset_y))
		pygame.display.flip() # update the display
		sleep(3)
		print "naechstes bild..."
		gc.collect()	

	pygame.quit()
	print "killed random image process"
	GPIO.remove_event_detect(button1_pin)
	start_again = True
	GPIO.output(led2_pin,False)
	
####################
### Main Program ###
####################

# when a falling edge is detected on button2_pin and button3_pin, regardless of whatever   
# else is happening in the program, their function will be run    
GPIO.add_event_detect(button2_pin, GPIO.FALLING, callback=shut_it_down, bouncetime=300) 

#choose one of the two following lines to be un-commented
GPIO.add_event_detect(button3_pin, GPIO.FALLING, callback=exit_photobooth, bouncetime=300) #use third button to exit python. Good while developing
#GPIO.add_event_detect(button3_pin, GPIO.FALLING, callback=clear_pics, bouncetime=300) #use the third button to clear pics stored on the SD card from previous events


print "Fotobox startet..." 
GPIO.output(led1_pin,True); #light up the lights to show the app is running
time.sleep(0.5)
GPIO.output(led2_pin,True);
time.sleep(0.5)
GPIO.output(led3_pin,True);
time.sleep(0.5)
GPIO.output(led4_pin,True);

#Falsche und defekte Bilder entfernen
systembefehl = "rm -f /home/pi/Desktop/*-0*.jpg &"
os.system(systembefehl)
gc.enable()
print "Fotobox ist gestartet"
print "OK"
while True:
	while start_again == False:
		GPIO.wait_for_edge(button1_pin, GPIO.FALLING)
		start_again = True
		GPIO.output(led1_pin,False); #turn off the lights
		GPIO.output(led2_pin,False);
		GPIO.output(led3_pin,False);
		GPIO.output(led4_pin,False);

	GPIO.output(led1_pin,True); #light up the lights to show the app is running
	
	time.sleep(0.3) #debounce
	
	start_photobooth()
Danke noch einmal.

Viele Grüße

Mieth
Zuletzt geändert von Anonymous am Montag 2. Januar 2017, 12:41, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@mieth: Leider hab ich heute keine Zeit mehr, aber morgen kann ich dir vielleicht helfen, den Code etwas aufzuräumen. Er scheint mir, nach kurzem überfliegen, ziemlich unübersichtlich. Vieles ist völlig unpythonisch. BlackJack hat ja schon darauf hingewiesen. So, wie der Code jetzt aussieht, ist er IMO wenig brauchbar. Dass er irgendwie zu funktionieren scheint, mag ja sein, bis zu dem Moment, wo er das - warum auch immer - nicht mehr tut und man in dem ganzen Ducheinander nicht herausfinden kann, woran es liegt, weil alles von allem abhängt und die Ablaufsteuerung über den gesamten Code verteilt ist (schau zB. mal, wo mit start_again operiert wird). Wie gesagt, morgen habe ich mehr Zeit.
In specifications, Murphy's Law supersedes Ohm's.
mieth
User
Beiträge: 4
Registriert: Samstag 27. Februar 2016, 23:56

@pillmuncher:

Super, vielen Dank für deine Hilfe!

Dir noch einen schönen Sonntag

Mieth
robbyatbln
User
Beiträge: 1
Registriert: Montag 2. Januar 2017, 11:14

Hallo ich habe das selbe Projekt mit dem selben Code hast du denn schon erfolge verzeichnen können??
gesundes neues und vielen dank
Gruß Robby
Antworten