1

I am trying to display 'latest' captured image for my project here in a label named captureLabel after I press the capture button as seen in the image below

screenshot

Appreciate the help..

Here is my full main.py

import tkinter as tk
import tkinter.font as tkFont
import cv2
from PIL import ImageTk, Image
import os
import time
import uuid

#setting title
gui = tk.Tk(className='yolov5')

#setting window size
width=1024
height=768
screenwidth = gui.winfo_screenwidth()
screenheight = gui.winfo_screenheight()
alignstr = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
gui.geometry(alignstr)
gui.resizable(width=False, height=False)

cap = cv2.VideoCapture(0)
IMAGES_PATH_CAPTURED = os.path.join('Captured')
label = 'image'

#functions
def captureButton_command():
    textLabel['text'] = "Capture button clicked.."
    ret, frame = cap.read()
    imgname = os.path.join(IMAGES_PATH_CAPTURED, label+'.'+str(uuid.uuid1())+'.jpg')
    cv2.imwrite(imgname, frame)
    time.sleep(1)
    print("Image saved to {}".format(IMAGES_PATH_CAPTURED))
    
def exitButton_command():
    gui.destroy()
    
def video_stream():
    _, frame = cap.read()
    cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
    img = Image.fromarray(cv2image)
    imgtk = ImageTk.PhotoImage(image=img)
    cameraLabel.imgtk = imgtk
    cameraLabel.configure(image=imgtk)
    cameraLabel.after(1, video_stream) 

#Capture Button
captureButton=tk.Button(gui)
captureButton["bg"] = "#efefef"
ft = tkFont.Font(family='Times',size=15)
captureButton["font"] = ft
captureButton["fg"] = "#000000"
captureButton["justify"] = "center"
captureButton["text"] = "Capture"
captureButton.place(x=10,y=220,width=150,height=50)
captureButton["command"] = captureButton_command

#Exit Button
exitButton=tk.Button(gui)
exitButton["bg"] = "#efefef"
ft = tkFont.Font(family='Times',size=15)
exitButton["font"] = ft
exitButton["fg"] = "#000000"
exitButton["justify"] = "center"
exitButton["text"] = "Exit"
exitButton.place(x=170,y=220,width=150,height=50)
exitButton["command"] = exitButton_command

#Message on top
textLabel=tk.Label(gui)
ft = tkFont.Font(family='Times',size=18)
textLabel["font"] = ft
textLabel["fg"] = "#333333"
textLabel["justify"] = "left"
textLabel["relief"] = "sunken"
textLabel["text"] = "Press capture to capture image"
textLabel.place(x=20,y=10,width=800,height=95)

#Camera Feed Label
cameraLabel=tk.Label(gui)
cameraLabel["text"] = "Camera Feed"
cameraLabel["borderwidth"] = "2px"
cameraLabel["relief"] = "solid"
cameraLabel.place(x=10,y=280,width=640,height=480)

#Captured Images Label
captureLabel = tk.Label(gui)
captureLabel["borderwidth"] = "2px"
captureLabel["relief"] = "solid"
captureLabel.place(x=720,y=110,width=300,height=300)

#Detected Images Label
detectedLabel = tk.Label(gui)
detectedLabel["borderwidth"] = "2px"
detectedLabel["relief"] = "solid"
detectedLabel.place(x=720,y=440,width=300,height=300)


            
#end
video_stream()
gui.mainloop()

I already tried the link text wherein it will save the image first in a folder and then reads the images but it seems to be showing only the images that are saved BEFORE running the application again and not displaying the latest images that I captured.

I was only expecting to display one image in the label provided with the border and displaying/replacing the result once I click the capture button.

j_4321
  • 15,431
  • 3
  • 34
  • 61

2 Answers2

0

The code sample seems to work fine.
For showing the captured frame in captureLabel, we may use the same code that is used in video_stream(), but using captureLabel instead of cameraLabel.

Example for updated: def captureButton_command():

def captureButton_command():
    textLabel['text'] = "Capture button clicked.."
    ret, frame = cap.read()
    if ret:
        imgname = os.path.join(IMAGES_PATH_CAPTURED, label+'.'+str(uuid.uuid1())+'.jpg')
        cv2.imwrite(imgname, frame)
        #time.sleep(1)
        print("Image saved to {}".format(IMAGES_PATH_CAPTURED))
        cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
        cv2image = cv2.resize(cv2image, [captureLabel.winfo_width(), captureLabel.winfo_height()], cv2.INTER_LANCZOS4)  # Resize the captured frame to the size of the label.
        img = Image.fromarray(cv2image)
        imgtk = ImageTk.PhotoImage(image=img)
        captureLabel.imgtk = imgtk
        captureLabel.configure(image=imgtk)

Using cv2.resize is optional.


Make sure you have a folder named Captured in the "working folder".
The images are saved fine using names as:
image.ed62ba02-f815-11ed-97a4-c86000dd9c4d.jpg
image.e75947ae-f815-11ed-8e4b-c86000dd9c4d.jpg
...


