PiCamera HD

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
beatbaer
User
Beiträge: 2
Registriert: Dienstag 29. Juni 2021, 13:49

Hallo

Vorweg: Bin Anfänger was Python angeht und fuchse mich da grad bis rein. Komm eher aus der Automatisierungsecke und schieb eigentlich einzelne bits durch die Gegend

Projektbeschreibung:
Raspi mit der Raspicam HD über nem Prüfplatz
Während der Ruhephase soll das aktuelle Bild der Kamera Live auf nem Bildschirm angezeigt werden
Bei Tastendruck eines Tasters der per GPIO angeschlossen ist soll ein Bild in voller größe aufgenommen werden
Dannach soll ein Zeitstempel oben links ins Bild mit rein
Per Pygame lass ich das fertige Bild mal für 10 sekunden anzeigen und dannach wieder ab in den Vorschaubetrieb

Hier mein aktuelles Problem:
Aus unerklärlichen Gründen schmeißt es mir nach unterschiedlicher zeit das Script raus und ich muss den Raspi neu starten. Neustart des scriptes per cronjob und überprüfung ob Prozess noch da ist geht irgendwie auch nicht richtig.

Code: Alles auswählen

import os
import time
import RPi.GPIO as GPIO
import socket
import sys
import argparse
import pygame
from picamera import PiCamera
from datetime import datetime
from PIL import Image, ImageFont, ImageDraw

GPIO.setmode(GPIO.BOARD)

GPIO.setup(7, GPIO.IN)
camera = PiCamera()
camera.resolution = (4056, 3040)
camera.start_preview()
camera.rotation = 180
camera.preview_fullscreen = False
camera.preview.window = (320, 300, 1280, 768)

while 1:
    try:
        time.sleep(0.2)
        if GPIO.input(7) == GPIO.HIGH:
           datetime_string = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
           datetime_string_pic = datetime.now().strftime("%Y-%m-%d_%H:%M")
           filename = "/home/pi/server/%s_mpad.jpg" % datetime_string
           camera.capture('temp.jpg')
           my_image = Image.open("temp.jpg")
           font = ImageFont.truetype("FreeSerifBold.ttf", 80)
           image_editable = ImageDraw.Draw(my_image)
           image_editable.text((15,15), datetime_string_pic, (255, 0, 0), font)
           my_image.save(filename)
           camera.stop_preview()
           pygame.display.init()
           imgSurf = pygame.image.load (filename)
           imgSurf = pygame.transform.scale( imgSurf, (1441, 1080))
           screen = pygame.display.set_mode ( imgSurf.get_size(), pygame.FULLSCREEN )
           screen.blit ( imgSurf, ( 0, 0 ) )
           pygame.display.flip()
           time.sleep(10)
           pygame.quit()
           camera.start_preview()
           camera.rotation = 180
           camera.preview_fullscreen = False
           camera.preview.window = (320, 300, 1280, 768)
           time.sleep(5)
    except:
        print "Irgendein Fehler:", sys.exc_info()[0]
        raise
        
Try und Except habe ich jetzt erst zum testen dazu, aber bin da wirklich erst mal etwas überfragt

Wäre auf jeden Fall für jeden Schubser in die richtige Richtung Dankbar
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Da ist vieles im Argen aber was mir sofort ins Auge sticht ist pygame init und quit in einer Schleife.
.Init wird einmal bei Programmstart aufgerufen und .quit als letzte Zeile im Code, bevor das Programm beendet wird.
Meine Vermutung für Grund des "Script rausschmeißens" ist Out-of-memory.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Benutzeravatar
Dennis89
User
Beiträge: 1153
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

