python - 使用 imagemagick 和 python 合成多组图像时线程延迟

标签 python imagemagick imagemagick-convert

我正在树莓派中构建一个应用程序,用户单击一个按钮,该应用程序会在倒计时后拍摄 3 张照片,并将这 3 张照片放入照片模板中。第一次单击按预期工作,但如果我第二次单击它,它会倒计时,但直到几秒钟后才会拍照,并且随着我单击按钮的次数增多,这种延迟也会增加。问题是,当应用程序将 3 张照片合成到模板中时,这需要一些时间来处理,并且会延迟用于捕获照片的线程。这是因为 ImageService.pycreatePhotoboothImage 函数中的 bash 命令无法异步执行,还是我对线程做错了什么?任何帮助或建议都会很棒!

GUIApp.py

class GUIApp:
    def __init__(self):
        self.root = tk.Tk()
        self.root.attributes('-zoomed', True)
        self.buttonCountDown = tk.Button(text='Count Down', command=self.capturePhotos)
        self.buttonCountDown.pack()
        self.label = tk.Label(text='Ready!', bg='#3D434F', fg='white', font=('Helvetica', 100, 'bold'))
        self.label.pack(side='top', fill='both', expand=True)
        self.queue = queue.Queue()
        self.captureQueue = queue.Queue()
        self.imageProcessQueue = queue.Queue()
        self.imageService = imageService.ImageService()
        self.cameraService = cameraService.CameraService()
        self.imageCount = 0
        self.images = []
        threading.Thread(target=self.listenToCaptureQueue).start()                
        threading.Thread(target=self.listenToQueue).start()
        threading.Thread(target=self.listenToImageProcessQueue).start()
        self.root.mainloop()

    def countDown(self, seconds):
        for i in range(seconds, 0, -1):
            self.queue.put(i)
            time.sleep(1)
        self.queue.put('SMILE!')
        time.sleep(1)
        self.captureQueue.put(True)        

    def listenToQueue(self):
        while True:
            try:
                if self.queue.empty() == False:
                    s = self.queue.get(0)
                    self.label['text'] = s
                elif self.queue.empty() == True: 
                    pass
            except queue.Empty:
                pass

    def listenToCaptureQueue(self):
        while True:
            try:
                if self.captureQueue.empty() == False:
                    if self.captureQueue.get(0):
                        ## Take a photo               
                        self.label['text'] = 'Please wait...'
                        filePath = self.cameraService.captureImage()
                        self.images.append("%r"%filePath)
                        self.imageCount += 1
                        if self.imageCount < 3:
                            # Start timer again to take photo
                            threading.Thread(target=self.countDown, args=(3,)).start()
                        else:
                            self.buttonCountDown['state'] = 'normal'  
                            self.label['text'] = 'Ready!'
                            self.imageProcessQueue.put(self.images)
                elif self.captureQueue.empty() == True:
                    pass
            except queue.Empty:
                pass

    def listenToImageProcessQueue(self):
        while True:
            try:
                if self.imageProcessQueue.empty() == False:  
                        # Composite the 3 photos to the template                 
                        images = self.imageProcessQueue.get(0)     
                        templatePath = '/home/pi/Documents/Test/template.jpg'
                        destinationPath = '/home/pi/Documents/Test/compositeImage.jpg'
                        self.imageService.createPhotoboothImage(images, templatePath, destinationPath)
                elif self.imageProcessQueue.empty() == True:
                    pass
            except queue.Empty:
                pass           

    def capturePhotos(self):
        self.images = []
        self.imageCount = 0
        self.buttonCountDown['state'] = 'disabled'         
        threading.Thread(target=self.countDown, args=(5,)).start()

ImageService.py

class ImageService:      
    def createPhotoboothImage(self, images, templatePath, destinationPath):
        cmd = 'convert ' + templatePath + ' \( ' + images[0] + ' -scale "18.5%" \) -geometry +53+401 -composite \( ' + images[1] + ' -scale "9.02%" \) -geometry +1205.5+401 -composite \( ' + images[2] + ' -scale "9.02%" \) -geometry +1205.5+790 -composite ' + destinationPath
        subprocess.call(cmd, shell=True)

最佳答案

由于全局解释器锁,线程在 Python 中不会并行运行,如果您确实需要并行执行,请使用进程。例如,参见 multiprocessing模块。

关于python - 使用 imagemagick 和 python 合成多组图像时线程延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57781369/

相关文章:

java - java的image magick问题

image-processing - Imagemagick 'convert' : how to simply create thumbnails for a folder of images and retain their filename?

python - 将焦点放在 Tkinter 窗口上(取决于平台?)

python - 不断收到错误 TypeError : function takes at most 2 arguments (3 given)

python - Fabric 忽略@hosts 装饰

ruby - 在 RMagick 中创建具有两种颜色的标题

python - 从列表中获取函数参数

imagemagick - 加载共享库时出错 : libMagickCore-7. Q16HDRI.so.6

macos - ImageMagick:dyld:库未加载。原因:找不到图片

ruby-on-rails - 使用蜻蜓 rails 裁剪圆形图像