Stop-Motion-Cam mit Tkinter-Gui

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
Benutzeravatar
kaytec
User
Beiträge: 545
Registriert: Dienstag 13. Februar 2007, 21:57

Samstag 10. Februar 2018, 10:08

Hallo,

die Buttons erklären sich selbst und es wird sofort ein Video zusammengefügt. Es langt eine USB-Cam oder auch die eingebaute Kamera im Rechner. Mit der "DEFAULT_CAM_ID" muss rumprobiert werden und mit "-1" wird die erste Cam (eingebaute Kamera) gefunden.

Code: Alles auswählen

#! /usr/bin/env python
# -*- coding: utf-8
try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk
        
import cv2
from PIL import Image, ImageTk
from functools import partial

WIDTH = 600
HEIGHT = 480
FPS = 30
DEFAULT_CAM_ID = 0
CODEC = "XVID"
DEFAULT_FILE_NAME = "output.avi"

class Cam(object):
    
    PROPID_WIDTH = 3
    PROPID_HEIGHT = 4
    
    def __init__(self, cam_id, file_name):
        self.cam = cv2.VideoCapture(cam_id)
        
        if not self.cam.isOpened():            
            raise RuntimeError("can not open camera {0!r}".format(
                cam_id))
                
        self.cam_width = self.cam.get(self.PROPID_WIDTH)
        self.cam_height = self.cam.get(self.PROPID_HEIGHT)
        self.video_writer = cv2.VideoWriter(file_name, cv2.cv.CV_FOURCC(
            *CODEC), FPS, (int(self.cam_width), int(self.cam_height)))
                
    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.release()

    @property
    def size(self):
        return (int(self.cam_width), int(self.cam_height))
                
    def get_image(self, size = None):
        if size:
            size = size
        else:
            size = self.size
        state, self.frame = self.cam.read()
        if state:
            image = Image.frombytes("RGB", self.size ,self.frame,
                "raw", "BGR").resize(size)
            return image
        else:
            return state
       
    def write_frame(self,width, height, fps):
        for x in xrange(fps):
            self.video_writer.write(self.frame)
                
    def release(self):
        self.cam.release()
            

class CartoonCamUI(tk.LabelFrame):
    
    UPDATE_INTERVAL = 20
    
    def __init__(self, parent, width, height, cam):
        tk.LabelFrame.__init__(self, parent, text="CAPTURE", 
            relief = "solid")
        self.parent = parent
        self.cam = cam
        self.width = width
        self.height = height
        self.tk_image = None
        self.fps = 0
        self.canvas = tk.Canvas(self, width=width, height=height, bd=10, 
            bg="lightgreen")
        self.canvas.pack(padx=5, pady=5)
        self.write_buttons = list()
        self.canvas_confirm_frame = tk.Frame(self, bd=2)
        confirm_yes = tk.Button(self.canvas_confirm_frame, text="YES",
        command=partial(self.start_stop, write = True))
        confirm_yes.pack(side="left")
        confirm_no = tk.Button(self.canvas_confirm_frame, text="NO", 
            command=self.start_stop)
        confirm_no.pack(side="right")
        write_button_frame = tk.Frame(self,  bg="gray")
        write_button_frame.pack(padx=5, pady=5)
        for column, (text, command, var) in enumerate(
            (("ONE FRAME", self.start_stop, 1),
              ("1/8 SEC", self.start_stop, FPS / 8),
              ("1/4 SEC", self.start_stop, FPS / 4),
              ("1/2 SEC", self.start_stop, FPS / 2),
              ("1 SEC", self.start_stop, FPS ))):
            button = tk.Button(write_button_frame, text=text, width=10, 
                relief="raised", font="Arial 10 bold")
            button.grid(column=column, row=0)
            self.write_buttons.append(button)
            button.config(command=partial(command, var))
            
    def start_stop(self, fps = None, write = False):
        if fps != None:
            self.fps = fps
        if self.after_id is None:
            self.canvas.config(bg="lightgreen")
            self.canvas.delete("confirm_frame")
            self.config(text="CAPTURE")
            for button in self.write_buttons:
                button.config(state="normal")
            if write:
                self.cam.write_frame(self.width, self.height, self.fps)
            self.run()
        else:        
            self.config(text="WRITE")
            self.canvas.config(bg="red")
            self.canvas.create_window(self.width / 2, self.height / 2, 
                window=self.canvas_confirm_frame, tag="confirm_frame")
            for button in self.write_buttons:
                button.config(state="disabled")
            self.after_cancel(self.after_id)
            self.after_id = None
           
    def run(self):
        self.tk_image = self.cam.get_image((self.width, self.height))
        if self.tk_image:
            self.canvas.delete("img")
            self.tk_image = ImageTk.PhotoImage(self.tk_image)
            self.canvas.create_image((10,10), anchor=tk.NW, 
                image=self.tk_image, tag="img")
            self.after_id = self.after(self.UPDATE_INTERVAL, self.run)
        else:
            self.canvas.create_text((self.width / 2, self.height / 2),
                text='NO CAM', font='Arial 40')
            self.config(text="NO CAM")
            for button in self.write_buttons:
                button.config(state="disabled")
            
    def release(self):
        self.parent.destroy()
        
