Binary-Cam

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

Hallo,
und weiter geht es mit den Opencv - Spielereien.

Code: Alles auswählen

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

import Tkinter as tk
from PIL import Image, ImageTk
import cv2

TITLE = "BINARY-CAM"
UPDATE_TIME = 10
WIDTH = 640
HEIGHT = 480
RGB = "L"
BGR = "BGR"
MODUS = "raw"
CAM = -1
LABEL_WIDTH = 20
LABEL_HEIGHT = 5
LABEL_TEXT = "NO CAM"
LABEL_FONT = "Arial 20"
PROPID_WIDTH = 3 
PROPID_HEIGHT = 4
GRAY = 255
KERNEL = (5, 5)
BLOCK_SIZE = 63
PARAM_1 = 5

class Cam(tk.Label):
    def __init__(self, width, height, cam):
        tk.Label.__init__(self)
        self.width = width
        self.height = height
        self.capture = True
        self.cam = cv2.VideoCapture(CAM)
        
    def start_stop(self):
        if self.capture:
            self.capture = False
        else:
            self.capture = True
            self.after(UPDATE_TIME, self.run)
        
    def run(self):
        if self.cam.isOpened():
            self.tk_image = ImageTk.PhotoImage(image = self.resize_image(
                Image.fromstring(RGB, (int(self.cam.get(PROPID_WIDTH)), 
                int(self.cam.get(PROPID_HEIGHT))),  cv2.blur(cv2.adaptiveThreshold(
                cv2.cvtColor(self.cam.read()[1], cv2.COLOR_BGR2GRAY), GRAY, 
                cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, BLOCK_SIZE, PARAM_1), 
                KERNEL), MODUS)))
            self.config(image = self.tk_image)
        else:
            self.config(width=LABEL_WIDTH, height=LABEL_HEIGHT,
                text = LABEL_TEXT, font=LABEL_FONT)
        if self.capture:
            self.after(UPDATE_TIME, self.run)
    
    def resize_image(self, img):
        img_width, img_height = img.size
        if self.height >= self.width:
            img_height = img_height * self.width // img_width
            img_width = self.width
        else:
            img_width = img_width * self.height // img_height
            img_height = self.height
        return img.resize((img_width, img_height))
        
    def release(self):
        self.cam.release()
        
if __name__ == '__main__':
    root = tk.Tk()
    cam = Cam(WIDTH, HEIGHT, CAM)
    cam.pack()
    cam.run()
    tk.Button(text="Start/Stop", command=cam.start_stop).pack()
    root.title(TITLE)
    root.mainloop()
    cam.release()
Gruß Frank
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Was genau macht denn das Programm?

Wozu hast Du die ganzen Konstanten auf Modulebene definiert? Wenn Du eh alles in eine Klasse stopfst (k.A. ob man das bei Tk so macht), hättest Du das auch als Exemplarattribute oder Klassenattribute realisieren können. Imho wäre der Bezug zur Verwendung dann deutlicher.

Die ``start_stop`` Methode kann man vereinfachen, indem man den Schalter einfach invertiert. Dann braucht man nur noch eine Bedingung für das Starten...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo Hyperion,

hatte gedacht keine Konstanten in den Code und daher alle nach oben. Falls ich die Methode vereinfache, kann ich dann noch das after ausführen ? Ohne die Zeitverzögerung starte ich einen neuen Thread und der alte läuft noch. Alles andere an deinen Fragen verstehe ich nicht. Mit dem Script kann man von sich oder anderen Personen Bilder aufnehmen und an die Wand werfen (Beamer nicht vergessen ;-)). Mit Stiften oder Pinsel abmalen und man hat ein schönes Geschenk. Ich mache solche Bilder als Herbstferienprojekt in einem Hort. Einen weiteren Zweck hat es nicht.

Gruß Frank

P.S.: Kann ich ein Bild einfügen, dann könnte ich es zeigen ?
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

