Skript zur Ermmittlung eines Helligkeitswertes aus (Webcam)Image, auch als DS

Begonnen von rbothe, 02 Oktober 2015, 14:45:47

Vorheriges Thema - Nächstes Thema

rbothe

Hallo, ich habe ein Skript entwickelt, um von einem Image
(.gif, .jpg, .png, ...), z. B. geliefert von einer Webcam,
deren Gesamtdurchnittshelligkeitswert zu ermitteln
(in einer Skala von 0=dunkel bis 100=hell) und diesen
Wert weiterzuverarbeiten.

Beispiel: hell45 --> 70 # Resultat 70. Imagename ist fix
Mit diesen Helligkeitswerten kann auch z. B. ein Software-
Daemmerungssensor betrieben werden, der Wechsel von hell ./. dunkel
anzeigt.
Beispiel: hell-dunkel --> Es wird hell [datum uhrzeit]
(kann ggf. auch auf TV ausgeben, Sprachausgabe, ...).


Bei mir laeuft das Skript alle 2 Minuten auf Linux-Platform.


Ich hatte es nicht gedacht, aber der Software-Sensor liefert bei mir
mit einer Webcam fast minutenzeitgenau den Wechsel hell ./. dunkel
wie der Hardwaresensor FS20 SD.


Zusaetzlich wird an Software benoetigt:
convert (Programm aus Imagemagick-Framework) und Perl-Modul Image::BMP



Diese Skripts sind zwar keine fhem-Bestandteile, dienen aber der
Heimautomatisierung und koennen bei Bedarf leicht in fhem eingebunden
werden.

Ich hoffe, ich habe die richtige Forumskategorie erwischt,
denkbar waeren sonst auch "Codeschnipsel" oder "Off-Topic"
oder "Unterstuetzende Dienste".


Code fuer Skript hell45
#!/bin/sh
#: || exec /bin/sh $0 $argv:q
#(alias) >/dev/null 2>&1 && exec /bin/sh "$0" $1+{"$@"}
### @(#)
### @(#){hell45} - {ermittelt aktuellen Helligkeitswert 0..100 aus Bilddatei}
### @(#)
### @(#){Richard Bothe} Version {1.0} vom {11.11.2013}
### @(#)
### @(#){Anwendungsklasse}: Tools fuer FHEM [8]
### @(#)
### @(#){Synopsis} hell45
### @(#)
### @(#){Description}
### @(#)konvertiert Bilddatei (.gif, .jpg, .png, ...) zu .bmp-Datei und
### @(#)ermittelt aus den einzelnen bitmap-Informationen dieser Datei
### @(#)den gemittelten Helligkeitswert im Bereich 0 .. 100
### @(#)Dieser wird fortlaufend in ein logfile geschrieben
### @(#)
### @(#){Returncodes}: 0 bei keinem erkannten Fehler
### @(#)
### @(#){Description of I/O channels}: -
### @(#)
### @(#){Description of Parameters}: -
### @(#)
### @(#){Examples} hell45
### @(#)
### @(#){Called by} cron every 2 minutes or manually
### @(#)
### @(#){Calls} hellsumx.pl
### @(#)
### @(#){Files needed}
### @(#)imgsrc: Name der Bilddatei in ueblichem img format, gif, png, jpg ...
### @(#)        fixer Dateiname: "/tmp/webcam/webcam4-5.jpg"
### @(#)imgsrc_: Name einer temporaeren Bilddatei die aus imgsrc
### @(#)         erstellt wird mit Bildgroesse 200x200 (Rechenzeitoptimierung)
### @(#)         fixer Dateiname: "/tmp/webcam/webcam4-5_.jpg"
### @(#)imgdst: Name einer temporaeren Bilddatei die daraus erzeugt wird
### @(#)        und ins bmp-Format konvertiert wurde
### @(#)fixer Dateiname: "/tmp/webcam/img5.bmp3"
### @(#)log: logfile: "/tmp/hellsum-5.log" # Ausgabedatei (appended)
### @(#)
### @(#){Diagnostics}: -
### @(#)
### @(#){Bugs}: -
### @(#)
### @(#){History}: -
### @(#)
### @(#){See also}: fhem, imagemagick, hell-dunkel
### @(#)
### @(#){keywords}: Helligkeitssensor, Helligkeit, webcam
### @(#)
### @(#){caveats}: benoetigs imagemagick framework
### @(#)
### @(#)END_of_sccsheader
#: sanity checks
export PATH || (/bin/sh $0; /bin/kill $$)
PATH="/bin"
PATH="`cd /bin; pwd`:`cd /usr/bin; pwd`:/opt/local/bin:/usr/local/bin" #handle universe dependicies
IFS='
'
export IFS