def main():
    root = tk.Tk()
    root.title('STOP-MOTION-CAM')
    
    try:
        with Cam(DEFAULT_CAM_ID, DEFAULT_FILE_NAME) as cam:
            cartoon_cam_ui = CartoonCamUI(root, WIDTH, HEIGHT, cam)
            cartoon_cam_ui.pack(expand=tk.YES, padx=5, pady=5)
            cartoon_cam_ui.run()
            root.protocol("WM_DELETE_WINDOW",cartoon_cam_ui.release)
            root.mainloop()
        
    except RuntimeError:
        tk.Label(root, text = 'can not open camera {0!r}'.format(
                DEFAULT_CAM_ID), font = "Arial 20", height = 10).pack()
        root.mainloop()
        
if __name__ == '__main__':
    main()
Gruß Frank
Benutzeravatar
kaytec
User
Beiträge: 545
Registriert: Dienstag 13. Februar 2007, 21:57

Samstag 7. April 2018, 07:11

Hallo,

nach der vielen Hilfe bei dem "Mikroskop mit Tkinter-GUI" habe ich die "Stop-Motion-Cam mit Tkinter-GUI" verbessert. Dir Profis finden bestimmt noch Fehler.

Code: Alles auswählen

#! /usr/bin/env python
# -*- coding: utf-8

import tkinter as tk
        
import cv2
from PIL import Image, ImageTk
from functools import partial
import numpy as np

WIDTH = 600
HEIGHT = 480
FPS = 30
DEFAULT_CAM_ID = 0
CODEC = "XVID"
DEFAULT_FILE_NAME = "output.avi"

class Cam(object):
    
    PROPID_WIDTH = 3
    PROPID_HEIGHT = 4
    INTERPOLATION_METHODS= {"NEAREST" : cv2.INTER_NEAREST,
                            "LINEAR" : cv2.INTER_LINEAR,
                            "AREA" : cv2.INTER_AREA,
                            "CUBIC" : cv2.INTER_CUBIC,
                            "LANCZOS4" : cv2.INTER_LANCZOS4}
    
    def __init__(self, cam_id=DEFAULT_CAM_ID, file_name=DEFAULT_FILE_NAME):
        self.cam = cv2.VideoCapture(cam_id)
        self.last_frame = None
        
        if not self.cam.isOpened():            
            raise RuntimeError("can not open camera {0!r}".format(
                cam_id))
                
        self.cam_width = self.cam.get(self.PROPID_WIDTH)
        self.cam_height = self.cam.get(self.PROPID_HEIGHT)
        self.video_writer = cv2.VideoWriter(file_name, cv2.cv.CV_FOURCC(
            *CODEC), FPS, (int(self.cam_width), int(self.cam_height)))
                
    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.release()

    @property
    def size(self):
        return (int(self.cam_width), int(self.cam_height))
                
    def get_image(self, size = None):
        state, frame = self.cam.read()
       
        if state and np.array_equal(self.last_frame, frame):
            self.release()
            state = False
        if not state:
            raise RuntimeError("could not read image")
 
        self.last_frame = frame
        self.inter_frame = cv2.resize(frame, size if size else self.size,
        interpolation = self.INTERPOLATION_METHODS["LINEAR"])
            
        return self.inter_frame
       
    def write_frame(self,width, height, fps):
        for x in xrange(fps):
            self.video_writer.write(self.inter_frame)
                
    def release(self):
        self.cam.release()
            