Note:
It is recommended to verify that the value of ret is true after ret, frame = cap.read()


Updated code sample:

import tkinter as tk
import tkinter.font as tkFont
import cv2
from PIL import ImageTk, Image
import os
import time
import uuid

#setting title
gui = tk.Tk(className='yolov5')

#setting window size
width=1024
height=768
screenwidth = gui.winfo_screenwidth()
screenheight = gui.winfo_screenheight()
alignstr = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
gui.geometry(alignstr)
gui.resizable(width=False, height=False)

cap = cv2.VideoCapture(0)
IMAGES_PATH_CAPTURED = os.path.join('Captured')
label = 'image'

#functions
def captureButton_command():
    textLabel['text'] = "Capture button clicked.."
    ret, frame = cap.read()
    if ret:
        imgname = os.path.join(IMAGES_PATH_CAPTURED, label+'.'+str(uuid.uuid1())+'.jpg')
        cv2.imwrite(imgname, frame)
        #time.sleep(1)
        print("Image saved to {}".format(IMAGES_PATH_CAPTURED))
        cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
        cv2image = cv2.resize(cv2image, [captureLabel.winfo_width(), captureLabel.winfo_height()], cv2.INTER_LANCZOS4)  # Resize the captured frame to the size of the label.
        img = Image.fromarray(cv2image)
        imgtk = ImageTk.PhotoImage(image=img)
        captureLabel.imgtk = imgtk
        captureLabel.configure(image=imgtk)

    
def exitButton_command():
    gui.destroy()
    
def video_stream():
    ret, frame = cap.read()
    if ret:
        cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
        img = Image.fromarray(cv2image)
        imgtk = ImageTk.PhotoImage(image=img)
        cameraLabel.imgtk = imgtk
        cameraLabel.configure(image=imgtk)
        cameraLabel.after(1, video_stream)

       

#Capture Button
captureButton=tk.Button(gui)
captureButton["bg"] = "#efefef"
ft = tkFont.Font(family='Times',size=15)
captureButton["font"] = ft
captureButton["fg"] = "#000000"
captureButton["justify"] = "center"
captureButton["text"] = "Capture"
captureButton.place(x=10,y=220,width=150,height=50)
captureButton["command"] = captureButton_command

#Exit Button
exitButton=tk.Button(gui)
exitButton["bg"] = "#efefef"
ft = tkFont.Font(family='Times',size=15)
exitButton["font"] = ft
exitButton["fg"] = "#000000"
exitButton["justify"] = "center"
exitButton["text"] = "Exit"
exitButton.place(x=170,y=220,width=150,height=50)
exitButton["command"] = exitButton_command

#Message on top
textLabel=tk.Label(gui)
ft = tkFont.Font(family='Times',size=18)
textLabel["font"] = ft
textLabel["fg"] = "#333333"
textLabel["justify"] = "left"
textLabel["relief"] = "sunken"
textLabel["text"] = "Press capture to capture image"
textLabel.place(x=20,y=10,width=800,height=95)

#Camera Feed Label
cameraLabel=tk.Label(gui)
cameraLabel["text"] = "Camera Feed"
cameraLabel["borderwidth"] = "2px"
cameraLabel["relief"] = "solid"
cameraLabel.place(x=10,y=280,width=640,height=480)

#Captured Images Label
captureLabel = tk.Label(gui)
captureLabel["borderwidth"] = "2px"
captureLabel["relief"] = "solid"
captureLabel.place(x=720,y=110,width=300,height=300)

#Detected Images Label
detectedLabel = tk.Label(gui)
detectedLabel["borderwidth"] = "2px"
detectedLabel["relief"] = "solid"
detectedLabel.place(x=720,y=440,width=300,height=300)


            
#end
video_stream()
gui.mainloop()

Sample output after pressing Capture button:
enter image description here

Rotem
  • 30,366
  • 4
  • 32
  • 65
0

Since you have already been reading image from the camera every 1ms, you can use this image as the captured image instead of reading one from the camera again:

def captureButton_command():
    textLabel['text'] = "Capture button clicked.."
    # get the saved image
    img = cameraLabel.img
    # save the image if required
    img.save(os.path.join(IMAGES_PATH_CAPTURED, label+'.'+str(uuid.uuid1())+'.png'))
    print("Image saved to {}".format(IMAGES_PATH_CAPTURED))
    # resize the image to fit the size of captureLabel
    img.thumbnail((300, 300))
    # show the image in captureLabel
    captureLabel.image = ImageTk.PhotoImage(img)
    captureLabel.config(image=captureLabel.image)

...

def video_stream():
    _, frame = cap.read()
    cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
    img = Image.fromarray(cv2image)
    imgtk = ImageTk.PhotoImage(image=img)
    cameraLabel.img = img      ### save the image
    cameraLabel.imgtk = imgtk
    cameraLabel.configure(image=imgtk)
    cameraLabel.after(1, video_stream)
acw1668
  • 40,144
  • 5
  • 22
  • 34