kaytec hat geschrieben:P.S.: Kann ich ein Bild einfügen, dann könnte ich es zeigen ?
Ein Link zu einem Bild wäre IMHO besser.
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo,

hier ist ein Link >> http://www.robindavid.fr/opencv-tutoria ... metic.html
Die Kamera läuft und wandelt gleichzeitig die Aufnahme um - sieht dann so aus wie bei dem Bild --> "Thresholded Binary" auf der o.g. Seite.

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

Hallo Hyperion,

etwa so:

Code: Alles auswählen

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

import Tkinter as tk
from PIL import Image, ImageTk
import cv2

TITLE = "BINARY-CAM"
BUTTON_TEXT = "Start/Stop"
WIDTH = 640
HEIGHT = 480    
CAM = -1
  
class Cam(tk.Label):
    UPDATE_TIME = 10
    RGB = "L"
    BGR = "BGR"
    MODUS = "raw"
    CAM = -1
    LABEL_WIDTH = 20
    LABEL_HEIGHT = 5
    LABEL_TEXT = "NO CAM"
    LABEL_FONT = "Arial 20"
    PROPID_WIDTH = 3
    PROPID_HEIGHT = 4
    GRAY = 255
    KERNEL = (5, 5)
    BLOCK_SIZE = 63
    PARAM_1 = 5
    
    def __init__(self, width, height, cam):
        tk.Label.__init__(self)
        self.width = width
        self.height = height
        self.capture = True
        self.cam = cv2.VideoCapture(cam)
       
    def start_stop(self):
        if self.capture:
            self.capture = False
        else:
            self.capture = True
            self.after(UPDATE_TIME, self.run)
       
    def run(self):
        if self.cam.isOpened():
            self.tk_image = ImageTk.PhotoImage(image = self.resize_image(
                Image.fromstring(self.RGB, (int(self.cam.get(
                self.PROPID_WIDTH)), int(self.cam.get(self.PROPID_HEIGHT))), 
                cv2.blur(cv2.adaptiveThreshold(cv2.cvtColor(
                self.cam.read()[1], cv2.COLOR_BGR2GRAY), self.GRAY,
                cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 
                self.BLOCK_SIZE, self.PARAM_1), self.KERNEL), self.MODUS)))
            self.config(image = self.tk_image)
        else:
            self.config(width=self.LABEL_WIDTH, height=self.LABEL_HEIGHT,
                text=self.LABEL_TEXT, font=self.LABEL_FONT)
        if self.capture:
            self.after(self.UPDATE_TIME, self.run)
   
    def resize_image(self, img):
        img_width, img_height = img.size
        if self.height >= self.width:
            img_height = img_height * self.width // img_width
            img_width = self.width
        else:
            img_width = img_width * self.height // img_height
            img_height = self.height
        return img.resize((img_width, img_height))
       
    def release(self):
        self.cam.release()
       
if __name__ == '__main__':
    root = tk.Tk()
    cam = Cam(WIDTH, HEIGHT, CAM)
    cam.pack()
    cam.run()
    tk.Button(text=BUTTON_TEXT, command=cam.start_stop).pack()
    root.title(TITLE)
    root.mainloop()
    cam.release()
Gruß Frank
BlackJack

@kaytec: ``RGB = "L"`` sieht ziemlich falsch aus. ;-)
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo BlackJack,

Eigentlich macht die Kamera (Web-Cam) ein Farbbild, doch die Umstellung von RGB = "L" ändert es zu einem "greyscale image" Die Konstante BGR ="BGR" ist unötigt und kann gelöscht werden.

Gruß Frank

War ein Fehler drin - konnte den oberen Breitag nicht editieren,

Code: Alles auswählen

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

import Tkinter as tk
from PIL import Image, ImageTk
import cv2

TITLE = "BINARY-CAM"
BUTTON_TEXT = "Start/Stop"
WIDTH = 640
HEIGHT = 480    
CAM = -1
  
