Tôi đã cố gắng tạo một cửa sổ cấp cao nhất để phát trực tuyến video dạng webcam và thực hiện quét QR. Tôi nhận mã quét QR này từ SO và another code chỉ cập nhật hình ảnh từ webcam thay vì phát trực tuyến video trên nhãn tkinter.python: tkinter để hiển thị video từ webcam và thực hiện quét QR
và tôi đã cố kết hợp cả hai cửa sổ này để cửa sổ to hơn với nhãn cập nhật hình ảnh từ webcam và nút đóng để đóng cửa sổ toplevel. Và trong khi nó truyền hình ảnh, nó có thể quét mã QR và nếu quét thành công, webcam và cửa sổ toplevel bị đóng.
đây là những gì tôi đã thử.
import cv2
import cv2.cv as cv
import numpy
import zbar
import time
import threading
import Tkinter
from PIL import Image, ImageTk
class BarCodeScanner(threading.Thread, Tkinter.Toplevel):
def __init__(self):
# i made this as a global variable so i can access this image
# outside ie,. beyond the thread to update the image on to the tkinter window
global imgtk
imgtk = None
threading.Thread.__init__(self)
self.WINDOW_NAME = 'Camera'
self.CV_SYSTEM_CACHE_CNT = 5 # Cv has 5-frame cache
self.LOOP_INTERVAL_TIME = 0.2
cv.NamedWindow(self.WINDOW_NAME, cv.CV_WINDOW_NORMAL)
self.cam = cv2.VideoCapture(-1)
self.confirm = 0
def scan(self, aframe):
imgray = cv2.cvtColor(aframe, cv2.COLOR_BGR2GRAY)
# to show coloured image, as from the other code mentioned in the other code
imgcol = cv2.cvtColor(aframe, cv2.COLOR_BGR2RGBA)
imgcol_array = Image.fromarray(imgcol)
imgtk = ImageTk.PhotoImage(image=imgcol_array)
raw = str(imgray.data)
scanner = zbar.ImageScanner()
scanner.parse_config('enable')
width = int(self.cam.get(cv.CV_CAP_PROP_FRAME_WIDTH))
height = int(self.cam.get(cv.CV_CAP_PROP_FRAME_HEIGHT))
imageZbar = zbar.Image(width, height,'Y800', raw)
scanner.scan(imageZbar)
for symbol in imageZbar:
print 'decoded', symbol.type, 'symbol', '"%s"' % symbol.data
return symbol.data
def run(self):
self.datalst = []
print 'BarCodeScanner run', time.time()
while True:
for i in range(0,self.CV_SYSTEM_CACHE_CNT):
self.cam.read()
img = self.cam.read()
self.data = self.scan(img[1])
cv2.imshow(self.WINDOW_NAME, img[1])
cv.WaitKey(1)
time.sleep(self.LOOP_INTERVAL_TIME)
if self.data:
self.datalst.append(self.data)
# i have added this section so that it waits for scan
# if a scan is made it and if gets same value after 2 scans
# it has to stop webcam
if len(self.datalst) == 2 and len(set(self.datalst)) <= 1:
# I want to close the webcam before closing the toplevel window
#self.cam.release()
#cv2.destroyAllWindows()
break
self.cam.release()
def Video_Window():
video_window = Tkinter.Toplevel()
video_window.title('QR Scan !!')
img_label = Tkinter.Label(video_window)
img_label.pack(side=Tkinter.TOP)
close_button = Tkinter.Button(video_window, text='close', command = video_window.destroy)
close_button.pack(side=Tkinter.TOP)
def update_frame():
global imgtk
img_label.configure(image=imgtk)
img_label.after(10,update_frame)
update_frame()
def main():
root = Tkinter.Tk()
button_scanQr = Tkinter.Button(root, text='QR Scan', command=start_scan)
button_scanQr.pack()
root.mainloop()
def start_scan():
scanner = BarCodeScanner()
scanner.start()
Video_Window()
#scanner.join()
main()
Vấn đề là,
- Tôi thực sự muốn để hiển thị video trên cửa sổ mục cấp đầu, không phải là cửa sổ OpenCV
- đồng thời làm một quét QR, nếu một đọc là thành công, cửa sổ Toplevel sẽ đóng mà không đột ngột đóng webcam (vì, khi tôi cố gắng sử dụng
self.cam.release()
hoặccv2.destroyAllWindows()
đèn webcam của mình hoặc bật ngay cả khi tôi buộc chấm dứt chương trình biên dịch).
Bây giờ, những gì tôi nhận được là một cửa sổ riêng được tạo bởi OpenCV để truyền video bên trong. Nhưng tôi không muốn cửa sổ đó, thay vào đó tôi muốn video được hiển thị trên cửa sổ tokivel của tkinter. cũng có khi đọc thành công, webcam sẽ dừng lại ở hình ảnh cuối cùng mà nó đọc.
tôi đã cố gắng để loại bỏ các dòng đó là chịu trách nhiệm cho cửa sổ OpenCV, bên trong lớp run
phương pháp BarcodeScanner
cv2.imshow(self.WINDOW_NAME, img[1])
nó vẫn xuất hiện với một cửa sổ khác nhau với không có đầu ra, và nếu tôi cố gắng để đóng mà cửa sổ, nó tạo ra một cái khác tương tự và đệ quy.
CẬP NHẬT:
Như tôi nhận thấy tôi thực hiện một số sai lầm ngớ ngẩn mà không hiểu biết về một số dòng trong cv2
, tôi thực hiện một số thay đổi về mã bằng cách thêm mã cửa sổ mục cấp đầu vào phương pháp run
của lớp (im không chắc chắn nếu đây là một cách đúng).
import cv2
import cv2.cv as cv
import numpy
import zbar
import time
import threading
import Tkinter
from multiprocessing import Process, Queue
from Queue import Empty
from PIL import Image, ImageTk
class BarCodeScanner(threading.Thread, Tkinter.Toplevel):
def __init__(self):
threading.Thread.__init__(self)
#self.WINDOW_NAME = 'Camera'
self.CV_SYSTEM_CACHE_CNT = 5 # Cv has 5-frame cache
self.LOOP_INTERVAL_TIME = 0.2
#cv.NamedWindow(self.WINDOW_NAME, cv.CV_WINDOW_NORMAL)
self.cam = cv2.VideoCapture(-1)
# check if webcam device is free
self.proceede = self.cam.isOpened()
if not self.proceede:
return
self.confirm = 0
def scan(self, aframe):
imgray = cv2.cvtColor(aframe, cv2.COLOR_BGR2GRAY)
raw = str(imgray.data)
scanner = zbar.ImageScanner()
scanner.parse_config('enable')
width = int(self.cam.get(cv.CV_CAP_PROP_FRAME_WIDTH))
height = int(self.cam.get(cv.CV_CAP_PROP_FRAME_HEIGHT))
imageZbar = zbar.Image(width, height,'Y800', raw)
scanner.scan(imageZbar)
for symbol in imageZbar:
print 'decoded', symbol.type, 'symbol', '"%s"' % symbol.data
return symbol.data
def run(self):
if not self.proceede:
return
def show_frame():
_, img = self.cam.read()
img = cv2.flip(img,1)
cv2image = cv2.cvtColor(img, cv2.COLOR_BGR2RGBA)
img = Image.fromarray(cv2image)
imgtk = ImageTk.PhotoImage(image=img)
img_label.imgtk = imgtk
img_label.configure(image=imgtk)
video_window.after(250, show_frame)
def destroy_video_window():
self.cam.release()
video_window.destroy()
# Toplevel GUI
video_window = Tkinter.Toplevel()
video_window.title('QR Scan !!')
img_label = Tkinter.Label(video_window)
img_label.pack(side=Tkinter.TOP)
close_button = Tkinter.Button(video_window, text='close', command = destroy_video_window)
close_button.pack(side=Tkinter.RIGHT)
show_frame()
self.datalst = []
print 'BarCodeScanner run', time.time()
while True:
for i in range(0,self.CV_SYSTEM_CACHE_CNT):
self.cam.read()
img = self.cam.read()
self.data = self.scan(img[1])
time.sleep(self.LOOP_INTERVAL_TIME)
if self.data:
self.datalst.append(self.data)
if len(self.datalst) == 2 and len(set(self.datalst)) <= 1:
video_window.destroy()
break
self.cam.release()
def main():
root = Tkinter.Tk()
button_scanQr = Tkinter.Button(root, text='QR Scan', command=scaner)
button_scanQr.pack()
root.mainloop()
def scaner():
scanner = BarCodeScanner()
scanner.start()
main()
bây giờ, tôi có thể lấy hình ảnh trên cửa sổ Toplevel, Nhưng tôi không biết cách đóng webcam.
điều kiện 1: khi tôi hiển thị mã QR để quét, nó đọc thành công và thoát webcam mà không gặp bất kỳ lỗi nào.
điều kiện 2: khi tôi nhấp vào nút Close trên cửa sổ mục cấp đầu (nói nếu người dùng không muốn làm bất cứ quét và chỉ muốn đóng webcam) tôi nhận được lỗi nói
libv4l2: error dequeuing buf: Invalid argument
VIDIOC_DQBUF: Invalid argument
select: Bad file descriptor
VIDIOC_DQBUF: Bad file descriptor
select: Bad file descriptor
VIDIOC_DQBUF: Bad file descriptor
Segmentation fault (core dumped)
Tôi đang viết ứng dụng này cho Linux
, Mac
và Windows
máy. Làm thế nào tôi có thể đóng hoặc chấm dứt webcam một cách an toàn.
có thể trùng lặp của [Sử dụng OpenCV với Tkinter] (http://stackoverflow.com/questions/32342935/using-opencv-with-tkinter) – tfv
@tfv,. nó trông tương tự, nhưng không giống nhau. ở đó video được hiển thị trên cửa sổ bằng cách sử dụng chức năng, nhưng ở đây kể từ khi im thực hiện quét QR đồng thời cùng với hiển thị video, kết hợp chúng bằng cách sử dụng lớp và luồng làm cho khó khăn hơn nhiều – arvindh