TZ='MEST-1NDT'
export TZ


# needs imagemagick package (convert), see http://de.wikipedia.org/wiki/ImageMagick
# if you dont know how to build imagemagick on fritzbox, PI, ...
# dont ask me

imgsrc="/tmp/webcam/webcam4-5.jpg" # name of the file generated by the webcam
imgsrc_="/tmp/webcam/webcam4-5_.jpg" # temp file for resizing webcam file
imgdst="/tmp/webcam/img5.bmp3" # temp file of resized file in bmp format
log="/tmp/hellsum-5.log"

convert -geometry 200x200 "$imgsrc" "$imgsrc_" # resize to valuable size
convert "$imgsrc_" "$imgdst" # convert to bmp3 format

rel="`perl /usr/local/bin/hellsumx.pl \"$imgdst\" | sed 1q`" # Helligkeitswert
rc=$? # returncode

d="`date '+%a, %d. %m. %Y %T'`" # aktual date

echo "$d $rel" >>"$log" # add date and Wert to hist file (ascii format)

exit $rc # end with correct return code



code fuer Hilfsskript hellsumx.pl

### @(#){hellsumx.pl} - {ermittelt aktuellen Helligkeitswert 0..100 aus Bilddatei im .img-Format}
### @(#)
### @(#){Richard Bothe} Version {1.0} vom {11.11.2013}
### @(#)
### @(#){Anwendungsklasse}: Tools fuer FHEM [8]
### @(#)
### @(#){Synopsis} perl hellsumx.pl file.bmp3
### @(#)
### @(#){Description}
### @(#)ermittelt aus den einzelnen bitmap-Informationen einer BMP-Bilddatei
### @(#)den gemittelten Helligkeitswert im Bereich 0 .. 100
### @(#)Dieser wird auf stdout ausgegeben.
### @(#)
### @(#){Returncodes}: 0 bei keinem erkannten Fehler
### @(#)
### @(#){Description of I/O channels}: -
### @(#)
### @(#){Description of Parameters}: bmp-filename (bmp3-format)
### @(#)
### @(#){Examples} perl hellsumx.pl file.bmp3
### @(#)           --> 70
### @(#)
### @(#){Called by} hell45
### @(#)
### @(#){Calls} -
### @(#)
### @(#){Files needed}: -
### @(#)
### @(#){Packages needed}: Image::BMP
### @(#)
### @(#){Diagnostics}: -
### @(#)
### @(#){Bugs}: does not reclaim missing filenames
### @(#)
### @(#){History}: -
### @(#)
### @(#){See also}: fhem, hell45, hell-dunkel
### @(#)
### @(#){keywords}: Helligkeitssensor, Helligkeit, webcam
### @(#)
### @(#){caveats}: benoetigs perl package Image::BMP
### @(#)           auf einigen Linuxen muss explizit Format bmp3 benutzt werden, bmp reicht nicht, sonst Fehler in $img->open_file($img_name)
### @(#)
### @(#)END_of_sccsheader


use Image::BMP; # BMP Package needed

my $img = new Image::BMP; # new empty image
my $img_name=$ARGV[0]; # image file name

$img->open_file($img_name); # open image file

$h=$img->{Height};
$w=$img->{Width};

$summe=0;

# loop over all pixels
for ($i=0; $i<$w; $i++) {
   for ($j=0; $j<$h; $j++) {
      ($r,$g,$b) = $img->xy_rgb($i,$j); # red,green,blue values of pixel
      $summe+=($r+$g+$b); # sum of all pixel values
      }
   }

