Aus Raspberry Pi Geek 10/2020

DIY-Fotografie mit dem Raspberry Pi (Seite 3)

Für das Aufnehmen einer kontinuierlichen Serie müssen Sie die Bedingungen während der Aufnahmeeinstellungen bedenken beziehungsweise die Einstellungen neu vornehmen. In zwei geschachtelten Schleifen nimmt das Programm dann für i Serien jeweils j Fotos auf, speichert die Bilder ab und zeigt sie verkleinert an. Nach jedem Bild erwartet das Skript noch eine Tasteneingabe, diese lässt sich aber auch durch eine kurze Zeitverzögerung ersetzen. Am Ende der Aufnahme erfolgt eine Datensicherung in ein Verzeichnis mit zufällig generiertem Namen. Das macht das Standarddatenverzeichnis für die nächste Bildserie frei.

Listing 4

# Take a series of photos - shootStills.py
import picamera
import time
import cv2
import random
import sys
import os
import glob
#
BASEDIR = 'photo/'
# Camera settings default
camSet={'series':'1', 'images':'7', 'delay':'10', 'resW':'2592', \
        'resH':'1944','iso':'200',  'metering':   'backlit',\
        'evValue':'0','refine':'no','serverIP':'93',\
        'shutter':'33333','bright':'50','sat':'0'}
cam = picamera.PiCamera()
def readCamSet (fileRef):
    try :
       fin = open(fileRef,'r')
       for line in fin:
          x=line.split(':')
          camSet[x[0]]=x[1]
       fin.close()
       #
       cam.resolution = (int(camSet['resW']),int(camSet['resH']))
       cam.iso        = (int(camSet['iso']))
       cam.meter_mode  = (str(camSet['metering']))
       cam.exposure_compensation = (int(camSet['evValue']))
       cam.brightness = (int(camSet['bright']))
       cam.saturation = (int(camSet['sat']))
       cam.awb_mode   = 'auto' # off gibt ein schwarzes Bild#
       if camSet['shutter'] == '0':
          time.sleep(1)     # warten auf die autom. Gain Kontrolle
          cam.shutter_speed = cam.exposure_speed
       else :
          cam.shutter_speed = int(camSet['shutter'])
        #
       series    = (int(camSet['series']))
       nrPhoto   = (int(camSet['images']))
       delay     = (int(camSet['delay']))
       refineBAK = (str(camSet['refine']))
    except:
       print ('Reading camSettings failed taking defaults')
    return series, nrPhoto, delay
def shoot(series,nrPhoto,delay):
    #cam.vflip         = True
    #cam.hflip         = True
    cam.led            = False      # Rotlicht an/aus
    for i in range (0,series):
      for j in range (0, nrPhoto):
        camFile = BASEDIR +'img_%1d_%02d.jpg' %(i, j)
        cam.capture(camFile,format='jpeg',quality = 99)
        print (camFile +' captured')
        image = cv2.imread(camFile)
        cv2.imshow(camFile +' key next_or_quit_with_q', cv2.resize(image,(640,480)))
        key = cv2.waitKey(0) & 0xFF
        cv2.destroyWindow(camFile +' key next_or_quit_with_q')
            # time.sleep (delay) # in automatic mode
        # if the `q` key was pressed break
        if key == ord("q"):
          break
    cam.close()
def goBackup():
    seq = '0123456789abcdefghklmopqrstuvwz'
    saveDir =''
    anzFiles=0
    for i in range (0,4):
        codeDir = random.choice(seq)
        saveDir = saveDir + codeDir
        codeDir = saveDir +'/'
    saveDir = BASEDIR + saveDir + '/'
    if (os.path.isdir (saveDir)== True):
        text = saveDir + 'exists, try again'
        print (text)
        return False,saveDir,anzFiles
    else:
        os.makedirs(saveDir)
    images = glob.glob(BASEDIR +'*.jpg')
    for filename in images:
        print (filename +' moved to ' +saveDir)
        comStr = 'mv ' + filename + ' ' +saveDir
        os.system(comStr)
        anzFiles = anzFiles + 1
    return True, saveDir,anzFiles
def main():
    series, nrPhoto,delay = readCamSet('camSettings.txt')
    shoot(series,nrPhoto,delay)
    store,savedir,n = goBackup()
    while not store:
        store,savedir,n = goBackup()
    print("Backup " + str(n) + ' files to ' + savedir)
    print("Don't forget image refinement on host!!!")
    print('bye')
main()

Backbord lauscht auf Steuerbord

Sofern der Leser einen Aufbau mit nur einer Kamera beabsichtigt, folgt unmittelbar die Nachbearbeitung, wie weiter unten erläutert. Mit den bisherigen Ausführungen ist jetzt aber der Punkt erreicht, an dem es den Übergang auf das Konzept zum Multikamerasystem zu vollziehen gilt. Damit die Erläuterungen nicht zu komplex werden, beschränkt sich der Blick auf ein Kameratandem.

Damit man links und rechts nicht verwechselt, wird die erste Kamera mit Backbord (Backbord 93, rot hinterlegt) bezeichnet, die zweite mit Steuerbord (Steuerbord 94, grün). Abbildung 5 zeigt beide Bedienoberflächen. Aus dem Backbord-Menü heraus bringt die gelbe Schaltfläche TARGET das Livebild zurück. Mit einem Klick auf die rote Schaltfläche DAEMON startet man den Kamera-Daemon. Danach verlässt man die Anwendung und wendet sich der ähnlich gestalteten Oberfläche des Partners (Steuerbord) zu.

Abbildung 5: Die GUI zum Einstellen der Parameter für ein Kameratandem.

Abbildung 5: Die GUI zum Einstellen der Parameter für ein Kameratandem.