du importierst 'os', 'socket' und 'argparse' nutzt sie aber gar nicht. Anstelle von 'GPIO', dass du übrigends mit 'as' von 'GPIO' in 'GPIO' "umbenennst", solltest du dir mal das aktuelle 'gpiozero' anschauen.
Auf Modulebene sollte nur Code stehen, der Konstanten, Funktionen oder Klassen beschreibt. Das Hauptprogramm wird dann in einer Funktion mit dem Namen 'main' gesteuert.
Anstatt 'while 1' ist es in Python üblich 'while True' als Dauerschleife zu benutzen.
Wieso erstellst du zwei Namen mit dem eigentlichen gleichen Inhalt? Der Unterschied zwischen 'datetime_string' und 'datetime_string_pic' ist eigentlich nur einen nicht passenden Platzhalter in 'datetime_string_pic'.
Für Pfade kann man das 'Path' aus 'pathlib' nutzen.
Ich habe jetzt gar keine Erfahrung mit 'pygame' und habe daher deinen Code genommen und mal etwas umstrukturiert. Habe leider keine Möglichkeit das zu testen, von dem her sehe folgenden Code eher als Beispiel für den Programmaufbau.

Code: Alles auswählen

#!/usr/bin/env python3

import time
from gpiozero import Button
import pygame
from picamera import PiCamera
from datetime import datetime
from PIL import Image, ImageFont, ImageDraw
from pathlib import Path


BUTTON_PIN = 4
PICTURE_PATH = '/home/pi/picture'


def show_preview(camera):
    camera.start_preview()
    camera.rotation = 180
    camera.preview_fullscreen = False
    camera.preview.window = (320, 300, 1280, 768)

def close_preview(camera):
    camera.capture('temp.jpg')
    camera.stop_preview()
    show_picture()
    show_preview(camera)

def show_picture():
    timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
    my_image = Image.open("temp.jpg")
    font = ImageFont.truetype("FreeSerifBold.ttf", 80)
    image_editable = ImageDraw.Draw(my_image)
    image_editable.text((15, 15), timestamp, (255, 0, 0), font)
    filename = Path(PICTURE_PATH, timestamp, '.jpeg')
    my_image.save(filename)
    pygame.display.init()
    imgSurf = pygame.image.load(filename)
    imgSurf = pygame.transform.scale(imgSurf, (1441, 1080))
    screen = pygame.display.set_mode(imgSurf.get_size(), pygame.FULLSCREEN)
    screen.blit(imgSurf, (0, 0))
    pygame.display.flip()
    time.sleep(10)
    pygame.quit()

def main():
    button = Button(BUTTON_PIN)
    camera = PiCamera()
    camera.resolution = (4056, 3040)
    show_preview(camera)
    button.when_pressed = close_preview(camera)



if __name__ == '__main__':
    main()
Vielleicht kann daraus noch jemand mit Erfahrung den fertigen Code bauen.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
Dennis89
User
Beiträge: 1153
Registriert: Freitag 11. Dezember 2020, 15:13

Nachtrag:
Meine Zeile

Code: Alles auswählen

button.when_pressed = close_preview(camera)
funktioniert so nicht. Dadurch wird der Callback auf 'None' gesetzt. Steht auch so in der Doku, das hatte ich falsch im Kopf.
Mit

Code: Alles auswählen

button.when_pressed = partial(close_preview, camera)
geht es aber.

Danke @hyle für den Hinweis.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
beatbaer
User
Beiträge: 2
Registriert: Dienstag 29. Juni 2021, 13:49

Hi

Danke euch.. dachte an nen Schubser - aber gleich so :D
Schaut natürlich viel aufgeräumter aus, bin halt schrittkettenmäßig ran und hab alles untereinander

Werd mich wohl bisl mehr mit der Materie beschäftigen müssen

Danke auf jeden Fall ;) Gleich mal probieren

Zur Erklärung wegen dem Datestring und dem Pic:
Im Bild soll der Text ohne Sekunden aber mit nem Doppelpunkt als Trennzeichen bei der Zeit sein
Im Dateinamen dann mit sekunden (wenn mehrere Bilder in einer Minute erstellt werden) und Binderstrich statt Doppelpunkt
Antworten