Wasserzeichen in Image einfügen

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
Helios86
User
Beiträge: 4
Registriert: Freitag 16. März 2018, 11:42

Mahlzeit

Nachdem meine Fotobox inzwischen ganz passabel funktioniert, bin ich auf der Suche nach einer Möglichkeit ein kleines Wasserzeichen am unteren Bildrand einzufügen. Der Plan war einen Subprozess laufen zu lassen, der im Hintergrund per Graphicsmagick ein eine .png Patei(400x70px) mit trasparentem Hintergrund über das bild legt bevor es auf den internen Webserver geladen wird, ich hab heute Nacht so zimlich alles getestet was ich dazu im Netz gefunden habe, aber entweder wird das Skript wegen eins Syntax Fehlers nicht ausgeführt oder das Wasserzeichen nicht auf dem bild.
Ich bin kurz davor die Sache bleiben zu lassen, aber eventuell hat ja von euch jemand die zündende Idee.

Der letzte Versuch ist noch drin, ich habe ihn mal rot markiert.

LG. Helios

Code: Alles auswählen

#!/usr/bin/env python
import os
import glob
import RPi.GPIO as GPIO
from time import sleep
import atexit
import picamera
import time
import subprocess
import os
import configparser
from PIL import Image
import pygame
from pygame.locals import QUIT, KEYDOWN, K_ESCAPE, MOUSEBUTTONDOWN



offset_x = 0 # how far off to left corner to display photos
offset_y = 0 # how far off to left corner to display photos
file_path ="/home/pi/photobooth/" #path of the photobooth programm
server_path="/var/www/html/" #path to the Webserverfiles
debug = False #set to True for debugging

#Variables to change as needed
licht_pin = 11
led_pin = 7    # LED pin
btn_pin = 18   # pin for the button
ausloser = 16
debounce = 1,0 # how long to debounce the button. Add more time if the button triggers too many times.
camera = picamera.PiCamera()
camera.vflip =True
camera.resolution =(2560,1440)


#GPIO setup
GPIO.setmode(GPIO.BOARD)
GPIO.setup(led_pin,GPIO.OUT) # LED 
GPIO.setup(btn_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) # button
GPIO.setup(ausloser, GPIO.IN, pull_up_down=GPIO.PUD_UP) # button
GPIO.setup(licht_pin,GPIO.OUT) # LICHT 

# initialize pygame
pygame.init()
if debug is True:
   monitor_w = 1024
   monitor_h = 600
   pygame.display.set_mode((monitor_w, monitor_h))
   screen = pygame.display.get_surface()
   pygame.display.set_caption('Photo Booth Pics')
   
else:
   monitor_w, monitor_h = pygame.display.Info().current_w, pygame.display.Info().current_h
   pygame.mouse.set_visible(False) #hide the mouse cursor 
   pygame.display.set_mode((monitor_w, monitor_h))
   screen = pygame.display.get_surface()
   pygame.display.set_caption('Photo Booth Pics')
   pygame.display.toggle_fullscreen()

def show_image(image_path):

	# clear the screen white
	screen.fill( (255,255,255))

	# load the image
	img = pygame.image.load(image_path)
	img = img.convert() 

	# rescale the image to fit the current display
	img = pygame.transform.scale(img, (monitor_w,monitor_h))
	screen.blit(img,(offset_x,offset_y))
	pygame.display.flip()