Die für Backbord eingestellten Daten holt man mittels Dateitransfer über das SSH-Protokoll dort ab (Button DAEMON) und prüft sie anhand eines mit SHOOT erstellten Testbilds. In der weiteren Anwendung müssen die Bilder annähernd parallel ausgerichtet sein. Eine Overlay-Funktion (Button OVRLAY) überblendet das letzte Bilder von Backbord mit dem aktuellen von Steuerbord.

Danach geben Sie die Aufnahmeserie frei. Dazu rufen Sie den Kamera-Client über den mit TAKEIT beschrifteten roten Button auf. Im neuen Fenster starten und sichern Sie die Serien von Steuerbord aus. Eine Miniaturanzeige der Bilder ist möglich, bei kurzen Intervallen zwischen den Bildern aber nicht sinnvoll.

Hinsichtlich der Synchronisation dürfen wir von einem Rolling-Shutter-System nicht zu viel erwarten. Abbildung 6 zeigt mit der Light-Version des Kamera-Rigs aufgenommene Graugänse und macht Hoffnung auf ein erfolgreiches Unterfangen. Ein Video illustriert den Aufnahmevorgang [8].

Abbildung 6: Graugänse, mit zwei Kameras synchron erwischt, im universellen 3D-Format L-R-L.

Abbildung 6: Graugänse, mit zwei Kameras synchron erwischt, im universellen 3D-Format L-R-L.

Die hier vorgestellte Lösung basiert auf einem Vorschlag von der Webseite Stackexchange [9]. Ein Benutzer bemängelte dort die langsame Aufnahmefolge von raspistill (siehe oben). Eine Lösung des Problems besteht in einem dauerhaft laufenden Kamera-Daemon und einem auf einem zweiten Terminal oder zweiten Rechner laufenden Kamera-Client. Die Kamera läuft dabei in einem eigenen Prozess, schließt nach der Bildaufnahme und öffnet sofort wieder für das nächste Bild.

Wir wissen also jetzt, dass im Kameranetzwerk ein Client und mehrere Daemons arbeiten. Statt des bisher verwendeten Skripts shootStills.py starten wir nun auf Backbord den Daemon camDaemon.py und aktivieren auf Steuerbord den Client camClient.py. Der Daemon reagiert auf die eingehenden Kommandos snap (Bildaufnahme) und backup (Datensicherung) sowie exit (stoppe den Service).

Im Vorspann der Programme sind noch das Ermitteln der IP-Adressen und die Befehle zur Kamerasteuerung (wie oben beschrieben) eingebunden. Der Quellcode ist nicht unbedingt einfach zu interpretieren; die Referenzen zu den Verzeichnissen muss der Benutzer gegebenenfalls anpassen. Der Client ist dagegen etwas einfacher strukturiert: Socket definieren, IP-Adresse bestimmen, Kameraparameter definieren und Capture-Befehle absetzen.

Nach dem Abarbeiten einer Bildserie erfolgt die Datensicherung auf beiden Rechnern, ebenfalls über den Client gesteuert. Mit dem Verfahren lassen sich Synchronisationen von unter 50 ms erzielen. Das ist nicht gerade “high speed”, trotzdem aber recht ordentlich und hinreichend für etliche Anwendungsfelder. Die erweiterte URL der Quelle ist im Sourcecode angegeben, den Sie im Download zu diesem Artikel finden.

Raumbilder – Fotos in 3D

Unter Stereovision versteht man den biologischen Prozess des zweiäugigen Sehens, den man analog mit einem Computer nachvollziehen kann. Die OpenCV-Bibliothek bedient dieses Gebiet unter anderem mit Algorithmen zur Merkmalserkennung, Kamerakalibrierung und Bildorientierung. Diese Themen liegen aber weit außerhalb des Spektrum dieses Beitrags. Wir befassen uns lediglich mit der synchronen Aufnahme parallel ausgerichteter Bilder. Die Ausrichtung der Stereobildpaare überlassen wir einer Freeware, die mit wenigen Mausklicks zum Ziel führt, dem universellen Stereoformat (vergleiche Abbildung 6).

Die dritte Dimension

Stereogramme oder auch Raumbilder kennt man schon seit Mitte des 19. Jahrhunderts. Aktuell findet man sie heute im Dynamic-Depth-Format als 3D-Darstellungen, die auf die Bewegung von Maus oder Handy reagieren. Man bedient sich dazu einer Tiefenmatrix und eines 2D-Bilds. Hochaufgelöste und wirklich interessante Raumbilder erhält man durch Synchronaufnahmen mit zwei näherungsweise parallel ausgerichteten Kameras. Den Abstand dieser Kameras bezeichnet man als Basis. Als Faustregel für die Basis gilt 1/30 der Entfernung von der Kamera zum nächsten Punkt des Objekts, dem sogenannten Nahpunkt.

Mit zwei RasPi-Kameras und den vorgestellten Software-Modulen können Sie derartige Aufnahmen anfertigen. Die Anordnung der Kameras auf einer Blitzschiene vereinfacht das Verfahren. Ohne Aufwand gelingt es aber kaum, die Bilder mechanisch präzise auszurichten. Daher lesen Sie das Bildpaar in die Windows-Freeware StereoPhoto Maker oder kurz SPM ein [10]. Die Software gibt es samt umfangreicher Anleitungen in deutscher und englischer Lokalisierung. Über das Dateimenü des Programms laden Sie das linke und das rechte Bild und führen Sie im Menü Adjust die Funktion Auto alignment aus. Auf Mausklick werden die beiden Bilder zueinander orientiert.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 10 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
RASPBERRY PI GEEK KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Raspberry Pi Geek bei Google Play Readly Logo
Nach oben