- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我一直在尝试创建一个 tkinter 顶级窗口,该窗口可以从网络摄像头流式传输视频并进行 QR 扫描。我从SO得到这个二维码和 another code它只是更新来自网络摄像头的图像,而不是在 tkinter 标签上流式传输视频。
我尝试将这两者结合起来,以便顶层窗口带有来自网络摄像头的标签更新图像和关闭按钮以关闭顶层窗口。在流式传输图像时,它可以扫描二维码,如果扫描成功,网络摄像头和顶层窗口将关闭。
这是我尝试过的。
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()
问题是,
self.cam.release()
或cv2.destroyAllWindows()
即使我强行终止程序编译,我的网络摄像头也会亮起或打开)。现在我得到的是一个由 OpenCV 创建的单独窗口,它在内部流式传输视频。但我不想要那个窗口,而是我希望视频显示在 tkinter 的顶层窗口上。此外,当读取成功时,网络摄像头会停留在它读取的最终图像上。
我试图删除负责 OpenCV 窗口的行,在 BarcodeScanner
类的 run
方法中
cv2.imshow(self.WINDOW_NAME, img[1])
它仍然显示一个没有输出的不同窗口,如果我试图关闭那个窗口,它会创建另一个类似的递归窗口。
更新:
因为我注意到我在不理解 cv2
中的某些行的情况下犯了一些愚蠢的错误,我通过将顶层窗口代码添加到 run
方法中对代码进行了一些更改类的(我不确定这是否是正确的方法)。
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()
现在,我可以在 Toplevel 窗口中获取图像,但我不知道如何关闭网络摄像头。
条件 1:当我显示要扫描的 QR 码时,它成功读取并退出网络摄像头,没有任何错误。
条件 2: 当我单击顶层窗口上的关闭按钮时(假设用户不想进行任何扫描而只想关闭网络摄像头)我收到错误提示
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)
我正在为 Linux
、Mac
和 Windows
机器编写此应用程序。如何安全地关闭或终止网络摄像头。
最佳答案
您的程序有两个线程,主线程和从相机读取帧的工作线程。单击关闭按钮时,它发生在主线程中。在self.cam.release()
之后对象 self.cam
可能处于无法使用的状态,并且当 self.cam
的方法时由工作线程调用,可能会有一些麻烦。也许执行 cv2.VideoCapture
是错误的,当发生这种情况时它应该抛出一些异常。
从主线程以外的其他线程访问 tkinter 小部件也可能会导致问题。
为了干净的程序终止,创建 threading.Event
的实例然后检查 event.is_set()
在工作线程中的某个时刻可以工作。例如
def destroy_video_window():
self.stop_event.set()
video_window.destroy()
然后在工作线程中
while True:
if self.stop_event.is_set():
break
for i in range(0, self.CV_SYSTEM_CACHE_CNT):
self.cam.read()
有几件事可以用其他方式完成,以下是代码的修改版本。它避免从主线程以外的其他线程调用 tkinter 方法,event_generate()
是工作线程调用的唯一 tkinter 方法。通过发出虚拟事件避免显式轮询,例如 <<ScannerQuit>>
, 被放置在 tkinter 事件队列中。
import cv2
import cv2.cv as cv
import zbar
import time
import threading
import Tkinter as tk
from PIL import Image, ImageTk
class Scanner(object):
def __init__(self, handler, *args, **kw):
self.thread = threading.Thread(target=self.run)
self.handler = handler
self.CV_SYSTEM_CACHE_CNT = 5 # Cv has 5-frame cache
self.LOOP_INTERVAL_TIME = 0.2
self.cam = cv2.VideoCapture(-1)
self.scanner = zbar.ImageScanner()
self.scanner.parse_config('enable')
self.cam_width = int(self.cam.get(cv.CV_CAP_PROP_FRAME_WIDTH))
self.cam_height = int(self.cam.get(cv.CV_CAP_PROP_FRAME_HEIGHT))
self.last_symbol = None
def start(self):
self.thread.start()
def scan(self, aframe):
imgray = cv2.cvtColor(aframe, cv2.COLOR_BGR2GRAY)
raw = str(imgray.data)
image_zbar = zbar.Image(self.cam_width, self.cam_height, 'Y800', raw)
self.scanner.scan(image_zbar)
for symbol in image_zbar:
return symbol.data
def run(self):
print 'starting scanner'
while True:
if self.handler.need_stop():
break
# explanation for this in
# http://stackoverflow.com/a/35283646/5781248
for i in range(0, self.CV_SYSTEM_CACHE_CNT):
self.cam.read()
img = self.cam.read()
self.handler.send_frame(img)
self.data = self.scan(img[1])
if self.handler.need_stop():
break
if self.data is not None and (self.last_symbol is None
or self.last_symbol <> self.data):
# print 'decoded', symbol.type, 'symbol', '"%s"' % symbol.data
self.handler.send_symbol(self.data)
self.last_symbol = self.data
time.sleep(self.LOOP_INTERVAL_TIME)
self.cam.release()
class ScanWindow(tk.Toplevel):
def __init__(self, parent, gui, *args, **kw):
tk.Toplevel.__init__(self, master=parent, *args, **kw)
self.parent = parent
self.gui = gui
self.scanner = None
self.lock = threading.Lock()
self.stop_event = threading.Event()
self.img_label = tk.Label(self)
self.img_label.pack(side=tk.TOP)
self.close_button = tk.Button(self, text='close', command=self._stop)
self.close_button.pack()
self.bind('<Escape>', self._stop)
parent.bind('<<ScannerFrame>>', self.on_frame)
parent.bind('<<ScannerEnd>>', self.quit)
parent.bind('<<ScannerSymbol>>', self.on_symbol)
def start(self):
self.frames = []
self.symbols = []
class Handler(object):
def need_stop(self_):
return self.stop_event.is_set()
def send_frame(self_, frame):
self.lock.acquire(True)
self.frames.append(frame)
self.lock.release()
self.parent.event_generate('<<ScannerFrame>>', when='tail')
def send_symbol(self_, data):
self.lock.acquire(True)
self.symbols.append(data)
self.lock.release()
self.parent.event_generate('<<ScannerSymbol>>', when='tail')
self.stop_event.clear()
self.scanner = Scanner(Handler())
self.scanner.start()
self.deiconify()
def _stop(self, *args):
self.gui.stop()
def stop(self):
if self.scanner is None:
return
self.stop_event.set()
self.frames = []
self.symbols = []
self.scanner = None
self.iconify()
def quit(self, *args):
self.parent.event_generate('<<ScannerQuit>>', when='tail')
def on_symbol(self, *args):
self.lock.acquire(True)
symbol_data = self.symbols.pop(0)
self.lock.release()
print 'symbol', '"%s"' % symbol_data
self.after(500, self.quit)
def on_frame(self, *args):
self.lock.acquire(True)
frame = self.frames.pop(0)
self.lock.release()
_, img = frame
img = cv2.flip(img, 1)
cv2image = cv2.cvtColor(img, cv2.COLOR_BGR2RGBA)
img = Image.fromarray(cv2image)
imgtk = ImageTk.PhotoImage(image=img)
self.img_label.imgtk = imgtk
self.img_label.configure(image=imgtk)
class GUI(object):
def __init__(self, root):
self.root = root
self.scan_window = ScanWindow(self.root, self)
self.scan_window.iconify()
self.root.title('QR Scan !!')
self.lframe = tk.Frame(self.root)
self.lframe.pack(side=tk.TOP)
self.start_button = tk.Button(self.lframe, text='start', command=self.start)
self.start_button.pack(side=tk.LEFT)
self.stop_button = tk.Button(self.lframe, text='stop', command=self.stop)
self.stop_button.configure(state='disabled')
self.stop_button.pack(side=tk.LEFT)
self.close_button = tk.Button(self.root, text='close', command=self.quit)
self.close_button.pack(side=tk.TOP)
self.root.bind('<<ScannerQuit>>', self.stop)
self.root.bind('<Control-s>', self.start)
self.root.bind('<Control-q>', self.quit)
self.root.protocol('WM_DELETE_WINDOW', self.quit)
def start(self, *args):
self.start_button.configure(state='disabled')
self.scan_window.start()
self.stop_button.configure(state='active')
def stop(self, *args):
self.scan_window.stop()
self.start_button.configure(state='active')
self.stop_button.configure(state='disabled')
def quit(self, *args):
self.scan_window.stop()
self.root.destroy()
def main():
root = tk.Tk()
gui = GUI(root)
root.mainloop()
main()
关于python:tkinter 显示来自网络摄像头的视频并进行 QR 扫描,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37089228/
避免必须自己创建整个相机应用程序,我调用: Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); this.startActivit
我使用这种方法从前置摄像头录制视频: Recording video via Mediarecorder 它在我的 Nexus 4 上运行良好,但有人说有很多手机的前置摄像头无法录制视频,只能拍照。我
我正在使用 Android 手机的摄像头作为输入来测试成像算法,并且需要一种方法来始终如一地测试算法。理想情况下,我想获取预先录制的视频源并让手机“假装”视频源是来自相机的实时视频。 我理想的解决方案
我想在 android 上通过 v4l 访问外部 USB 摄像头。 我试过了 SimpleWebCam .在对原始源代码进行一些细微修改后,我实现了使其在 Root过的 android 设备上运行。然
我正在尝试连接两个连接到单个 USB 端口的 USB 网络摄像头。问题是当时只有一个摄像头工作...我在 python 中使用 OpenCV。这可能吗?我的目标是将多台相机连接到一台计算机以进行机器视
我想知道如何在 virtualbox 中使用笔记本电脑的内置网络摄像头和 android x86。 我已经尝试启动默认的“相机”应用程序,它告诉我必须配置 SDCard,我在本教程中所做的:SD ca
我在 64 位华硕的 Ubuntu 12.10 上安装了 ARToolKit。安装没有错误,所以我觉得我没问题。但是当我想尝试一个例子时,它找不到相机。如果我在 char *vconf = ""; 没
我想以编程方式移动 webvr 场景中 View 的位置。为此,我使用了position.add 方法。 以下是我如何以编程方式移动相机: 摄像机移至此处: var obj3d = docume
我正在使用 Camera 2 API 将 JPEG 图像保存在磁盘上。我的 Nexus 5X 目前有 3-4 fps,我想将其提高到 20-30。可能吗? 将图像格式更改为 YUV 我设法生成 30
Baby Monitor (http://www.babymonitor3g.com/) 等应用程序可让两台 iOS 设备相互连接。连接后,一台设备可以激活另一台设备上的摄像头、灯光和麦克风,即使该应
我有一个论坛帖子表单,允许发帖人附加录音和/或网络摄像头快照。这两个都是使用 navigator.getUserMedia() 实现的应用程序接口(interface)。对于音频,我建立了 varia
我对 Opencv 和 Python 有疑问。当我尝试从相机中查看帧时,它无法识别 USB 相机,我使用了带有两个 USB 相机的书籍中的标准代码,问题是只有一个相机工作,我不知道。我在 window
我编写了一个程序,基本上使用步进电机 + a4988 驱动程序将托盘放在连接到 Raspberry Pi 的相机下方。代码将托盘带到起始位置,迈出一步,拍照并重复 10 次。然后托盘返回到起始位置。我
我的 uEye 相机遇到了一个问题。使用我的笔记本电脑摄像头(id 0)或 usb 上的网络摄像头(id 1)这条线完美运行: TheVideoCapturer.open(1); (TheVideoC
我是 Android 版 openCV 的新手,我需要一个在后台运行的图像处理应用(检测图像的线条)。 我已经制作了一个应用程序来完成我需要的所有图像处理(使用 jni),但它不能在后台运行并且它使用
我正在尝试使用 OpenCV 从 USB 摄像头捕获视频。 #include #include using namespace std; using namespace cv; int main(
我正在寻找启用和禁用默认 iPhone 相机的方法,例如在特定时间或纬度/经度。有些地方是禁止摄像头的,所以我们可以在到达这样的地方时关闭它,这里只是举个例子。好吧,我认为在 iPhone 中禁用和启
有人有这种“东西”的工作样本吗? 在理论上,以这种方式实现它是个好主意,但我没有看到任何相关的代码 fragment 来说明如何实现它。 我不要花哨的东西,越简单越好。我只想在单独的线程上实现与相机控
我正在开发一个新网站。您可以加入房间通话并进行语音通话,因此可以使用您的网络摄像头,但您也可以共享您的屏幕。 问题是当我将轨道添加到流中时,对等点不再工作......我不知道如何解决这个问题。我还尝试
我需要在 Flutter 中创建一个考试应用程序,我们需要每隔一段时间拍摄用户的照片和视频,而在执行此操作时我们不想显示相机屏幕。 我尝试使用 Flutter 的 Camera 插件,但我无法找到任何
我是一名优秀的程序员,十分优秀!