I'm trying to capture video/image feed from a USB 3.0 webcam. When ever I try to run this code,the code runs and captures feed. But, after a while I get 'select timeout'.
The error is not grabbed by exception.
Can someone help me with this issue?
select timeout
OpenCV Error: Assertion failed (total() == 0 || data != __null) in Mat, file /home/opencv-3.4.0/modules/core/include/opencv2/core/mat.inl.hpp, line 500
try:
while True:
ret, frame = cap.read()
if ret != True:
break
if stat == None:
stat = ret
print('[INFO] ---- Reading video feed')
continue
frame = cv2.resize(frame , (int(320/2),int(240/2)))
video.write(frame)
if stat1 == None:
stat1 = ret
print('[INFO] ---- Video recording on process')
continue
c+=1
print(c)
key = cv2.waitKey(30) & 0xFF
if key == 27:
break
elif c == 1200:
break
except Exception as e:
print(e)
sys.exit()
I have also tried editing the 'uvcvideo' driver parameters
$ modprobe uvcvideo nodrop=1 timeout=6000
And also,
Enabled module traces,
$ sudo echo 0xffff > /sys/module/uvcvideo/parameters/trace
Observed these errors on 'dmesg' IMAGE
Link which I followed:
Select Timeout error in Ubuntu - Opencv
Related
Trying to set a max timeout for VideoCapture to catch the exception and print a message if the stream is down. For example, I need it to try for 10 seconds and then assume the stream is offline. I have the following code so far.
import cv2
try:
cap = cv2.VideoCapture("rtsp://Username:Password#IP_ADDRESS:PORT")
print("Stream found.")
cap.release()
cv2.destroyAllWindows()
except:
# It actually never reaches the exception
print("Stream not found.")
Edit: Tried to simplify the answer below and it kind of works as expected but still with its own timeout decision.
import cv2
import time
try:
cap = cv2.VideoCapture("rtsp://DNA:DNA2020!#98.173.8.28:5514")
try:
success, video_frame = cap.read()
if success:
print('Frame read')
else:
print('No frame read')
except cv2.error as e:
print(f'CV2 Exception: {str(e)}')
cap.release()
except:
print("Stream not found.")
When opening the stream you only get a video object. Then you have to start reading the frames from the video object. This will tell you if there is a video stream.
TIMEOUT: The code stops if during 10 seconds no frames have been received.
RESET TIMEOUT: If within the 10 seconds new frames are being received then receiving resumes and the timeout will be again 10 seconds.
I have tested this code on a video file. I think it should work on your camera also.
import cv2
import time
try:
cap = cv2.VideoCapture("rtsp://Username:Password#IP_ADDRESS:PORT")
print("Stream found.")
stream_ok = True
while True:
try:
success, video_frame = cap.read()
if success:
print('Frame read')
frame_ok = True
# show frame
cv2.imshow("Image", video_frame)
cv2.waitKey(1)
else:
print('No frame read')
frame_ok = False
except cv2.error as e:
print(f'CV2 Exception: {str(e)}')
frame_ok = False
if stream_ok:
if not frame_ok:
# start of missing video
stream_ok = False
no_frame_start_time = time.time()
else:
if not frame_ok:
# still no video
if time.time() - no_frame_start_time > 10:
print('NO VIDEO - CAPTURE ABORTED')
break
else:
# video restarted
stream_ok = True
cap.release()
cv2.destroyAllWindows()
except:
# It actually never reaches the exception
print("Stream not found.")
happy day, I am trying to synchronize two cameras
(my local computer) and the camera of my cell phone with IP Web cam,
however when running the code it generates an error and the two
cameras that I have previously opened are closed (see photo ). What
would this be due to? Thanks for your help!
ERROR -->
Traceback (most recent call last):
File "C:\Users\JUCABALL\Desktop\camera_stream_openCV-master\main.py", line 20, in <module>
cv2.imshow ('cam1', frame1)
cv2.error: OpenCV (4.5.4-dev) D:\a\opencv-python\opencv-python\opencv\modules\imgproc\src\color.cpp: 182:
error: (-215: Assertion failed)! _src .empty () in function 'cv :: cvtColor'
This is the tabs - after fews seconds tabs close
[Tabs, 2 cameras][1]
This is my code
import numpy as np
import cv2
# capture the webcam
vid1 = cv2.VideoCapture(0, cv2.CAP_DSHOW)
vid2 = cv2.VideoCapture(1, cv2.CAP_DSHOW)
vid3 = cv2.VideoCapture(
"http://192.168.0.11:8080/video", cv2.CAP_DSHOW
) # ipwebcam address
while True: # while true, read the camera
ret, frame = vid1.read()
ret1, frame1 = vid2.read()
ret2, frame2 = vid3.read()
if ret:
cv2.imshow("cam0", frame) # frame with name and variable of the camera
cv2.imshow("cam1", frame1)
cv2.imshow("cam3", frame2)
# to break the loop and terminate the program
if cv2.waitKey(1) & 0xFF == ord("q"):
break
vid1.release()
vid2.release()
vid3.release()
The problem is you're not checking the value of ret1 and ret2.
If those are False, the images will not have been captured, and you're still trying to show them, and OpenCV crashes because there's no way to show an image that doesn't exist.
Try
if ret:
cv2.imshow("cam0", frame)
if ret1:
cv2.imshow("cam1", frame1)
if ret2:
cv2.imshow("cam3", frame2)
instead.
You could also store all of the capture devices in a list, and all the captured images equally so, to make the code a little simpler to work with:
import numpy as np
import cv2
captures = [
cv2.VideoCapture(0, cv2.CAP_DSHOW),
cv2.VideoCapture(1, cv2.CAP_DSHOW),
cv2.VideoCapture("http://192.168.0.11:8080/video", cv2.CAP_DSHOW), # ipwebcam address
]
while True: # while true, read the camera
frames = []
for cap in captures:
ret, frame = cap.read()
frames.append((frame if ret else None))
for i, frame in enumerate(frames):
if frame is not None: # None if not captured
cv2.imshow(f"cam{i}", frame)
# to break the loop and terminate the program
if cv2.waitKey(1) & 0xFF == ord("q"):
break
for cap in captures:
cap.release()
Every 10 seconds, I capture a new image using my igmcap() function and store it in the direction folder Captures. I want my identify() function to run on the latest image captured. Is the best way to do this to wrap all of the functions inside of a single loop?
Python Code:
def imgcap():
cap = cv2.VideoCapture(0)
framerate = cap.get(10)
x=1
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
if ret:
# Our operations on the frame come here
filename = 'Captures\\capture' + str(int(x)) + ".png"
x=x+1
cv2.imshow("frame", frame)
cv2.imwrite(filename, frame)
time.sleep(5)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
print("Ret False")
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
imgcap()
def identify(path):
cmd = f"darknet.exe detector test cfg/obj.data cfg/yolov4_test.cfg custom-yolov4-detector_best.weights -ext_output -out result.json {path}"
# cmd = f"darknet.exe detector test cfg/obj.data cfg/yolov4-tiny-custom.cfg custom-yolov4-tiny-detector_best.weights -ext_output -out result.json {path}"
os.chdir(r'C:\Yolo_v4\darknet\build\darknet\x64')
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
out = p.stdout.read()
print(out)
identify(r'C:\\Yolo_v4\\darknet\\build\\darknet\\x64\\Captures\\SOMETHING_GOES_HERE')
If you want to keep your functions independent, imgcap() could return the actual path to the capture so it can be used for subsequent analysis:
def imgcap():
# All your code goes here
...
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
return filename
If you are always going to run identify() on every new frame captured, it makes sense to make them part of the same loop, after the frame is saved.
My IP camera seems to be a little unstable and disconnects randomly. I'd like my script to be able to determine when its disconnected and attempt to reconnect a few times, probably waiting 5-10 seconds between attempts. I've tried a few things, but nothing is working.
This is my basic script, when ret is false the script ends:
#!/usr/local/bin/python3
import cv2
import time
import datetime
print("start time: " + datetime.datetime.now().strftime("%A %d %B %Y %I:%M:%S%p"))
cap = cv2.VideoCapture('rtsp://<ip><port>/live0.264')
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
# Confirm we have a valid image returned
if not ret:
print("disconnected!")
break
# Our operations on the frame come here
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA)
# Display the resulting frame
cv2.imshow('frame', gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
print("end time: " + time.strftime("%X"))
# When everything is done, release the capture
cap.release()
cv2.destroyAllWindows()
Edit: I would also like the script to try to reconnect to the camera in the event that my network goes down temporarily or anything like that as well.
I was finally able to solve this myself. Hopefully this is useful for anyone else looking to do the same thing.
This is actually a shell of a more complex script that has logic for motion detection and video recording when motion is detected. Everything is working very well with this basic logic (and my crappy IP camera) although I am still doing testing.
#!/usr/local/bin/python3
import cv2
import datetime
import time
def reset_attempts():
return 50
def process_video(attempts):
while(True):
(grabbed, frame) = camera.read()
if not grabbed:
print("disconnected!")
camera.release()
if attempts > 0:
time.sleep(5)
return True
else:
return False
recall = True
attempts = reset_attempts()
while(recall):
camera = cv2.VideoCapture("rtsp://<ip><port>/live0.264")
if camera.isOpened():
print("[INFO] Camera connected at " +
datetime.datetime.now().strftime("%m-%d-%Y %I:%M:%S%p"))
attempts = reset_attempts()
recall = process_video(attempts)
else:
print("Camera not opened " +
datetime.datetime.now().strftime("%m-%d-%Y %I:%M:%S%p"))
camera.release()
attempts -= 1
print("attempts: " + str(attempts))
# give the camera some time to recover
time.sleep(5)
continue
More detailed description:
https://github.com/Combinacijus/various-code-samples/tree/master/Python/OpenCV/ip_cam_reconnecting
Wrote a class to deal with IP camera disconnecting randomly. Main idea is to check if cap.read() returns a frame and if it doesn't it tries to reconnect to the camera.
import cv2
import requests # NOTE: Only used for forceful reconnection
import time # NOTE: Only used for throttling down printing when connection is lost
class IPVideoCapture:
def __init__(self, cam_address, cam_force_address=None, blocking=False):
"""
:param cam_address: ip address of the camera feed
:param cam_force_address: ip address to disconnect other clients (forcefully take over)
:param blocking: if true read() and reconnect_camera() methods blocks until ip camera is reconnected
"""
self.cam_address = cam_address
self.cam_force_address = cam_force_address
self.blocking = blocking
self.capture = None
self.RECONNECTION_PERIOD = 0.5 # NOTE: Can be changed. Used to throttle down printing
self.reconnect_camera()
def reconnect_camera(self):
while True:
try:
if self.cam_force_address is not None:
requests.get(self.cam_force_address)
self.capture = cv2.VideoCapture(self.cam_address)
if not self.capture.isOpened():
raise Exception("Could not connect to a camera: {0}".format(self.cam_address))
print("Connected to a camera: {}".format(self.cam_address))
break
except Exception as e:
print(e)
if self.blocking is False:
break
time.sleep(self.RECONNECTION_PERIOD)
def read(self):
"""
Reads frame and if frame is not received tries to reconnect the camera
:return: ret - bool witch specifies if frame was read successfully
frame - opencv image from the camera
"""
ret, frame = self.capture.read()
if ret is False:
self.reconnect_camera()
return ret, frame
if __name__ == "__main__":
CAM_ADDRESS = "http://192.168.8.102:4747/video" # NOTE: Change
CAM_FORCE_ADDRESS = "http://192.168.8.102:4747/override" # NOTE: Change or omit
cap = IPVideoCapture(CAM_ADDRESS, CAM_FORCE_ADDRESS, blocking=True)
# cap = IPVideoCapture(CAM_ADDRESS) # Minimal init example
while True:
ret, frame = cap.read()
if ret is True:
cv2.imshow(CAM_ADDRESS, frame)
if cv2.waitKey(1) == ord("q"):
break
__author__ = 'Kyle'
HELP_MESSAGE = """Script: frame_grabber.py
Usage: python frame_grabber.py path/to/video
Requires: OpenCV 2.4.8+
Purpose: Select and save frames from a given video.
Commands:
Key Function
a previous frame
d next frame
q exit
SHIFT + a skip 10 frames forward
SHIFT + d skip 10 frames backwards
s saves current frame
dbl click saves current frame
Controls:
Slider Navigate through the video
"""
# Check if the user has provided a path to a file
# otherwise display the HELP_MESSAGE
import sys
import time as t
# Check if OpenCV module is present
# otherwise stop the application
try:
import cv2
except ImportError as e:
print "Fatal Error: Could not import OpenCV, ", e
exit(-1)
else:
print "Using OpenCV ", cv2.__version__
# these flags may depend on your opencv version:
# in opencv 3.0.0 these flags are implemented as
# cv2.CAP_PROP_POS_FRAMES and
# cv2.CAP_PROP_FRAME_COUNT
CURRENT_FRAME_FLAG = cv2.cv.CV_CAP_PROP_POS_FRAMES
TOTAL_FRAMES_FLAG = cv2.cv.CV_CAP_PROP_FRAME_COUNT
WIN_NAME = "Frame Grabber"
POS_TRACKBAR = "pos_trackbar"
#VIDEO_PATH = 'camera13.h264'
#try:
# VIDEO_PATH = sys.argv[1]
# except IndexError as e:
# print HELP_MESSAGE
# exit(-1)
cap = cv2.VideoCapture("camera13.h264")
if not cap.isOpened():
print "Fatal Error: Could not open the specified file."
exit(-1)
ret, frame = cap.read()
if not ret:
print "Fatal Error: Could not read/decode frames from specified file."
exit(-1)
def dummy():
pass
def save_image():
filename = "image_%0.5f.png" % t.time()
cv2.imwrite(filename, frame)
def seek_callback(x):
global frame
i = cv2.getTrackbarPos(POS_TRACKBAR, WIN_NAME)
cap.set(CURRENT_FRAME_FLAG, i-1)
_, frame = cap.read()
cv2.imshow(WIN_NAME, frame)
def mouse_callback(event,x,y,flags,param):
if event == cv2.EVENT_LBUTTONDBLCLK:
save_image()
def skip_frame_generator(df):
def skip_frame():
global frame
cf = cap.get(CURRENT_FRAME_FLAG) - 1
cap.set(CURRENT_FRAME_FLAG, cf+df)
cv2.setTrackbarPos(POS_TRACKBAR, WIN_NAME, int(cap.get(CURRENT_FRAME_FLAG)))
_, frame = cap.read()
return skip_frame
cv2.namedWindow(WIN_NAME)
cv2.createTrackbar(POS_TRACKBAR, WIN_NAME, 0, int(cap.get(TOTAL_FRAMES_FLAG)), seek_callback)
cv2.setMouseCallback(WIN_NAME, mouse_callback)
actions = dict()
actions[ord("D")] = skip_frame_generator(10)
actions[ord("d")] = skip_frame_generator(1)
actions[ord("a")] = skip_frame_generator(-1)
actions[ord("A")] = skip_frame_generator(-10)
actions[ord("q")] = lambda: exit(0)
actions[ord("s")] = save_image
while True:
cv2.imshow(WIN_NAME, frame)
key = cv2.waitKey(0) & 0xFF
actions.get(key, dummy)()``
When the code is executed, I receive the error - OverflowError: Python int too large to convert to C long. How may I go about solving this please? This code is meant to create a frame grabber that allows me to pick a frame that I want and save it.
Well, the error is telling you that you are passing a number in this line:
cv2.createTrackbar(POS_TRACKBAR, WIN_NAME, 0,int(cap.get(TOTAL_FRAMES_FLAG)), seek_callback)
That is too large to be cast to ctypes.c_long; The maximum number that can be represented by this type is (2**31)-1 = 2147483647.
This is presumably your TOTAL_FRAMES_FLAG. Now that's a lot of frames (approx. 500 days #50fps), so it can't be right.
I notice that you are getting this value before you open the video file, so it's likely to be undefined at that point. Try doing it after you've opened your file, and see if that fixes things. You could print the value, as well, to see if it is indeed too large (before you try the suggested change).