$summax=3*256*($h+1)*($w+1); # maximum value (all 100)
$rel=100.0 * $summe / $summax; # ratio of sumval of pixels and max value
$relint=int($rel+0.5); # round to integer
print "$relint\n";



Code fuer skript hell-dunkel

#!/bin/sh
#: || exec /bin/sh $0 $argv:q
#(alias) >/dev/null 2>&1 && exec /bin/sh "$0" $1+{"$@"}
### @(#)
### @(#){hell-dunkel} - {wertet Helligkeitswerte aus logfile aus und erzeugt Aktionen, wenn sich status hell / dunkel aendert}
### @(#)
### @(#){Richard Bothe} Version {1.0} vom {11.11.2013}
### @(#)
### @(#){Anwendungsklasse}: Tools fuer FHEM [8]
### @(#)
### @(#){Synopsis} hell-dunkel
### @(#)
### @(#){Description}
### @(#)Aus einem vorhanden laufend fortgeschriebenem logfile mit
### @(#)Helligkeitswerten (0 .. 100) werden die letzten (5) Werte genommen
### @(#)und eine Aktion ausgeloest, wenn sich der Status hell/dunkel
### @(#)geaendert hat im Vergleich mit den letzten 4 Werten und
###@(#)den Limit ueber/unterschreitet.
### @(#)Die letzten 4 werden genommen, damit kurzfristige Schwankungen
### @(#)nicht ausloesen.
### @(#)
### @(#){Returncodes}: 0 bei keinem erkannten Fehler
### @(#)
### @(#){Description of I/O channels}: stdout: Aenderungstext bei Wechsel von hell ./. dunkel
### @(#)
### @(#){Description of Parameters}: -
### @(#)
### @(#){Called by} cron every 2 minutes or manually
### @(#)
### @(#){Calls} hell-dunkel.awk
### @(#)
### @(#){Examples} hell-dunkel
### @(#)
### @(#){Files needed}
### @(#)logfile: fortgeschriebenes logfile der Helligkeitswerte
### @(#)         fixer Dateiname: "/tmp/hellsum-5.log"
### @(#)         Format: Datum Helligkeitswert (0..100)
### @(#)outfile: fortgeschriebenes file mit Ergebnis der Berechnung,
### @(#)         eigentlich nur fuer debugging
### @(#)         fixer Dateiname: "/tmp/hell.dat"
### @(#)
### @(#){Diagnostics}:
### @(#)Es wird draussen hell Datum # bei Wechsel
### @(#)Es wird draussen dunkel Datum # bei Wechsel
### @(#)
### @(#){Bugs}: -
### @(#)
### @(#){History}: -
### @(#)
### @(#){See also}: fhem, hell45
### @(#)
### @(#){keywords}: Helligkeitssensor, Helligkeit, webcam
### @(#)
### @(#){caveats}: -
### @(#)
### @(#)END_of_sccsheader
#: sanity checks
PATH="$PATH:/usr/local/bin"
export PATH

logfile="/tmp/hellsum-5.log" # hist file written by hell45 each 2 minutes
outfile="/tmp/hell.dat" # fortgeschriebens Ergebnis fuer Debugging
script="/usr/local/bin/hell-dunkel.awk" # helper script
helllimit="45" # limit (0..100) for state "hell"
dunkellimit="35" # limit (0..100) for state "dunkel"
# beide Werte sind Beispielswerte, zu ermitteln je nach
# Tageszeit mit hell45
tailval=5 # respect last $tailval lines

res="`
cat \"$logfile\" | grep -v '^#' |
tail -$tailval | awk -f \"$script\" helllimit=\"$helllimit\" \
dunkellimit=\"$dunkellimit\" -`"

if [ "X$res" != "X" ]; then
   echo "$res" # Ausgabe
   echo "$res" >>"$outfile"
   #sag-was "$res" >/dev/null 2>&1 # Beispiel fuer Sprachausgabe
   #dreambox-mess "$res" # Beispiel fuer Ausgabe auf TV via dreambox
   fi