class Cam(tk.Label):
    UPDATE_TIME = 10
    RGB = "L"
    MODUS = "raw"
    CAM = -1
    LABEL_WIDTH = 20
    LABEL_HEIGHT = 5
    LABEL_TEXT = "NO CAM"
    LABEL_FONT = "Arial 20"
    PROPID_WIDTH = 3
    PROPID_HEIGHT = 4
    GRAY = 255
    KERNEL = (5, 5)
    BLOCK_SIZE = 63
    PARAM_1 = 5
    
    def __init__(self, width, height, cam):
        tk.Label.__init__(self)
        self.width = width
        self.height = height
        self.capture = True
        self.cam = cv2.VideoCapture(cam)
       
    def start_stop(self):
        if self.capture:
            self.capture = False
        else:
            self.capture = True
            self.after(self.UPDATE_TIME, self.run)
       
    def run(self):
        if self.cam.isOpened():
            self.tk_image = ImageTk.PhotoImage(image = self.resize_image(
                Image.fromstring(self.RGB, (int(self.cam.get(
                self.PROPID_WIDTH)), int(self.cam.get(self.PROPID_HEIGHT))), 
                cv2.blur(cv2.adaptiveThreshold(cv2.cvtColor(
                self.cam.read()[1], cv2.COLOR_BGR2GRAY), self.GRAY,
                cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 
                self.BLOCK_SIZE, self.PARAM_1), self.KERNEL), self.MODUS)))
            self.config(image = self.tk_image)
        else:
            self.config(width=self.LABEL_WIDTH, height=self.LABEL_HEIGHT,
                text=self.LABEL_TEXT, font=self.LABEL_FONT)
        if self.capture:
            self.after(self.UPDATE_TIME, self.run)
   
    def resize_image(self, img):
        img_width, img_height = img.size
        if self.height >= self.width:
            img_height = img_height * self.width // img_width
            img_width = self.width
        else:
            img_width = img_width * self.height // img_height
            img_height = self.height
        return img.resize((img_width, img_height))
       
    def release(self):
        self.cam.release()
       
if __name__ == '__main__':
    root = tk.Tk()
    cam = Cam(WIDTH, HEIGHT, CAM)
    cam.pack()
    cam.run()
    tk.Button(text=BUTTON_TEXT, command=cam.start_stop).pack()
    root.title(TITLE)
    root.mainloop()
    cam.release()
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo,
kann gelöscht werden!
Zuletzt geändert von kaytec am Samstag 3. Oktober 2015, 09:34, insgesamt 1-mal geändert.
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo,
so sieht es aus.
Bild
Gruß Frank
BlackJack

@kaytec: Ich weiss was das macht, genau deswegen weiss ich ja das `RGB` der falsche Name für 'L' ist, denn 'L' steht eben nicht für `RGB` sondern für `LUMINANCE` oder üblicher `GRAYSCALE`. Und spezifischer für das Programm wäre die Bedeutung von dem Wert wohl eher so etwas wie `PIL_IMAGE_MODE`, dann müsste man den Namen nicht ändern wenn man den Wert zum Beispiel tatsächlich auf 'RGB' ändert.

Einige andere Konstantennamen sind auch sehr nichtssagend. `WIDTH`, `HEIGHT`, `LABEL_TEXT` oder `BUTTON_TEXT` zum Beispiel sagen zu wenig aus. Mir sind's auch zu viele Konstanten. Man muss nicht krampfhaft *jeden* literalen Wert an einen Konstantennamen binden, das macht ein Programm am Ende sogar schwerer zu warten, weil Informationen die nur einmal irgendwo verwendet werden und nicht zur Kategorie „sollte am Anfang definiert werden weil die Wahrscheinlichkeit gross ist dass das mal leicht angepasst werden muss“ gehören, dann an zwei Stellen im Programm verteilt sind. So etwas wie Höhe und Breite des Kamerabildes oder Pfadangaben, aber nicht jede Schaltflächen- oder Label-Beschriftung.

Das Hauptprogramm steht auf Modulebene und nicht in einer Funktion. Das erhöht die Gefahr das man ausversehen irgendwann einmal doch direkt auf die dort definierten Objekte zugreift.

Da der `release()`-Aufruf wichtig ist um die externen Ressourcen der Kamera wieder freizugeben würde ich mit einem ``try``/``finally`` sicherstellen dass das auch tatsächlich in jedem Fall passieren wird.

Das `Label`-Objekt bekommt gar kein `parent` übergeben.

Das `capture`-Flag ist ”fragil”. Der Wert der in der `__init__()` zugewiesen wird stimmt nur wenn man dann auch tatsächlich `run()` von *aussen* aufruft. Macht man das nicht, stimmt der interne Zustand dieses Objekts nicht. Ich würde anstelle des Flags auch eher die ID verwenden die man von `after()` bekommt und `None` für den Stop-Zustand.

Die Stelle wo `self.tk_image` definiert wird ist ein unlesbarer, grosser Code-Klumpen. Zumindest ich sehe da nicht was tatsächlich vor sich geht, welcher Aufruf wo anfängt und wo aufhört und welche und wieviele Argumente der jeweils hat.

Ich komme dann ungefähr auf so etwas:

Code: Alles auswählen

#! /usr/bin/env python
# -*- coding: utf-8
from __future__ import absolute_import, division, print_function
import Tkinter as tk

import cv2
from PIL import Image, ImageTk
 
CAPTURE_WIDTH = 640
CAPTURE_HEIGHT = 480    
DEFAULT_CAM_ID = -1


class CamUI(tk.Label):

    UPDATE_INTERVAL = 10
    PROPID_WIDTH = 3
    PROPID_HEIGHT = 4
   
    def __init__(self, parent, width, height, cam_id):
        tk.Label.__init__(self, parent)
        self.width = width
        self.height = height
        self.after_id = None
        self.image = None
        self.cam = cv2.VideoCapture(cam_id)
       
    def start_stop(self):
        if self.after_id is None:
            self.run()
        else:
            self.after_cancel(self.after_id)
            self.after_id = None
       
    def run(self):
        if self.cam.isOpened():
            self.image = ImageTk.PhotoImage(
                image=self.resize_image(
                    Image.fromstring(
                        'L',
                        (
                            int(self.cam.get(self.PROPID_WIDTH)),
                            int(self.cam.get(self.PROPID_HEIGHT))
                        ),
                        cv2.blur(
                            cv2.adaptiveThreshold(
                                cv2.cvtColor(
                                    self.cam.read()[1], cv2.COLOR_BGR2GRAY
                                ),
                                255,
                                cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                cv2.THRESH_BINARY,
                                63,
                                5,
                            ),
                            (5, 5)),
                        'raw',
                    )
                )
            )
            self.config(image=self.image)
        else:
            self.config(width=20, height=5, text='NO CAM', font='Arial 20')

        self.after_id = self.after(self.UPDATE_INTERVAL, self.run)
   
    def resize_image(self, img):
        img_width, img_height = img.size
        if self.height >= self.width:
            img_height = img_height * self.width // img_width
            img_width = self.width
        else:
            img_width = img_width * self.height // img_height
            img_height = self.height
        return img.resize((img_width, img_height))
       
    def release(self):
        self.cam.release()


def main():
    root = tk.Tk()
    root.title('BINARY-CAM')
    try:
        cam_ui = CamUI(root, CAPTURE_WIDTH, CAPTURE_HEIGHT, DEFAULT_CAM_ID)
        cam_ui.pack()
        cam_ui.run()
        tk.Button(text='Start/Stop', command=cam_ui.start_stop).pack()
        root.mainloop()
    finally:
        cam_ui.release()


