Nu heb ik daar vaak een breed plaatje en niet een staande dvd style hoes.
Ik heb daar een python script voor gemaakt dat computervision gebruikt.
Het kijkt naar het formaat (liggend of staand)
als je een liggend plaatje (png of jpg) laat vallen op het programma icoon in de Incompleet folder dan KIJKT het programma of er gezichten in voor komen, zo ja dan neemt hij het gevonden gezicht als midden voor de uitsnede van een staand plaatje en schrijft dat weg als folder.jpg in de LAATST gemaakte map (de film die je aan het binnen halen bent) dan kopieert hij ook het originele plaatje en noemt dat fanart.jpg.
Mochten er meerdere gezichten herkend zijn, dan opend hij de foto en een invoer veld waarop gevraagd word het juiste gezicht nummer in te voeren.
Dat is herkenbaar aan gekleurde randen om het herkende gezicht.
Bij een volledige dvd inlay zal dat bijna altijd de voorzijde van de dvd zijn (ongelijk of die links of rechts geplaatst is)
Ik ben het nog verder in functie aan het uitbreiden, maar mogelijk heeft iemand hier iets aan :-)
Stuur mij een bericht als je de laatste versie wil hebben incl de haarcascade files voor de gezichts herkenning (het zijn 3 files in totaal)
het werkt LOS van SAB
Code: Select all
import os
import sys
import cv2
import winreg as reg
from PIL import Image
import numpy as np
import tkinter as tk
from tkinter import simpledialog
import shutil
# Versie 1.8 - 25 september 2023
# Dit is een POST process script voor SABNZBD
# Het word aangeroepen door er een plaatje op te laten vallen
def crop_portrait(image_path):
# Laad de afbeelding
image = cv2.imread(image_path)
# Controleer of de breedte van de afbeelding groter is dan de hoogte
if image.shape[1] > image.shape[0]:
# Converteer de afbeelding naar grijswaarden
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Laad het Haar-cascade XML-bestand voor gezichtsdetectie
cascade_path = cv2.data.haarcascades + 'haarcascade_frontalface_default.xml'
face_cascade = cv2.CascadeClassifier(cascade_path)
# Voer gezichtsdetectie uit
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=15, minSize=(100, 100)) # was 30,30
if len(faces) == 0:
status = "Geen gezichten gevonden in de afbeelding."
else:
# Beperk het aantal gedetecteerde gezichten tot maximaal 5
if len(faces) > 5:
faces = faces[:5]
# Bereken het midden van elk gedetecteerd gezicht
colors = [(0, 0, 255), (0, 255, 0), (255, 0, 0), (0, 255, 255), (255, 255, 0)] # Rood, Groen, Blauw, Geel, Cyaan
output_image = image.copy()
for i, (x, y, w, h) in enumerate(faces):
color = colors[i % len(colors)]
cv2.rectangle(output_image, (x, y), (x + w, y + h), color, 2)
cv2.putText(output_image, str(i+1), (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.8, color, 2)
# Sla de afbeelding op met de gedetecteerde gezichten en hun corresponderende nummers als "temp.jpg"
output_image = cv2.cvtColor(output_image, cv2.COLOR_BGR2RGB)
pil_output_image = Image.fromarray(output_image)
pil_output_image.save("temp.jpg", format='JPEG')
if len(faces) == 1:
# Als er slechts één gezicht is, gebruik het dan direct voor bijsnijden
x, y, w, h = faces[0]
else:
os.system("temp.jpg") # Hier word het plaatje geopend im een viewer (systeem standaard viewer)
# Als er meerdere gezichten zijn, vraag de gebruiker om er een te kiezen
root = tk.Tk()
root.withdraw()
choice = simpledialog.askinteger("Kies een gezicht", "Meerdere gezichten gedetecteerd. Kies een gezicht om te gebruiken voor de DVD-hoes:", minvalue=1, maxvalue=len(faces), parent=root)
root.destroy()
os.remove("temp.jpg")
if choice is None:
# Gebruiker heeft het dialoogvenster gesloten, gebruik het eerste gezicht standaard
x, y, w, h = faces[0]
os.remove("temp.jpg")
else:
x, y, w, h = faces[choice - 1]
# Bereken het midden van het geselecteerde gezicht
center_x = x + w // 2
center_y = y + h // 2
# Bereken de gewenste hoogte voor de DVD-hoes
desired_height = image.shape[0]
# Bereken de gewenste breedte op basis van de beeldverhouding en gewenste hoogte
desired_width = int(desired_height * 4 / 6)
# Bereken de coördinaten van de linkerbovenhoek voor bijsnijden
left = max(0, center_x - desired_width // 2)
top = max(0, center_y - desired_height // 2)
# Bijsnijden van de afbeelding op basis van de gewenste breedte en hoogte
cropped_image = image[top:top + desired_height, left:left + desired_width]
# Beschrijf waarom het bijsnijden op deze locatie is gedaan
explanation = "Bijsnijden om te focussen op het gezicht op (x={}, y={}).".format(center_x, center_y)
status = explanation + "\nFolder.jpg succesvol gecreëerd.\n"
# Krijg de map van het momenteel uitgevoerde script
script_directory = os.path.dirname(os.path.abspath(__file__))
# Sla de bijgesneden afbeelding op als "Folder.jpg"
folder_image_name = "Folder.jpg"
cv2.imwrite(folder_image_name, cropped_image)
# Zoek de nieuwste map op basis van de aanmaaktijd in dezelfde map als de scriptmap
script_parent_directory = os.path.dirname(script_directory)
latest_directory = max([f.path for f in os.scandir(script_directory) if f.is_dir()], key=os.path.getctime, default=None)
if latest_directory:
# Verplaats "Folder.jpg" naar de nieuwste map
shutil.move(folder_image_name, os.path.join(latest_directory, "Folder.jpg"))
shutil.move(image_path, os.path.join(latest_directory,"Fanart.jpg" ))
# Voeg een statusbericht toe voor de kopieeroperatie
copy_status = f"Folder.jpg is verplaatst naar {latest_directory}"
# Exporteer de kopieerstatus naar een tekstbestand
output_status_file = os.path.join(script_directory, "output_status.txt")
with open(output_status_file, 'a') as file: # 'a' mode voegt toe aan het bestand
file.write(copy_status + "<1>\n") # Voeg een nieuwe regel toe
os.remove("temp.jpg")
os.system("taskkill PhotosApp.exe")
else:
status = "Het plaatje is NIET in Landschaps oriëntatie.<3>\n"
# Exporteer de status naar een tekstbestand
output_file = "output_status.txt"
with open(output_file, 'a') as file: # 'a' mode voegt toe aan het bestand
file.write(status + "\n") # Voeg een nieuwe regel toe
# Krijg het bestandspad van de neergezette afbeelding
if len(sys.argv) > 1:
dropped_file_path = sys.argv[1]
crop_portrait(dropped_file_path)
output_file = "output_status.txt"
with open(output_file, 'a') as file: # 'a' mode voegt toe aan het bestand
file.write("Image " + dropped_file_path + " verwijderd\n") # Voeg een nieuwe regel toe
os.remove(dropped_file_path)
else:
# print("Geen afbeeldingsbestand op het programma-icoon neergezet.")
# Voeg een statusbericht toe voor de de beeldbewerkings aktie
# Dit deel is feitelijk overbodig geworden met de drop functie
copy_status = f"Geen afbeeldingsbestand op het programma-icoon neergezet."
with open(output_file, 'a') as file: # 'a' mode voegt toe aan het bestand
file.write(status + "<2>\n") # Voeg een nieuwe regel toe
status = "temp.jpg is weer verwijderd.\n"
# verwijder het evt aan gemaakte temp.jpg image
output_file = "output_status.txt"
with open(output_file, 'a') as file: # 'a' mode voegt toe aan het bestand
file.write(status + "\n") # Voeg een nieuwe regel toe
# os.remove("temp.jpg")