class CartoonCamUI(tk.LabelFrame):
    
    UPDATE_INTERVAL = 20
    
    def __init__(self, parent, width, height, cam):
        tk.LabelFrame.__init__(self, parent, text="CAPTURE", 
            relief = "solid")
        self.parent = parent
        self.cam = cam
        self.width = width
        self.height = height
        self.tk_image = None
        self.fps = 0
        self.canvas = tk.Canvas(self, width=width, height=height, bd=10, 
            bg="lightgreen")
        self.canvas.pack(padx=5, pady=5)
        self.write_buttons = list()
        self.canvas_confirm_frame = tk.Frame(self, bd=2)
        confirm_yes = tk.Button(self.canvas_confirm_frame, text="YES",
        command=partial(self.start_stop, write = True))
        confirm_yes.pack(side="left")
        confirm_no = tk.Button(self.canvas_confirm_frame, text="NO", 
            command=self.start_stop)
        confirm_no.pack(side="right")
        write_button_frame = tk.Frame(self,  bg="gray")
        write_button_frame.pack(padx=5, pady=5)
        for column, (text, command, var) in enumerate(
            (("ONE FRAME", self.start_stop, 1),
              ("1/8 SEC", self.start_stop, FPS / 8),
              ("1/4 SEC", self.start_stop, FPS / 4),
              ("1/2 SEC", self.start_stop, FPS / 2),
              ("1 SEC", self.start_stop, FPS ))):
            button = tk.Button(write_button_frame, text=text, width=10, 
                relief="raised", font="Arial 10 bold")
            button.grid(column=column, row=0)
            self.write_buttons.append(button)
            button.config(command=partial(command, var))
            

    def start_stop(self, fps = None, write = False):

        if not self.after_id:
            self.canvas.config(bg="lightgreen")
            self.canvas.delete("confirm_frame")
            self.config(text="CAPTURE")
            for button in self.write_buttons:
                button.config(state="normal")
            if write:
                self.cam.write_frame(self.width, self.height, 
                    fps if fps else self.fps)
            self.run()
        else:        
            self.config(text="WRITE")
            self.canvas.config(bg="red")
            self.canvas.create_window(self.width / 2, self.height / 2, 
                window=self.canvas_confirm_frame, tag="confirm_frame")
            for button in self.write_buttons:
                button.config(state="disabled")
            self.after_cancel(self.after_id)
            self.after_id = None
           
    def run(self):
        try:
            tk_image = Image.frombytes("RGB",  self.cam.size,
                self.cam.get_image(), "raw", "BGR")
        except RuntimeError:
            self.raise_cam_id_error()
            return
            
        self.canvas.delete("img")
        self.tk_image = ImageTk.PhotoImage(tk_image)
        self.canvas.create_image((10,10), anchor=tk.NW, 
            image=self.tk_image, tag="img")
        self.after_id = self.after(self.UPDATE_INTERVAL, self.run)
                
    def raise_cam_id_error(self):
        self.canvas.delete("img", "rec", "txt")
        self.canvas.create_text((self.width / 2, self.height / 2),
            text='NO CAM', font='Arial 40')
        for button in self.buttons:
            button.config(state="disabled")
            
    def release(self):
        self.parent.destroy()
        
def main():
    root = tk.Tk()
    root.title('STOP-MOTION-CAM')
    
    try:
        with Cam() as cam:
            cartoon_cam_ui = CartoonCamUI(root, WIDTH, HEIGHT, cam)
            cartoon_cam_ui.pack(expand=tk.YES, padx=5, pady=5)
            cartoon_cam_ui.run()
            root.protocol("WM_DELETE_WINDOW",cartoon_cam_ui.release)
            root.mainloop()
        
    except RuntimeError:
        tk.Label(root, text = 'can not open camera {0!r}'.format(
                DEFAULT_CAM_ID), font = "Arial 20", height = 10).pack()
        root.mainloop()
        