if __name__ == '__main__':
    main()
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo Black Jack,
danke für deine konstruktive Kritik. Ich hatte gedacht alle Konstanten aus dem Code - muss ich mich auch nicht mehr mit "Namensdichtung" beschäftigen. PROPID_HEIGHT u. PROPID_WIDTH sind eigentlich auch nicht veränderbar, da sie Indizes für tatsächliche Höhe und Weite sind.
Der Codeklumpen hat mir das Gefühl von Geheimwissen gegeben :-). Wenn etwas nach tausend Versuchen funktioniert hat, habe ich es reinkopiert und war echt stolz.

"from __future__ import absolute_import, division, print_function" -->für was benötige ich diesen import ?

Gruß Frank
BlackJack

@kaytec: Die `PROPID_*`\s sind zwar nicht veränderbar aber das sind ”magische” Zahlen von denen man sonst nicht weiss was sie bedeuten.

Die `__future__`-Importe mache ich mittlerweile grundsätzlich damit sich Python 2.6/2.7 etwas mehr wie Python 3 verhält. Für den Fall das ich irgendwann doch mal portieren sollte. In Python 3.x haben die dann einfach keinen Effekt mehr.
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo BlackJack,
sind bei dem Import von division noch zwei Geteilzeichen notwendig?

Gruß Frank
BlackJack

@kaytec: Ja, dann erst recht, denn ein einfaches ``/`` hat durch den Import von `division` zur Folge das *immer* eine Gleitkommazahl bei der Operation heraus kommt.
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo BlackJack,

läuft bei mir nur so

Code: Alles auswählen

#! /usr/bin/env python
# -*- coding: utf-8
from __future__ import absolute_import, division, print_function
import Tkinter as tk
 
import cv2
from PIL import Image, ImageTk
 
CAPTURE_WIDTH = 640
CAPTURE_HEIGHT = 480    
DEFAULT_CAM_ID = -1
 
 
class CamUI(tk.Label):
 
    UPDATE_INTERVAL = 10
    PROPID_WIDTH = 3
    PROPID_HEIGHT = 4
   
    def __init__(self, parent, width, height, cam_id):
        tk.Label.__init__(self, parent)
        self.parent = parent
        self.width = width
        self.height = height
        self.after_id = None
        self.image = None
        self.cam = cv2.VideoCapture(cam_id)
       
    def start_stop(self):
        if self.after_id is None:
            self.run()
        else:
            self.after_cancel(self.after_id)
            self.after_id = None
       
    def run(self):
        if self.cam.isOpened():
            self.image = ImageTk.PhotoImage(
                image=self.resize_image(
                    Image.fromstring(
                        'L',
                        (
                            int(self.cam.get(self.PROPID_WIDTH)),
                            int(self.cam.get(self.PROPID_HEIGHT))
                        ),
                        cv2.blur(
                            cv2.adaptiveThreshold(
                                cv2.cvtColor(
                                    self.cam.read()[1], cv2.COLOR_BGR2GRAY
                                ),
                                255,
                                cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                cv2.THRESH_BINARY,
                                63,
                                5,
                            ),
                            (5, 5)),
                        'raw',
                    )
                )
            )
            self.config(image=self.image)
        else:
            self.config(width=20, height=5, text='NO CAM', font='Arial 20')
 
        self.after_id = self.after(self.UPDATE_INTERVAL, self.run)
   
    def resize_image(self, img):
        img_width, img_height = img.size
        if self.height >= self.width:
            img_height = img_height * self.width // img_width
            img_width = self.width
        else:
            img_width = img_width * self.height // img_height
            img_height = self.height
        return img.resize((img_width, img_height))
       
    def release(self):
        self.cam.release()
        self.parent.destroy()
 
def main():
    root = tk.Tk()
    root.title('BINARY-CAM')
    cam_ui = CamUI(root, CAPTURE_WIDTH, CAPTURE_HEIGHT, DEFAULT_CAM_ID)
    cam_ui.pack()
    tk.Button(text='Start/Stop', command=cam_ui.start_stop).pack()
    cam_ui.run()
    root.protocol("WM_DELETE_WINDOW", cam_ui.release)
    root.mainloop()
    
if __name__ == '__main__':
    main()
Gruß
Benutzeravatar
kaytec
User
Beiträge: 608
Registriert: Dienstag 13. Februar 2007, 21:57

Hallo,
jetzt ist es eine Warhol-Cam.

Code: Alles auswählen

#! /usr/bin/env python
# -*- coding: utf-8
from __future__ import absolute_import, division, print_function
import Tkinter as tk
 
import cv2
from PIL import Image, ImageTk, ImageOps
 
PICTURE_COLORS_2_3 = ((("#F7FF00", "#2E64FE"), 
                       ("#000000", "#00FF40"), 
                       ("#CD00FF", "#FF8000")), 
                      (("#FF0000", "#B700FF"), 
                       ("#FF00AF", "#FFFF00"), 
                       ("#31B404", "#FE2E2E")))
                       
CAPTURE_WIDTH = 640
CAPTURE_HEIGHT = 350
DEFAULT_CAM_ID = -1
 
class CamUI(tk.Label):
 
    UPDATE_INTERVAL = 10
    PROPID_WIDTH = 3
    PROPID_HEIGHT = 4
                        
    def __init__(self, parent, width, height, cam_id, picture_colors):
        tk.Label.__init__(self, parent)
        self.parent = parent
        self.width = width
        self.height = height
        self.after_id = None
        self.image = None
        self.picture_colors = picture_colors
        self.cam = cv2.VideoCapture(cam_id)
       
    def start_stop(self):
        if self.after_id is None:
            self.run()
        else:
            self.after_cancel(self.after_id)
            self.after_id = None
       
    def run(self):
        if self.cam.isOpened():
            image = Image.fromstring(
                    'L',
                    (
                        int(self.cam.get(self.PROPID_WIDTH)),
                        int(self.cam.get(self.PROPID_HEIGHT))
                    ),
                    cv2.blur(
                        cv2.adaptiveThreshold(
                            cv2.cvtColor(
                                self.cam.read()[1], cv2.COLOR_BGR2GRAY
                            ),
                            255,
                            cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                            cv2.THRESH_BINARY,
                            63,
                            5,
                        ),
                        (5, 5)),
                    'raw',
                )
                    
            self.image = ImageTk.PhotoImage(self.multiply_image(image))
            self.config(image=self.image)
        else:
            self.config(width=20, height=5, text='NO CAM', font='Arial 20')
            
        self.after_id = self.after(self.UPDATE_INTERVAL, self.run)
        
    def multiply_image(self, image):
        img_width, img_height = image.size
        warhol_img_width = img_width * len(self.picture_colors[0])
        warhol_img_height = img_height * len(self.picture_colors)
        warhol_image = Image.new("RGB", (warhol_img_width, warhol_img_height))
        for x, row in enumerate(self.picture_colors):
            for y, colors in enumerate(row):
                warhol_image.paste(ImageOps.colorize(image, colors[0],
                    colors[1]), (img_width * y, img_height * x))
        return self.resize_image(warhol_image)
   
    def resize_image(self, img):
        img_width, img_height = img.size
        if self.height >= self.width:
            img_height = img_height * self.width // img_width
            img_width = self.width
        else:
            img_width = img_width * self.height // img_height
            img_height = self.height
        return img.resize((img_width, img_height))
       
    def release(self):
        self.cam.release()
        self.parent.destroy()
 
def main():
    root = tk.Tk()
    root.title('WARHOL-CAM')
    cam_ui = CamUI(root, CAPTURE_WIDTH, CAPTURE_HEIGHT, DEFAULT_CAM_ID, 
        PICTURE_COLORS_2_3)
    cam_ui.pack()
    tk.Button(text='Start/Stop', command=cam_ui.start_stop).pack()
    cam_ui.run()
    root.protocol("WM_DELETE_WINDOW", cam_ui.release)
    root.mainloop()
    
if __name__ == '__main__':
    main()
Gruß Frank
Antworten