在使用python使用threading、os、cv2进行多线程文件的图像的获取存储、读取、删除的过程中,遇到了一些无法解决的问题:
代码如下:
import cv2
import time
import threading
import os
#从电脑摄像头获取图片并存储
def cunchu():
cap = cv2.VideoCapture(0)
success,x_img=cap.read()
cv2.imwrite(os.path.join('C:\\Users\\10605\\Desktop\\wjj','1.png'), x_img)
#读取图片
def duqv():
img = cv2.imread('C:\\Users\\10605\\Desktop\\wjj\\1.png')
cv2.imshow("img", img)
cv2.waitKey(1)
#删除图片
def shanchu():
os.remove('C:\\Users\\10605\\Desktop\\wjj\\1.png')
if __name__== '__main__':
cunchu1 = threading.Thread(target=cunchu)
duqv1 = threading.Thread(target=duqv)
shanchu1 = threading.Thread(target=shanchu)
cunchu1.start()
time.sleep(1)
print("1")
duqv1.start()
time.sleep(2)
print("2")
shanchu1.start()
time.sleep(1)
print("3")
报错如下
C:\Users\10605\Desktop\venv\Scripts\python.exe C:/Users/10605/Desktop/venv/图片实验.py
1
[ WARN:0@1.422] global D:\a\opencv-python\opencv-python\opencv\modules\imgcodecs\src\loadsave.cpp (239) cv::findDecoder imread_('C:\Users\10605\Desktop\wjj\1.png'): can't open/read file: check file path/integrity
Exception in thread Thread-2 (duqv):
Traceback (most recent call last):
File "C:\Users\10605\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1009, in _bootstrap_inner
self.run()
File "C:\Users\10605\AppData\Local\Programs\Python\Python310\lib\threading.py", line 946, in run
self._target(*self._args, **self._kwargs)
File "C:\Users\10605\Desktop\venv\图片实验.py", line 15, in duqv
cv2.imshow("img", img)
cv2.error: OpenCV(4.6.0) D:\a\opencv-python\opencv-python\opencv\modules\highgui\src\window.cpp:967: error: (-215:Assertion failed) size.width>0 && size.height>0 in function 'cv::imshow'
2
3
进程已结束,退出代码0
问题分析:在多线程操作中,由于线程间的并发执行,可能会导致某些操作的顺序出现问题,比如在duqv线程中读取图片时,可能会出现文件不存在的情况,因为cunchu线程还没有完成图片的存储就被duqv线程读取了。另外,在删除图片时也需要注意,可能会出现文件不存在的情况,因为shanchu线程可能会先于cunchu线程执行,导致文件还没有创建就被删除了。
解决思路:可以使用线程同步的方式来解决这个问题,比如使用锁来保证cunchu线程完成图片存储后再执行duqv线程,使用条件变量来保证cunchu线程完成图片存储后再执行shanchu线程。另外,可以使用异常处理来捕获文件不存在等异常情况。
代码如下:
import cv2
import time
import threading
import os
#从电脑摄像头获取图片并存储
def cunchu(lock, event):
cap = cv2.VideoCapture(0)
success, x_img = cap.read()
cv2.imwrite(os.path.join('C:\\Users\\10605\\Desktop\\wjj','1.png'), x_img)
event.set()
lock.release()
#读取图片
def duqv(lock, event):
event.wait()
lock.acquire()
try:
img = cv2.imread('C:\\Users\\10605\\Desktop\\wjj\\1.png')
cv2.imshow("img", img)
cv2.waitKey(0)
except Exception as e:
print(e)
finally:
lock.release()
#删除图片
def shanchu(lock, event):
event.wait()
lock.acquire()
try:
os.remove('C:\\Users\\10605\\Desktop\\wjj\\1.png')
except Exception as e:
print(e)
finally:
lock.release()
if __name__ == '__main__':
lock = threading.Lock()
event = threading.Event()
cunchu1 = threading.Thread(target=cunchu, args=(lock, event))
duqv1 = threading.Thread(target=duqv, args=(lock, event))
shanchu1 = threading.Thread(target=shanchu, args=(lock, event))
lock.acquire()
cunchu1.start()
duqv1.start()
shanchu1.start()
在这个例子中,我们使用了线程同步的方式来保证cunchu线程完成图片存储后再执行duqv线程和shanchu线程,具体的方法是使用锁和条件变量。首先,我们创建了一个锁和一个条件变量,然后在cunchu线程中,当图片存储完成后,我们使用event.set()来设置条件变量,表示图片已经存储完成;然后使用lock.release()来释放锁。在duqv线程和shanchu线程中,我们先使用event.wait()来等待条件变量被设置,表示图片已经存储完成;然后使用lock.acquire()来获取锁,保证线程同步。在读取图片和删除图片时,我们使用了异常处理来避免文件不存在等异常情况。
以下回答结合了ChatGPT:
根据你提供的错误信息来看,是在调用cv2.imshow("img", img)方法时,内部方法在判断图片的大小size.width>0 && size.height>0时报错了,说明你的图片应该是没有读取成功,导致判断大小时失败了。因为是使用了线程,而线程是并发执行的,有可能在你还没有把图片存储下来,另一个线程就去读取了,从而导致图片没有读取成功,建议你把存储图片和读取图片之间的休眠时间设置长一点看看。
这个代码对于调用函数的返回值没有判断哈,中间如果有错误就会出问题
先可以看下 cunchu 产生1.png文件是否成功了
然后在 duqv 函数,用os模块里面的函数先判断一下文件1.png是否存在, 还需判断img是否为None等
既然说了并发,要考虑下 读取和删除方式 获取文件失败场景,其次也要考虑保存方法 文件路径是否存在
不知道你这个问题是否已经解决, 如果还没有解决的话: