i need to to add webcam window inside tkinter UI , what i actually need when the user pressed on start the webcam must appear in white box as it shown in the picture and the code down below also ive made a class that opens the webacam window and recognize faces
canvans=tkinter.Canvas(pro, width =900, height = 700, borderwidth=10, relief="solid",bg="#ffffff",
highlightbackground="#0E6655")
canvans.place(x=300,y=100)
pro.mainloop()
x=Gui()
In comments you get link to example but I made some changes
check if read() gives any frame
use cap.release() after using webcam
(PEP8) import * is not preferred
(PEP8) organize code - put all functions after import
import tkinter as tk # PEP8: `import *` is not preferred
from PIL import Image, ImageTk
import cv2
# --- functions --- # PEP8: all functions after imports
def show_frame():
# get frame
ret, frame = cap.read()
if ret:
# cv2 uses `BGR` but `GUI` needs `RGB`
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# convert to PIL image
img = Image.fromarray(frame)
# convert to Tkinter image
photo = ImageTk.PhotoImage(image=img)
# solution for bug in `PhotoImage`
label.photo = photo
# replace image in label
label.configure(image=photo)
# run again after 20ms (0.02s)
root.after(20, show_frame)
# --- main ---
cap = cv2.VideoCapture(0)
root = tk.Tk()
# create a Label to display frames
label = tk.Label(root)
label.pack(fill='both', expand=True) # to resize label when resize window
# start function which shows frame
show_frame()
root.mainloop()
cap.release()
BTW:
PEP 8 -- Style Guide for Python Code
Tkinter: Why Label doesn't display image? Bug with Garbage Collector in PhotoImage.
EDIT:
The same for Canvas
It uses image's ID to replace PhotoImage on Canvas
import tkinter as tk # PEP8: `import *` is not preferred
from PIL import Image, ImageTk
import cv2
# --- functions ---
def show_frame():
global image_id # inform function to assign new value to global variable instead of local variable
# get frame
ret, frame = cap.read()
if ret:
# cv2 uses `BGR` but `GUI` needs `RGB
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# convert to PIL image
img = Image.fromarray(frame)
# convert to Tkinter image
photo = ImageTk.PhotoImage(image=img)
# solution for bug in `PhotoImage`
canvas.photo = photo
# check if image already exists
if image_id:
# replace image in PhotoImage on canvas
canvas.itemconfig(image_id, image=photo)
else:
# create first image on canvas and keep its ID
image_id = canvas.create_image((0,0), image=photo, anchor='nw')
# resize canvas
canvas.configure(width=photo.width(), height=photo.height())
# run again after 20ms (0.02s)
root.after(20, show_frame)
# --- main ---
image_id = None # default value at start (to create global variable)
cap = cv2.VideoCapture(0)
root = tk.Tk()
# create a Label to display frames
canvas = tk.Canvas(root)
canvas.pack(fill='both', expand=True)
# start function which shows frame
show_frame()
root.mainloop()
cap.release()
Related
I am working on a python messaging application using tkinter and i need a loading screen animation but none of them where fitting with my purpose so i Tried to rotate a image in python continusly which will look like a animation.
This is the image i want to ratate for some time in tkinter
The application code
i only need a simple tkinter window with the rotating screen
I tried google and i got this code to rote a image
from PIL import Image # Import Image class from the library.
image = Image.open("file.jpg") # Load the image.
rotated_image = image.rotate(180) # Rotate the image by 180 degrees.
rotated_image.save("file_rotated.jpg")
So i tried using this code like this:-
from tkinter import *
from PIL import ImageTk, Image
import os
root = Tk()
c = Canvas(root, width=700, height=700)
c.pack()
while True:
img = ImageTk.PhotoImage(Image.open(r"Loading_Icon.png"))
c.create_image(100, 100, image=img, anchor=NW)
image = Image.open(Loading_Icon.png") # Load the image.
rotated_image = image.rotate(30)
os.remove("Loading_Icon.png")
rotated_image.save("Loding_Icon.png")
root.mainloop()
c.delete("all")
Look at this:
from PIL import Image, ImageTk
import tkinter as tk
# Load the original image
pil_img = Image.open("pawn.black.png")
def loading_loop(i=0):
global tk_img
print(f"Loop {i}")
# If the prgram has loaded, stop the loop
if i == 13: # You can replace this with your loading condition
return
# Rotate the original image
rotated_pil_img = pil_img.rotate(30*i)
tk_img = ImageTk.PhotoImage(rotated_pil_img)
# put the rotated image inside the canvas
canvas.delete("all")
canvas.create_image(0, 0, image=tk_img, anchor="nw")
# Call `loading_loop(i+1)` after 200 milliseconds
root.after(200, loading_loop, i+1)
root = tk.Tk()
canvas = tk.Canvas(root)
canvas.pack()
# start the tkinter loop
loading_loop()
root.mainloop()
It loads the original image then it start a tkinter loop which runs loading_loop every 200 milliseconds. Inside loading_loop, I rotate the image 30*i degrees, where i is the iteration number. Then I put the image inside the canvas.
Notice how I only call .mainloop() once and there is no while True loop. Those are best practises for when using tkinter.
It's best to create only 1 image inside the canvas and just reconfigure it but that will make the code longer.
I am trying to make a GUI-based face recognition program with tkinter and opencv. I have used the function cv2.VideoCapture() before, but usually NOT inside a function and it worked successfully.
This time, though, I wanted to use it inside a function, but the program just does not run. I got no errors in the terminal, and the window just froze.
Here is my code (I haven't yet added the face recognition functionality)
import tkinter as tk
from PIL import Image, ImageTk
root = tk.Tk()
root.configure(bg='#3d3d3d')
f1 = tk.LabelFrame(root, bg='#3d3d3d')
f1.place(relx=0.5, rely=0.53, anchor=tk.CENTER)
feed = tk.Label(f1)
feed.pack()
cap = cv2.VideoCapture(0)
def capture():
while cap.isOpened():
img = cap.read()[1]
img = cv2.flip(img, 1)
img1 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # changing color to RGB
img = ImageTk.PhotoImage(Image.fromarray(img1))
feed['image'] = img # putting the webcam feed in the 'feed' LabelFrame
capture()
root.mainloop()
I tried to input values 0, 1, -1 for the VideoCapture() function, but the problem persisted
Note that this is not my full code and I have just included the important parts. I am asking this question because I want to implement this functionality on a Toplevel() window which is opened by clicking a button. The code for the Toplevel() window is indside a function.
Thanks in advance!
There are mainly two issues in your code:
using while loop which will block root.mainloop() from executing. Use after() instead.
image created inside a function will be garbage collected if its reference is not saved
Below is a modified code to fix the above issues:
import tkinter as tk
from PIL import Image, ImageTk
import cv2
root = tk.Tk()
root.configure(bg='#3d3d3d')
root.geometry('800x600')
f1 = tk.LabelFrame(root, bg='#3d3d3d')
f1.place(relx=0.5, rely=0.53, anchor=tk.CENTER)
feed = tk.Label(f1)
feed.pack()
cap = cv2.VideoCapture(0)
# used after() instead of while loop
def capture():
if cap.isOpened():
ret, img = cap.read()
if ret:
img = cv2.flip(img, 1)
img1 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # changing color to RGB
img = ImageTk.PhotoImage(Image.fromarray(img1))
feed['image'] = img # putting the webcam feed in the 'feed' LabelFrame
feed.image = img # save reference of the image
root.after(10, capture)
capture()
root.mainloop()
I am a beginner in python and learning about PIL and tkinter.
Now what I am trying is to edit a image and I am struggling from blur and rotate.
When I blur an image, I cannot get rid of it without rotating it. (I want to make a button to on/off blur)
And if I blur/rotate an image,
Another one doesn't work at the same time.
How can I solve this problem? here is my code
import tkinter as tk
from PIL import Image, ImageTk, ImageFilter
from tkinter import filedialog as fd
img=None
tk_img=None
angle=0
def open():
global img, tk_img
filename=fd.askopenfilename()
img=Image.open(filename)
tk_img=ImageTk.PhotoImage(img)
canvas.create_image(250,250,image=tk_img)
window.update()
def quit():
window.destroy()
def image_rotate():
global img,tk_img,angle
angle=angle+45
tk_img=ImageTk.PhotoImage(img.rotate(angle))
canvas.create_image(250,250,image=tk_img)
window.update()
def image_blur():
global img,tk_img
tk_img=ImageTk.PhotoImage(img.filter(ImageFilter.BLUR))
canvas.create_image(250,250,image=tk_img)
window.update()
window = tk.Tk() #윈도우 생성
canvas=tk.Canvas(window,width=500,height=500)
canvas.pack()
menubar = tk.Menu(window) #메뉴바 생성
filemenu = tk.Menu(menubar) #파일메뉴를 메뉴바에 달아줌
filemenu.add_command(label="picture", command=open)
filemenu.add_command(label="exit", command=quit)
menubar.add_cascade(label="파일", menu=filemenu)
imagemenu=tk.Menu(menubar)
imagemenu.add_command(label="rotate",command=image_rotate)
imagemenu.add_command(label="blur",command=image_blur)
menubar.add_cascade(label="movement", menu=imagemenu)
window.config(menu=menubar)
window.mainloop()
The reason is quite obvious, your img object as seen is only defined/updated in open(), so the image will always refer to the original image selected and not the new edited image, so to show the change store it in a new variable and then globalize it.
Also note that you are creating a new canvas image every time you call the function, which is not efficient, so make a single canvas image and then update it each time, inside the function using itemconfig() method.
def open():
global img, tk_img
filename = fd.askopenfilename()
img = Image.open(filename)
tk_img = ImageTk.PhotoImage(img)
canvas.itemconfig('img',image=tk_img) # Update image
def image_rotate():
global tk_img, angle, img
angle += 45 # More pythonic to always use += rather than a = a + 10
img = img.rotate(angle)
tk_img = ImageTk.PhotoImage(img)
canvas.itemconfig('img',image=tk_img) # Update image
angle -= 45
def image_blur():
global tk_img, img
img = img.filter(ImageFilter.BLUR)
tk_img = ImageTk.PhotoImage(img)
canvas.itemconfig('img',image=tk_img) # Update image
canvas = tk.Canvas(window,width=500,height=500)
canvas.create_image(250,250,tag='img') # Create initial canvas object
canvas.pack()
Also take a look at how I formatted your code to make it look more near, follow PEP 8 -- Style Guide for Python Code for more.
You can blur the image using opencv package
import cv2
img = cv2.imread('imagepath')
blurImg = cv2.blur(img,(10,10))
cv2.imshow('blurred image',blurImg)
cv2.waitKey(0)
cv2.destroyAllWindows()
Or u can check the documentation of opencv to blurr the image.
U can also rotate image using opencv
# importing cv2
import cv2
src = cv2.imread(path)
window_name = 'Image'
image = cv2.rotate(src, cv2.ROTATE_90_COUNTERCLOCKWISE)
# Displaying the image
cv2.imshow(window_name, image)
cv2.waitKey(0)
I am trying to continuously display and replace an image in a Tkinter interface taken from OpenCV's VideoCapture. However, I am getting the following error that I think is a result of improper formatting of the image numpy array:
TypeError: unhashable type: 'numpy.ndarray'
How can I reformat it to all it to display properly? Below is my code:
import tkinter as tk
import cv2
import numpy as np
from PIL import ImageTk, Image
main = tk.Tk()
main.title("Hole Pattern Recognition")
main.geometry("300x300")
frame = tk.Frame(main)
frame.pack()
def startScan():
global main, frame
#begins utilizing webcam for scan
cap = cv2.VideoCapture(0)
while(True):
ret,img = cap.read()
img = ImageTk.PhotoImage(img)
panel = tk.Label(main, image = img)
panel.pack(side = "bottom", fill = "both", expand = "yes")
ch = cv2.waitKey(1)
if ch == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
startButton = tk.Button(frame,
text="Start Scan",
fg="blue",
command=startScan)
startButton.pack(side=tk.TOP)
main.mainloop()
First you need to use PIL.Image.fromarray() to convert the captured image to format supported by tkinter.
Second better not use while loop in main thread as it will block the tkinter mainloop. Use after() instead.
import tkinter as tk
from PIL import Image, ImageTk
import cv2
cap = None
main = tk.Tk()
main.title('Hole Pattern Recognition')
#main.geometry('300x300')
frame = tk.Frame(main)
frame.pack()
def startScan():
global cap
def scan():
ret, img = cap.read()
if ret:
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = Image.fromarray(img)
tkimg = ImageTk.PhotoImage(img)
panel.config(image=tkimg)
panel.tkimg = tkimg # save a reference to the image to avoid garbage collection
panel.after(25, scan) # change 25 to other value to adjust FPS
if cap is None:
cap = cv2.VideoCapture(0)
scan() # start the capture loop
else:
print('capture already started')
startButton = tk.Button(frame, text='Start Scan', fg='blue', command=startScan)
startButton.pack()
panel = tk.Label(main)
panel.pack()
main.mainloop()
if cap:
cap.release()
I have a question, how do I integrate tkinter with cv2, I mean I can create a tkinter window filled with objects and I can open my laptop camera in a frame, but I want to integrate this "frame" from openCV cv2 into the tkinter window, next to the other objects, How do I do that?
I am using, Python 3.4, OpenCV, Numpy, Scipy, Windows 8
here is my code
import time, serial, sys, os, cv2
import tkinter as tk
from tkinter import *
from cv2 import *
from scipy import *
from numpy import array
from tkinter import ttk
try:
import Tkinter
import ttk
except ImportError:
import tkinter as Tkinter
import tkinter.ttk as ttk
mGui = Tk()
mGui.geometry('120x67+0+0')
mGui.configure(background="Sky Blue")
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
cv2.imshow("Camera's View", frame)
mGui.mainloop()
thanks
I understand now, if you too pull me up
I have to
create a frame
create a label inside of the frame
take the camera's view and convert it into an image
read the image and assigned to a variable
create a new property for the label (image)
assign the red image to the property
configure the label to display the image
so clear now, so obvious
here is the code (include previous libraries)
from PIL import Image, ImageTk (add library)
mGui = Tk()
mGui.geometry('600x600+0+0')
mGui.configure(background="Sky Blue")
fframe = Frame(mGui, width=500, height=500)
fframe.place(x=50, y=50)
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
v1 = Label(fframe, text="fchgvjvjhb")
v1.place(x=0, y=10)
v2 = Label(fframe, text="ajajajaja")
v2.place(x=300, y=10)
def dddd():
ret, frame = cap.read()
img = Image.fromarray(frame)
nimg = ImageTk.PhotoImage(image=img)
v1.n_img = nimg
v1.configure(image=nimg)
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
gimg = Image.fromarray(gray)
gnimg = ImageTk.PhotoImage(image=gimg)
v2.ng_img = gnimg
v2.configure(image=gnimg)
mGui.after(10, dddd)
dddd()
mGui.mainloop()