if __name__ == '__main__':
    main()
Gruß Frank
Benutzeravatar
kaytec
User
Beiträge: 545
Registriert: Dienstag 13. Februar 2007, 21:57

Dienstag 10. April 2018, 05:20

Hallo,

hat keine Bilder mehr in die Datei geschrieben, da "self.fps" immer mit None überschrieben wurde. Die Bildgröße ändern im laufenden Betrieb ist auch keine gute Idee - sollte beim Starten gleich gemacht werden.

Code: Alles auswählen

#! /usr/bin/env python
# -*- coding: utf-8

import tkinter as tk
        
import cv2
from PIL import Image, ImageTk
from functools import partial
import numpy as np

WIDTH = 640
HEIGHT = 480
FPS = 30
DEFAULT_CAM_ID = 0
CODEC = "XVID"
DEFAULT_FILE_NAME = "output.avi"

class Cam(object):
    
    PROPID_WIDTH = 3
    PROPID_HEIGHT = 4
    INTERPOLATION_METHODS = {"NEAREST" : cv2.INTER_NEAREST,
                             "LINEAR" : cv2.INTER_LINEAR,
                             "AREA" : cv2.INTER_AREA,
                             "CUBIC" : cv2.INTER_CUBIC,
                             "LANCZOS4" : cv2.INTER_LANCZOS4}
    
    def __init__(self, cam_id=DEFAULT_CAM_ID, file_name=DEFAULT_FILE_NAME):
        self.cam = cv2.VideoCapture(cam_id)
        self.last_frame = None
        
        if not self.cam.isOpened():            
            raise RuntimeError("can not open camera {0!r}".format(
                cam_id))
                
        self.cam_width = int(self.cam.get(self.PROPID_WIDTH))
        self.cam_height = int(self.cam.get(self.PROPID_HEIGHT))
        self.video_writer = cv2.VideoWriter(file_name, cv2.cv.CV_FOURCC(
            *CODEC), FPS, (int(self.cam_width), int(self.cam_height)))
                
    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.release()

    @property
    def size(self):
        return self.cam_width, self.cam_height
                
    def get_image(self):
        state, frame = self.cam.read()
       
        if state and np.array_equal(self.last_frame, frame):
            self.release()
            state = False
        if not state:
            raise RuntimeError("could not read image")
 
        self.last_frame = frame
        self.inter_frame = cv2.resize(frame, self.size,
        interpolation = self.INTERPOLATION_METHODS["LINEAR"])
            
        return self.inter_frame
       
    def write_frame(self, fps):
        for x in xrange(fps):
            self.video_writer.write(self.inter_frame)
                
    def release(self):
        self.cam.release()
            

