Hello. I am writing a program that displays a webcam feed live on the computer screen while also taking an image from that feed every 30 seconds or so to do some operation on that image (mainly slicing it up using numpy and opencv and reading numbers with Tesseract). Because I need to display the feed in a cv2.imshow() infinite loop that is uninterrupted, I have the loop in a thread so the image operation (scheduled every 30 seconds using a python scheduler) does not interrupt and freeze the display.
For some reason, the cv2.imshow() screen goes black after a random amount of time. This has happened after 15 minutes, and after 4 hours of functional operation, seemingly completely random. Not only that, but it saves an all black picture as well. The camera is on when it turns black (the light is anyway) and I have run a simple cv2.imshow() for hours to check for a hardware issue and there doesn’t seem to be one.
Below is my code. This is not the final code, but it is the smallest I can make it while keeping the same structure and reproducing the error.
import time import gc import cv2 import threading import schedule import numpy class operator(): def __init__(self): print("Start") def start_cam(self): is_blurry = True while is_blurry == True: print("Start of start_cam") self.camera = cv2.VideoCapture(0, cv2.CAP_DSHOW) # Make camera object with correct format, size, and autofocus. All of these appear to be necessary to get 4K resolution in OpenCV self.camera.set(cv2.CAP_PROP_FRAME_WIDTH, 3840) #3840 self.camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 2160) #2160 self.camera.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc('m','j','p','g')) self.camera.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc('M','J','P','G')) self.camera.set(cv2.CAP_PROP_AUTOFOCUS, 1) self.camera.set(cv2.CAP_PROP_FPS, 60) i=10 while i>0: # Takes 10 pictures and waits 1 sec in between each. This is done to make sure it has time to autofocus i=i-1 cv2.waitKey(1000) #1000 ret, self.frame = self.camera.read() if ret != True: print("image error") # Check to make sure it actually took a picture and didn't fail if ret != True and i == 1: restart_loop = True print("Image error, restarting loop") # continue laplace = cv2.Laplacian(self.frame, cv2.CV_64F).var() # Checks if image is blurry. If it is, it restarts the camera. print(laplace) if laplace < 20: # Blurry print("Blurry image, reinitializing") self.camera.release() del(self.camera) cv2.destroyAllWindows() gc.collect() time.sleep(2) else: print("image not blurry") break def live_loop(self): loop_bool = True cv2.namedWindow("Live Feed", cv2.WINDOW_NORMAL) # Creates a normal window so that the 4k image is scaled correctly for the live feed (I have a relatively small monitor) while loop_bool == True: ret, self.frame = self.camera.read() if ret != True: print("image error") break self.frame_rotate = cv2.rotate(self.frame, cv2.ROTATE_180) cv2.imshow("Live Feed", self.frame_rotate) k = cv2.waitKey(10) gc.collect() def data_operation(self): print("Start data operation") imgpath = "path where image is saved" cv2.imwrite(imgpath, self.frame) t = time.localtime() # If the image can't be read as a number, saves the image with a timestamp so that it can be examined later timestamp = time.strftime('%b-%d-%Y_%H;%M', t) print(timestamp) if __name__== "__main__": op = operator() op.start_cam() x = threading.Thread(target=op.live_loop, daemon = True) x.start() schedule.every(30).seconds.do(op.data_operation) try: while True: schedule.run_pending() time.sleep(1) except KeyboardInterrupt: print("Ended Program") gc.collect()
The image operation starts by saving the image (using cv2.imwrite()) which is necessary because I need to upload the image to a google drive depending on certain variables. Interestingly, when I comment out the lines that save the image in the data_operation() function, the program seems to work without randomly turning black. However, I need to save the image as I said so I don’t know how to work around this.
Another interesting thing is that the program works fine on my laptop and never seems to go black, but the issue persists on the computer it needs to work on. I have done my best to replicate the exact conditions (external camera, same code, same python module version, etc.) and it never fails.
I realize this could be a python issue rather than an open issue, but I don’t know where else to turn. My StackOverflow question got no helpful answers, and I am totally stumped.
If there is a way to show a live webcam feed while grabbing an image from it and doing operations on that image (including saving it to the computer) without interrupting that live feed, please let me know. I don’t mind rebuilding this from the ground up if needed, I just want it to work. I am not a programmer by trade so I’ve gotten this far by Googling and problem solving, but this issue is so inconsistent that I don’t know what else to do.
Thanks in advance.