def starting():
    
    shoot()
    show_image(str(file_path)+'media/processing.jpg')    
    camera.stop_preview()
    if debug is True:
       print('Montage')
    subprocess.call("montage -geometry 960x540+ -tile 2x2 -background '#336699' -geometry +50+50 "+str(file_path)+"/image1.jpg "+str(file_path)+"image2.jpg "+str(file_path)+"image3.jpg "+str(file_path)+"montage_temp.jpg", shell=True)
    subprocess.call("composite -gravity center "+str(file_path)+"media/overlay.png  "+str(file_path)+"montage_temp.jpg  "+str(file_path)+"montage.jpg", shell = True)
    # LED a
    zeit=time.strftime('%d-%I.%M.%S') 
    GPIO.output(7, GPIO.LOW)
    img = Image.open(str(file_path)+'montage.jpg')
    pad = Image.new('RGB', (
      ((img.size[0] + 31) // 32) * 32,
      ((img.size[1] + 15) // 16) * 16,
      ))
    pad.paste(img, (0, 0))
    o = camera.add_overlay(pad.tostring(), size=img.size)
    o.alpha = 255 #128
    o.layer = 3
    sleep(10)
    show_image(str(file_path)+'media/intro.jpg')      
    camera.remove_overlay(o)
    del img
    del pad
  
    
    return;
def delete():
    subprocess.call('sudo rm -r '+str(server_path)+'images/*', shell=True)
    subprocess.call('sudo rm -r '+str(server_path)+'thumbs/*', shell=True)
    return;

def shoot():
  y=3
  for x  in range(1,y+1):
    if debug is True:
        print('Foto '+ str(x))
    if x >1:
        show_image(str(file_path)+'media/nextone.jpg')
    else:
        show_image(str(file_path)+'media/getready.jpg')
    sleep(4)
    camera.iso = 400
    camera.rotation = 180
    camera.start_preview()
    countdown_overlay('test')
    show_image(str(file_path)+'media/smile.jpg')
    camera.stop_preview()
    sleep(1) 
    GPIO.output(11, GPIO.HIGH)
    camera.capture(str(file_path)+'image'+str(x)+'.jpg')
    img = Image.open(str(file_path)+'image'+str(x)+'.jpg')
    pad = Image.new('RGB', ([color=#804040][/color]
      ((img.size[0] + 31) // 32) * 32,
      ((img.size[1] + 15) // 16) * 16,
      ))
    pad.paste(img, (0, 0))
    o = camera.add_overlay(pad.tostring(), size=img.size)
    o.alpha = 255 #128
    o.layer = 3
    GPIO.output(11, GPIO.LOW)
    [color=#FF0000] graphicsmagick = "composite -gravity southwest /home/pi/media/watermark.png "+'image'+str(x)+'.jpg'
    os.(graphicsmagick) [/color]
    #show_image(str(file_path)+'image'+str(x)+'.jpg')
    zeit=time.strftime('%d-%I.%M.%S') 
    subprocess.call('sudo cp '+str(file_path)+'image'+str(x)+'.jpg '+str(server_path)+'images/image'+zeit+'.jpg', shell=True)
    subprocess.call('sudo convert '+str(file_path)+'image'+str(x)+'.jpg -resize 320x240 '+str(server_path)+'thumbs/image'+zeit+'.jpg',shell=True)
    sleep(3)
    camera.remove_overlay(o)
    del img
    del pad
  return;


def countdown_overlay(ggg):
  countdown=4
  
  for i  in range(countdown,0,-1):
   
    img = Image.open(str(file_path)+'media/'+str(i)+'.jpg')
    pad = Image.new('RGB', (
      ((img.size[0] + 31) // 32) * 32,
      ((img.size[1] + 15) // 16) * 16,
      ))
    pad.paste(img, (0, 0))
    o = camera.add_overlay(pad.tostring(), size=img.size)
    o.alpha = 90 #128
    o.layer = 3
    sleep(1)
    camera.remove_overlay(o)
  del img
  del pad
  return;



def cleanup():
  print('Goodbye.')
  GPIO.cleanup()
atexit.register(cleanup) 

run_state = False
def check_light():
	if run_state:
		GPIO.output(led_pin,True)
		print("LED on")
		camera.start_preview()
	else:
		GPIO.output(led_pin,False)
		print("LED off")
		camera.stop_preview()

show_image(str(file_path)+'media/intro.jpg')  
# Dauersschleife
while 1:
  
  for event in pygame.event.get():
  # Spiel beenden, wenn wir ein QUIT-Event finden.
      if event.type == pygame.QUIT:
          running = False
          pygame.quit()
 
            # Wir interessieren uns auch für "Taste gedrückt"-Events.
      if event.type == pygame.KEYDOWN:
                # Wenn Escape gedrückt wird, posten wir ein QUIT-Event in Pygames Event-Warteschlange.
          if event.key == pygame.K_ESCAPE:
              pygame.event.post(pygame.event.Event(pygame.QUIT))
              pygame.quit()
          elif event.key == pygame.K_SPACE:
              starting()
          elif event.key == pygame.K_d:
              delete()
      if event.type == pygame.MOUSEBUTTONDOWN:
              starting()  
       
        
   # LED off
  GPIO.output(7, GPIO.LOW)

  # read GPIO
  if GPIO.input(18) == GPIO.LOW:
    pygame.quit()
    # Warte 100 ms
    time.sleep(0.1)
    
    
  if GPIO.input(16) == GPIO.LOW:
    # goto starting
    GPIO.output(7, GPIO.HIGH)
    starting()

   
    


try:	
	while True:
		GPIO.wait_for_edge(btn_pin, GPIO.FALLING)
		sleep(debounce)
		if run_state:
			run_state = False
		else:
			run_state = True
		print("Button pressed")
		check_light()
except KeyboardInterrupt:
	print('\nScript Exited.')
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@Helios86: ist gibt genug Beispiele, wie man mit PIL Wasserzeichen hinzufügt: https://gist.github.com/snay2/876425

Das mischen von Funktionsdefinitionen und ausgeführtem Code ist schrecklich. Alles auf Moduleebene außer Konstanten und Definitionen sollte in eine Funktion wandern. Pfade setzt man mit os.path.join zusammen, und subprocess nutzt man ohne `shell=True`. Die Kommandos sind für mich auch nicht lesbar. Und wie gesagt, PIL bringt die Funktionalität schon mit.

Die `del` und einzenen `return` sind alle unsinnig und können weg.
`sudo rm -r` würde ich in keinen Programm aufrufen. Sorge dafür, dass der normale Nutzer Schreibrechte auf den Verzeichnissen hat.

Die Einrückungen sind uneinheitlich und machen des Lesen unnötig schwierig. Eingerückt wird immer mit 4 Leerzeichen pro Ebene.

Alles ab Zeile 230 wird nie erreicht. `debounce` enthält nicht den Wert, den Du denkst.
Helios86
User
Beiträge: 4
Registriert: Freitag 16. März 2018, 11:42

Vielen Dank für deine Tips, mit diesem Github Beitrag habe ich mich die halbe Nacht herumgequält. Von Perfektion bin ich weit entfernt, das ist mir bewusst. Bis auf die Sache mit dem Wasserzeichen tut das Skript allerdings genau das was es soll, ich sehe aktuell also keinen Grund etwas daran zu ändern. Wenn ich gewusst hätte was ich damit lostrete, hätte ich es vermutlich gleich sein lassen. Die Funktion wäre eben ein lustiges Gimmick. Ich schau mich mal noch nach anderen Lösungsansätzen um aber bevor ich mich damit unglücklich mache lasse ich es lieber sein.

LG. Helios
IHack
User
Beiträge: 14
Registriert: Dienstag 13. März 2018, 11:17

Du ziehst die falsche Lehre aus der lehrreichen Antwort,
wenn du keine Lehre daraus ziehst.

Damit werden deine Pythonkenntnisse sich nicht verbessern.
Helios86
User
Beiträge: 4
Registriert: Freitag 16. März 2018, 11:42

Mein Problem ist, das diese für mich neue Funktion in PIP noch weitere neue Fragen aufwirft die ich mir erst mal beantworten muss. ich bin im Moment wirklich froh das das Skript überhaupt funktioniert. Zugegeben sind meine Kenntnisse eher überschaubar und viele Zusammenhänge erschließen sich mir noch nicht so ganz. Ich versuche nicht allzuviel zu ändern um die Übersicht zu behalten. Die katastrophale Darstellung kommt wohl daher das ich das Skrip aus dem WinSCP Editor rüber kopiert habe. Nichts für ungut, aber ich komm hier einfach nicht weiter. Mein erklärtes Ziel ist es aber auch nicht pygame Virtuose zu werden sondern diese blöde Box für die Hochzeit von meinem Bruder nächste Woche zum Laufen zu bekommen.

LG. Helios ... der nervlich am Ende ist
Antworten