Friday, November 12, 2021

[SOLVED] OpenCV module not repeating loop in Raspberry Pi 4. Working fine on windows

Issue

Let me start by saying that I am very new to Python and Raspberry Pi.

I've "made"(more like copied from a lot of diff. sources and compiled) a module on windows to capture images from a web cam on key press and save it in a folder(code attached). It is working fine on windows and repeats the loop but throws an error on Raspberry Pi after the first loop.

Code for windows:-

# Import Modules #######################################################################################################

from datetime import datetime
import cv2
import time
import queue
import threading


# Module Level Variables ###############################################################################################


inpath = "D:\\Python Projects\\OCR Trial2\\Input\\Training Data\\"
outpath = "D:\\Python Projects\\OCR Trial2\\Output\\"
intpath = "D:\\Python Projects\\OCR Trial2\\Intermediate\\"
file_Prefix = 'IMG100'
file_Extension = '.png'


# Class Definitions ####################################################################################################

class VideoCapture:

    def __init__(self, name):
        self.cap = cv2.VideoCapture(name)
        self.q = queue.Queue()
        t = threading.Thread(target=self._reader)
        t.daemon = True
        t.start()

    def _reader(self):
        while True:
            ret, frame = self.cap.read()
            if not ret:
                break
            if not self.q.empty():
                try:
                    self.q.get_nowait()
                except queue.Empty:
                    pass
            self.q.put(frame)

    def read(self):
        return self.q.get()

# Functions ############################################################################################################

def main():
    while True:
        try:
            windowName = "Live Video Feed"
            cv2.namedWindow(windowName)

            if cv2.waitKey(1) == ord("c"):

                time.sleep(1)
                now = datetime.now()
                formatted_time = now.strftime('%Y-%m-%d %H-%M-%S.%f')[:-3]
                cam = VideoCapture(0 + cv2.CAP_DSHOW)
                frame1 = cam.read()
                cv2.imshow(windowName,frame1)
                cv2.imwrite(intpath + file_Prefix + formatted_time + file_Extension, frame1)
                print(formatted_time)
            else:
                continue
        except:
            pass

# Execute Code #########################################################################################################

if __name__ == "__main__":
    main()

Output for Windows:-

2021-01-06 17-20-05.255
2021-01-06 17-20-07.404
2021-01-06 17-20-08.601
2021-01-06 17-20-10.766
2021-01-06 17-20-12.408

Process finished with exit code -1

Code for Raspberry Pi:-

# Import Modules #######################################################################################################

from datetime import datetime
import cv2
import time
import queue
import threading

# Module Level Variables ###############################################################################################



intpath = "/home/pi/Python Images/"
file_Prefix = 'IMG100'
file_Extension = '.png'


# Class Definitions ####################################################################################################

class VideoCapture:

    def __init__(self, name):
        self.cap = cv2.VideoCapture(name)
        self.q = queue.Queue()
        t = threading.Thread(target=self._reader)
        t.daemon = True
        t.start()

    def _reader(self):
        while True:
            ret, frame = self.cap.read()
            if not ret:
                break
            if not self.q.empty():
                try:
                    self.q.get_nowait()
                except queue.Empty:
                    pass
            self.q.put(frame)

    def read(self):
        return self.q.get()

# Functions ############################################################################################################


def main():
    while True:
        try:
            windowName = "Live Video Feed"
            cv2.namedWindow(windowName)

            if cv2.waitKey(1) == ord("c"):

                time.sleep(1)
                now = datetime.now()
                formatted_time = now.strftime('%Y-%m-%d %H-%M-%S.%f')[:-3]
                cam = VideoCapture(0)
                frame1 = cam.read()
                cv2.imshow(windowName,frame1)
                cv2.imwrite(intpath + file_Prefix + formatted_time + file_Extension, frame1)
                print(formatted_time)
            else:
                continue
        except:
            pass

# Execute Code #########################################################################################################


if __name__ == "__main__":
    main()

Output for Raspberry Pi :-

2021-01-06 17-07-59.501
[ WARN:4] global /tmp/pip-wheel-qd18ncao/opencv-python/opencv/modules/videoio/src/cap_v4l.cpp (893) open VIDEOIO(V4L2:/dev/video0): can't open camera by index

Process finished with exit code 137 (interrupted by signal 9: SIGKILL)

Open CV module on Raspberry Pi was installed by PIP and not manually compiled. General OpenCV functions like Video capture and imshow work fine on Raspberry Pi and it captures the first photo successfully but cannot capture the second one. Please suggest what could be the problem, what can I try next.

Edit 1 - Added this is the whole error after printing the exception:-

/home/pi/PycharmProjects/pythonProject/venv/bin/python "/home/pi/PycharmProjects/pythonProject/Image Capture.py"
2021-01-07 15-07-36.555
[ WARN:4] global /tmp/pip-wheel-qd18ncao/opencv-python/opencv/modules/videoio/src/cap_v4l.cpp (893) open VIDEOIO(V4L2:/dev/video0): can't open camera by index
Traceback (most recent call last):
  File "/home/pi/PycharmProjects/pythonProject/Image Capture.py", line 72, in <module>
    main()
  File "/home/pi/PycharmProjects/pythonProject/Image Capture.py", line 59, in main
    frame1 = cam.read()
  File "/home/pi/PycharmProjects/pythonProject/Image Capture.py", line 42, in read
    return self.q.get()
  File "/usr/lib/python3.7/queue.py", line 170, in get
    self.not_empty.wait()
  File "/usr/lib/python3.7/threading.py", line 296, in wait
    waiter.acquire()
KeyboardInterrupt

Process finished with exit code 1

Solution

Your mistake can be cam = VideoCapture(0) inside loop.

You should create it only once - before loop.

If you try to use it second time (for example in loop) then system can't access it before it still use previous cam = VideoCapture(0).



Answered By - furas