exit



Code fuer Hilfsskript hell-dunkel.awk

#!/bin/sh
### @(#)
### @(#){hell-dunkel.awk} - {ermittelt Helligkeitswertswechselvon hel/dunkel}
### @(#)Hilfskript fuer hell-dunkel
### @(#)
### @(#){Richard Bothe} Version {1.0} vom {11.11.2013}
### @(#)
### @(#){Anwendungsklasse}: Tools fuer FHEM [8]
### @(#)
### @(#){Synopsis} awk -f hell-dunkel.awk helllimit="$helllimit" dunkellimit="$dunkellimit" -
### @(#)
### @(#){Description}
### @(#)erkennt einen Wechsel von hell ./. dunkel
### @(#)Die 5 Werte (einer / Zeile) werden inspiziert.
### @(#)Es wird ein Text ausgegeben, wenn sich Status aendert wie folgt:
### @(#)der letzte Wert ist von den 4 Werten davor verschieden
### @(#)
### @(#){Returncodes}: 0 bei keinem erkannten Fehler
### @(#)
### @(#){Description of I/O channels}:
### @(#)stdin: logfileinput
### @(#)stdout: msg bei Aenderung hell / dunkel
### @(#)
### @(#){Description of Parameters}: -
### @(#)
### @(#){Examples} hell-dunkel.awk
### @(#)
### @(#){Files needed}: -
### @(#)
### @(#){Diagnostics}:
### @(#)Es wird draussen hell: tag monat jahr zeit
### @(#)Es wird draussen dunkel: tag monat jahr zeit
### @(#)
### @(#){Bugs}: -
### @(#)
### @(#){History}: -
### @(#)
### @(#){See also}: fhem, hell-dunkel, hell45
### @(#)
### @(#){keywords}: Helligkeitssensor, Helligkeit, webcam
### @(#)
### @(#){caveats}: -
### @(#)
### @(#)END_of_sccsheader
#: sanity checks

BEGIN {
   val_change=""
   }

NF>=6 {
   str=$0
   tag=$2
   monat=$3
   jahr=$4
   zeit=$5
   val=$6

   status="x" # undetermined oder Zwischenwert
   if (val>helllimit) {
      status="h" # hell
      }
   if (val<dunkellimit) {
      status="d" # dunkel
      }

   if (NR==1) { # 1. Zeile
      status1=status
      }
   if (NR==2) { # 2. Zeile
      status2=status
      }
   if (NR==3) { # 3. Zeile
      status3=status
      }
   if (NR==4) { # 4. Zeile
      status4=status
      }
   if (NR==5) { # 5. Zeile
      status5=status
      }

   }

END {
   if ((status1=="d" || status1=="x") \
   && (status2=="d" || status2=="x" ) \
   && (status3=="d" || status3=="x" ) \
   && (status4=="d" || status4=="x" ) \
   && (status5=="h" )) {
      val_change="h" # es wird hell
      print "Es wird draussen hell: " tag monat jahr " " zeit
      }

   if ((status1=="h" || status1=="x") \
   && (status2=="h" || status2=="x" ) \
   && (status3=="h" || status3=="x" ) \
   && (status4=="h" || status4=="x" ) \
   && (status5=="d" )) {
      val_change="d" # es wird dunkel
      print "Es wird draussen dunkel: " tag monat jahr " " zeit
      }

   }



Alle Skripte sollen unter /usr/local/bin platziert werden oder die Pfade darin angepasst werden.

Nicht vergessen, skripts hell45 und hell-dunkel ausfuehrbar zu machen (chmod 755 hell45 hell-dunkel)
und darin die Pfade in hell45 der images anzupassen (/tmp/webcam/...).
FHEM 5.6 auf 2 Linux-Servern als Highavailability Heartbeat- Cluster
1xCUNO
2x HMLAN via 1x VCCU redundant angebunden
Ansonst: wie erstelle ich eine Signatur? Gibt es eine Inventory Funktion im FHEM?