class CartoonCamUI(tk.LabelFrame):
    
    UPDATE_INTERVAL = 20
    
    def __init__(self, parent, width, height, cam):
        tk.LabelFrame.__init__(self, parent, text="CAPTURE", 
            relief = "solid")
        self.parent = parent
        self.cam = cam
        self.width = width
        self.height = height
        self.tk_image = None
        self.fps = 0
        self.canvas = tk.Canvas(self, width=width, height=height, bd=10, 
            bg="lightgreen")
        self.canvas.pack(padx=5, pady=5)
        self.write_buttons = list()
        self.canvas_confirm_frame = tk.Frame(self, bd=2)
        confirm_yes = tk.Button(self.canvas_confirm_frame, text="YES",
        command=partial(self.start_stop, write = True))
        confirm_yes.pack(side="left")
        confirm_no = tk.Button(self.canvas_confirm_frame, text="NO", 
            command=self.start_stop)
        confirm_no.pack(side="right")
        write_button_frame = tk.Frame(self,  bg="gray")
        write_button_frame.pack(padx=5, pady=5)
        for column, (text, command, var) in enumerate(
            (("ONE FRAME", self.start_stop, 1),
              ("1/8 SEC", self.start_stop, FPS / 8),
              ("1/4 SEC", self.start_stop, FPS / 4),
              ("1/2 SEC", self.start_stop, FPS / 2),
              ("1 SEC", self.start_stop, FPS ))):
            button = tk.Button(write_button_frame, text=text, width=10, 
                relief="raised", font="Arial 10 bold")
            button.grid(column=column, row=0)
            self.write_buttons.append(button)
            button.config(command=partial(command, var))
            

    def start_stop(self, fps = None, write = False):
        if fps:
            self.fps = fps
        if not self.after_id:
            self.canvas.config(bg="lightgreen")
            self.canvas.delete("confirm_frame")
            self.config(text="CAPTURE")
            for button in self.write_buttons:
                button.config(state="normal")
            if write:
                self.cam.write_frame(self.fps)
            self.run()
        else:        
            self.config(text="WRITE")
            self.canvas.config(bg="red")
            self.canvas.create_window(self.width / 2, self.height / 2, 
                window=self.canvas_confirm_frame, tag="confirm_frame")
            for button in self.write_buttons:
                button.config(state="disabled")
            self.after_cancel(self.after_id)
            self.after_id = None
           
    def run(self):
        try:
            tk_image = Image.frombytes("RGB",  self.cam.size,
                self.cam.get_image(), "raw", "BGR")
        except RuntimeError:
            self.raise_cam_id_error()
            return
            
        self.canvas.delete("img")
        self.tk_image = ImageTk.PhotoImage(tk_image)
        self.canvas.create_image((10,10), anchor=tk.NW, 
            image=self.tk_image, tag="img")
        self.after_id = self.after(self.UPDATE_INTERVAL, self.run)
                
    def raise_cam_id_error(self):
        self.canvas.delete("img", "rec", "txt")
        self.canvas.create_text((self.width / 2, self.height / 2),
            text='NO CAM', font='Arial 40')
        for button in self.buttons:
            button.config(state="disabled")
            
    def release(self):
        self.parent.destroy()
        
def main():
    root = tk.Tk()
    root.title('STOP-MOTION-CAM')
    
    try:
        with Cam() as cam:
            cartoon_cam_ui = CartoonCamUI(root, WIDTH, HEIGHT, cam)
            cartoon_cam_ui.pack(expand=tk.YES, padx=5, pady=5)
            cartoon_cam_ui.run()
            root.protocol("WM_DELETE_WINDOW",cartoon_cam_ui.release)
            root.mainloop()
        
    except RuntimeError:
        tk.Label(root, text = 'can not open camera {0!r}'.format(
                DEFAULT_CAM_ID), font = "Arial 20", height = 10).pack()
        root.mainloop()
        
if __name__ == '__main__':
    main()
    
Gruß
Benutzeravatar
MagBen
User
Beiträge: 791
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Dienstag 10. April 2018, 07:42

Hast du Beispiele von Stopmotion Animationen, die du damit gemacht hast (z.B. auf YouTube)?
a fool with a tool is still a fool, www.magben.de, YouTube
Benutzeravatar
kaytec
User
Beiträge: 545
Registriert: Dienstag 13. Februar 2007, 21:57

Dienstag 10. April 2018, 08:07

Hallo MagBen,

ich habe mit Hortkindern schon sehr viele Filme erstellt, doch mache ich solche Angebote nicht mit dem Anspruch ein "Meisterwerk" der Filmgeschichte zu produzieren. Die Kinder sollen eher einen Einblick in die Tricks/Manipulation von Filmen bekommen. Falls ich Zeit habe, dann mache ich mal eins für Youtube.

Gruß Frank
Benutzeravatar
Kebap
User
Beiträge: 402
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

Dienstag 10. April 2018, 08:14

Hallo Frank,

ich wollte das mal ausprobieren, leider erfolglos:

Code: Alles auswählen

ImportError: No module named cv2
MorgenGrauen: 1 Welt, >12 Gilden, >85 Abenteuer, >1000 Waffen und Rüstungen,
>2500 NPC, >16000 Räume, >170 freiwillige Programmierer, einfach Text, seit 1992.
Benutzeravatar
kaytec
User
Beiträge: 545
Registriert: Dienstag 13. Februar 2007, 21:57

Dienstag 10. April 2018, 08:22

Hallo Kebap,

braucht du OpenCV --> https://opencv.org/

Gruß
Benutzeravatar
kaytec
User
Beiträge: 545
Registriert: Dienstag 13. Februar 2007, 21:57

Samstag 28. April 2018, 06:30

Hallo,
war noch ein kleiner Fehler drin.

Code: Alles auswählen

#! /usr/bin/env python
# -*- coding: utf-8

import tkinter as tk
        
import cv2
from PIL import Image, ImageTk
from functools import partial
import numpy as np

WIDTH = 640
HEIGHT = 480
FPS = 30
DEFAULT_CAM_ID = 0
CODEC = "XVID"
DEFAULT_FILE_NAME = "output.avi"

class Cam(object):
    
    PROPID_WIDTH = 3
    PROPID_HEIGHT = 4
    INTERPOLATION_METHODS = {"NEAREST" : cv2.INTER_NEAREST,
                             "LINEAR" : cv2.INTER_LINEAR,
                             "AREA" : cv2.INTER_AREA,
                             "CUBIC" : cv2.INTER_CUBIC,
                             "LANCZOS4" : cv2.INTER_LANCZOS4}
    
    def __init__(self, cam_id=DEFAULT_CAM_ID, file_name=DEFAULT_FILE_NAME):
        self.cam = cv2.VideoCapture(cam_id)
        self.last_frame = None
        
        if not self.cam.isOpened():            
            raise RuntimeError("can not open camera {0!r}".format(
                cam_id))
                
        self.cam_width = int(self.cam.get(self.PROPID_WIDTH))
        self.cam_height = int(self.cam.get(self.PROPID_HEIGHT))
        self.video_writer = cv2.VideoWriter(file_name, cv2.cv.CV_FOURCC(
            *CODEC), FPS, (int(self.cam_width), int(self.cam_height)))
                
    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.release()

    @property
    def size(self):
        return self.cam_width, self.cam_height
                
    def get_image(self):
        state, frame = self.cam.read()
       
        if state and np.array_equal(self.last_frame, frame):
            self.release()
            state = False
        if not state:
            raise RuntimeError("could not read image")
 
        self.last_frame = frame
        self.inter_frame = cv2.resize(frame, self.size,
        interpolation = self.INTERPOLATION_METHODS["LINEAR"])
            
        return self.inter_frame
       
    def write_frame(self, fps):
        for x in xrange(fps):
            self.video_writer.write(self.inter_frame)
                
    def release(self):
        self.cam.release()
            

class CartoonCamUI(tk.LabelFrame):
    
    UPDATE_INTERVAL = 20
    
    def __init__(self, parent, width, height, cam):
        tk.LabelFrame.__init__(self, parent, text="CAPTURE", 
            relief = "solid")
        self.parent = parent
        self.cam = cam
        self.width = width
        self.height = height
        self.tk_image = None
        self.fps = 0
        self.canvas = tk.Canvas(self, width=width, height=height, bd=10, 
            bg="lightgreen")
        self.canvas.pack(padx=5, pady=5)
        self.canvas_confirm_frame = tk.Frame(self, bd=2)
        confirm_yes = tk.Button(self.canvas_confirm_frame, text="YES",
        command=partial(self.start_stop, write = True))
        confirm_yes.pack(side="left")
        confirm_no = tk.Button(self.canvas_confirm_frame, text="NO", 
            command=self.start_stop)
        confirm_no.pack(side="right")
        button_frame = tk.Frame(self,  bg="gray")
        button_frame.pack(padx=5, pady=5)
        self.buttons = list()
        for column, (text, command, var) in enumerate(
            (("ONE FRAME", self.start_stop, 1),
              ("1/8 SEC", self.start_stop, FPS / 8),
              ("1/4 SEC", self.start_stop, FPS / 4),
              ("1/2 SEC", self.start_stop, FPS / 2),
              ("1 SEC", self.start_stop, FPS ))):
            button = tk.Button(button_frame, text=text, width=10, 
                relief="raised", font="Arial 10 bold")
            button.grid(column=column, row=0)
            self.buttons.append(button)
            button.config(command=partial(command, var))

    def start_stop(self, fps = None, write = False):
        if fps:
            self.fps = fps
        if not self.after_id:
            self.canvas.config(bg="lightgreen")
            self.canvas.delete("confirm_frame")
            self.config(text="CAPTURE")
            for button in self.buttons:
                button.config(state="normal")
            if write:
                self.cam.write_frame(self.fps)
            self.run()
        else:        
            self.config(text="WRITE")
            self.canvas.config(bg="red")
            self.canvas.create_window(self.width / 2, self.height / 2, 
                window=self.canvas_confirm_frame, tag="confirm_frame")
            for button in self.buttons:
                button.config(state="disabled")
            self.after_cancel(self.after_id)
            self.after_id = None
           
    def run(self):
        try:
            tk_image = Image.frombytes("RGB",  self.cam.size,
                self.cam.get_image(), "raw", "BGR")
        except RuntimeError:
            self.raise_cam_id_error()
            return
            
        self.canvas.delete("img")
        self.tk_image = ImageTk.PhotoImage(tk_image)
        self.canvas.create_image((10,10), anchor=tk.NW, 
            image=self.tk_image, tag="img")
        self.after_id = self.after(self.UPDATE_INTERVAL, self.run)
                
    def raise_cam_id_error(self):
        self.canvas.delete("img", "rec", "txt")
        self.canvas.create_text((self.width / 2, self.height / 2),
            text='NO CAM', font='Arial 40')
        for button in self.buttons:
            button.config(state="disabled")
            
    def release(self):
        self.parent.destroy()
        
def main():
    root = tk.Tk()
    root.title('STOP-MOTION-CAM')
    
    try:
        with Cam() as cam:
            cartoon_cam_ui = CartoonCamUI(root, WIDTH, HEIGHT, cam)
            cartoon_cam_ui.pack(expand=tk.YES, padx=5, pady=5)
            cartoon_cam_ui.run()
            root.protocol("WM_DELETE_WINDOW",cartoon_cam_ui.release)
            root.mainloop()
        
    except RuntimeError:
        tk.Label(root, text = 'can not open camera {0!r}'.format(
                DEFAULT_CAM_ID), font = "Arial 20", height = 10).pack()
        root.mainloop()
        
if __name__ == '__main__':
    main()
Gruß
Benutzeravatar
kaytec
User
Beiträge: 545
Registriert: Dienstag 13. Februar 2007, 21:57

Sonntag 9. Dezember 2018, 09:10

Hallo,

hat sich bei OpenCV was geändert.

Code: Alles auswählen

/usr/bin/env python
# -*- coding: utf-8

import Tkinter as tk
        
import cv2
from PIL import Image, ImageTk
from functools import partial
import numpy as np

WIDTH = 640
HEIGHT = 480
FPS = 30
DEFAULT_CAM_ID = 0
CODEC = "XVID"
DEFAULT_FILE_NAME = "output.avi"

class Cam(object):
    
    PROPID_WIDTH = 3
    PROPID_HEIGHT = 4
    INTERPOLATION_METHODS = {"NEAREST" : cv2.INTER_NEAREST,
                             "LINEAR" : cv2.INTER_LINEAR,
                             "AREA" : cv2.INTER_AREA,
                             "CUBIC" : cv2.INTER_CUBIC,
                             "LANCZOS4" : cv2.INTER_LANCZOS4}
    
    def __init__(self, cam_id=DEFAULT_CAM_ID, file_name=DEFAULT_FILE_NAME):
        self.cam = cv2.VideoCapture(cam_id)
        self.last_frame = None
        
        if not self.cam.isOpened():            
            raise RuntimeError("can not open camera {0!r}".format(
                cam_id))
                
        self.cam_width = int(self.cam.get(self.PROPID_WIDTH))
        self.cam_height = int(self.cam.get(self.PROPID_HEIGHT))
        self.video_writer = cv2.VideoWriter(file_name, cv2.VideoWriter_fourcc(
            *CODEC), FPS, (int(self.cam_width), int(self.cam_height)))
                
    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.release()

    @property
    def size(self):
        return self.cam_width, self.cam_height
                
    def get_image(self):
        state, frame = self.cam.read()
       
        if state and np.array_equal(self.last_frame, frame):
            self.release()
            state = False
        if not state:
            raise RuntimeError("could not read image")
 
        self.last_frame = frame
        self.inter_frame = cv2.resize(frame, self.size,
        interpolation = self.INTERPOLATION_METHODS["LINEAR"])
            
        return self.inter_frame
       
    def write_frame(self, fps):
        for x in xrange(fps):
            self.video_writer.write(self.inter_frame)
                
    def release(self):
        self.cam.release()
            

class CartoonCamUI(tk.LabelFrame):
    
    UPDATE_INTERVAL = 20
    
    def __init__(self, parent, width, height, cam):
        tk.LabelFrame.__init__(self, parent, text="CAPTURE", 
            relief = "solid")
        self.parent = parent
        self.cam = cam
        self.width = width
        self.height = height
        self.tk_image = None
        self.fps = 0
        self.canvas = tk.Canvas(self, width=width, height=height, bd=10, 
            bg="lightgreen")
        self.canvas.pack(padx=5, pady=5)
        self.canvas_confirm_frame = tk.Frame(self, bd=2)
        confirm_yes = tk.Button(self.canvas_confirm_frame, text="YES",
        command=partial(self.start_stop, write = True))
        confirm_yes.pack(side="left")
        confirm_no = tk.Button(self.canvas_confirm_frame, text="NO", 
            command=self.start_stop)
        confirm_no.pack(side="right")
        button_frame = tk.Frame(self,  bg="gray")
        button_frame.pack(padx=5, pady=5)
        self.buttons = list()
        for column, (text, command, var) in enumerate(
            (("ONE FRAME", self.start_stop, 1),
              ("1/8 SEC", self.start_stop, FPS / 8),
              ("1/4 SEC", self.start_stop, FPS / 4),
              ("1/2 SEC", self.start_stop, FPS / 2),
              ("1 SEC", self.start_stop, FPS ))):
            button = tk.Button(button_frame, text=text, width=10, 
                relief="raised", font="Arial 10 bold")
            button.grid(column=column, row=0)
            self.buttons.append(button)
            button.config(command=partial(command, var))

    def start_stop(self, fps = None, write = False):
        if fps:
            self.fps = fps
        if not self.after_id:
            self.canvas.config(bg="lightgreen")
            self.canvas.delete("confirm_frame")
            self.config(text="CAPTURE")
            for button in self.buttons:
                button.config(state="normal")
            if write:
                self.cam.write_frame(self.fps)
            self.run()
        else:        
            self.config(text="WRITE")
            self.canvas.config(bg="red")
            self.canvas.create_window(self.width / 2, self.height / 2, 
                window=self.canvas_confirm_frame, tag="confirm_frame")
            for button in self.buttons:
                button.config(state="disabled")
            self.after_cancel(self.after_id)
            self.after_id = None
           
    def run(self):
        try:
            tk_image = Image.frombytes("RGB",  self.cam.size,
                self.cam.get_image(), "raw", "BGR")
        except RuntimeError:
            self.raise_cam_id_error()
            return
            
        self.canvas.delete("img")
        self.tk_image = ImageTk.PhotoImage(tk_image)
        self.canvas.create_image((10,10), anchor=tk.NW, 
            image=self.tk_image, tag="img")
        self.after_id = self.after(self.UPDATE_INTERVAL, self.run)
                
    def raise_cam_id_error(self):
        self.canvas.delete("img", "rec", "txt")
        self.canvas.create_text((self.width / 2, self.height / 2),
            text='NO CAM', font='Arial 40')
        for button in self.buttons:
            button.config(state="disabled")
            
    def release(self):
        self.parent.destroy()
        
def main():
    root = tk.Tk()
    root.title('STOP-MOTION-CAM')
    
    try:
        with Cam() as cam:
            cartoon_cam_ui = CartoonCamUI(root, WIDTH, HEIGHT, cam)
            cartoon_cam_ui.pack(expand=tk.YES, padx=5, pady=5)
            cartoon_cam_ui.run()
            root.protocol("WM_DELETE_WINDOW",cartoon_cam_ui.release)
            root.mainloop()
        
    except RuntimeError:
        tk.Label(root, text = 'can not open camera {0!r}'.format(
                DEFAULT_CAM_ID), font = "Arial 20", height = 10).pack()
        root.mainloop()
        
if __name__ == '__main__':
    main()


Gruß Frank
Antworten