How to time out a statement in a for loop - python

I'm writing a python script to perform camera calibration with OpenCV.
I found that the cv2.findChessboardCorners function may take very long to run on certain images.
I would therefore like to be able to stop the function after a certain period of time has passed, and move on to the next image.
How do I do that?
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, corners = cv2.findChessboardCorners(gray, (20, 17), None)

You could use Pebble as a multiprocessing library, which allows scheduling tasks. The code below also uses multiple threads for the processing:
from pebble import ProcessPool
from concurrent.futures import TimeoutError
import cv2
import glob
import os
CALIB_FOLDER = "path/to/folder"
# chessboard size
W = 10
H = 7
def f(fname):
img = cv2.imread(fname)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Find the chessboard corners
ret, corners = cv2.findChessboardCorners(gray, (W-1, H-1), None)
return ret, corners
calib_imgs = glob.glob(os.path.join(CALIB_FOLDER, "*.jpg"))
calib_imgs = sorted(calib_imgs)
futures = []
with ProcessPool(max_workers=6) as pool:
for fname in calib_imgs:
future = pool.schedule(f, args=[fname], timeout=10)
futures.append(future)
for idx, future in enumerate(futures):
try:
ret, corners = future.result() # blocks until results are ready
print(ret)
except TimeoutError as error:
print("{} skipped. Took longer than {} seconds".format(calib_imgs[idx], error.args[1]))
except Exception as error:
print("Function raised %s" % error)
print(error.traceback) # traceback of the function

Related

frame.shape NameError: name 'frame' is not defined

I don't know anything about Python, but I have a job that requires processing, so I need to implement some functions.
Below is my code.
When I ran Python,
Traceback (most recent call last): File "C:\Users\user\Desktop\bodypix\bodypix.py", line 80, in
frame.shape
NameError: name 'frame' is not defined
This error is checked.
Why does this error appear?
If you know how to solve this problem, I would really appreciate your help.
import tensorflow as tf
from tf_bodypix.api import download_model, load_model, BodyPixModelPaths
import cv2
from matplotlib import pyplot as plt
import numpy as np
# # 2. Detections
# In[2]:
load_model(download_model(BodyPixModelPaths.MOBILENET_FLOAT_50_STRIDE_16))
# In[3]:
bodypix_model = load_model(download_model(BodyPixModelPaths.MOBILENET_FLOAT_50_STRIDE_16))
# In[27]:
# get vid cap device
cap = cv2.VideoCapture(0)
# loop through frame
while cap.isOpened():
ret, frame = cap.read()
# BodyPix Detections
result = bodypix_model.predict_single(frame)
mask = result.get_mask(threshold=0.5).numpy().astype(np.uint8)
masked_image = cv2.bitwise_and(frame, frame, mask=mask)
# Show result to user on desktop
cv2.imshow('BodyPix', masked_image)
# Break loop outcome
if cv2.waitKey(10) & 0xFF == ord('q'):
break
cap.release() # Releases webcam or capture device
cv2.destroyAllWindows() # Closes imshow frames
# # 3. Add Virtual Background
# In[12]:
img = cv2.imread('beach.jpg')
img = img[:480, :640, :]
# In[13]:
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
# In[14]:
img.shape
# In[15]:
frame.shape
# In[24]:
plt.imshow(mask)
# In[23]:
plt.imshow(np.where(np.add(mask, -1) == -1, 1, np.add(mask, -1)))
# In[ ]:
# get vid cap device
cap = cv2.VideoCapture(0)
# loop through frame
while cap.isOpened():
ret, frame = cap.read()
# BodyPix Detections
result = bodypix_model.predict_single(frame)
mask = result.get_mask(threshold=0.5).numpy().astype(np.uint8)
masked_image = cv2.bitwise_and(frame, frame, mask=mask)
# Apply virtual background
neg = np.add(mask, -1)
inverse = np.where(neg==-1, 1, neg).astype(np.uint8)
masked_background = cv2.bitwise_and(img, img, mask=inverse)
final = cv2.add(masked_image, masked_background)
# Show result to user on desktop
cv2.imshow('BodyPix', final)
# Break loop outcome
if cv2.waitKey(10) & 0xFF == ord('q'):
break
cap.release() # Releases webcam or capture device
cv2.destroyAllWindows() # Closes imshow frames
You're referencing frame.shape prior to frame being assigned. Notice how img.shape is allowed since before this there is an assignment: img = cv2.imread('beach.jpg').
Read the documentation to see what "frame" should be assigned to.

OpenCV VideoCapture can't run with 3 cameras

I am running this class function in loop and plotting the return image at the same time. However, if I have more than 2 cameras this does not seem to work.
I have this error (continuously):
CvCapture_MSMF::grabFrame videoio(MSMF): can't grab frame. Error: -2147483638
def grab_frame(self):
image = []
timestamp = []
for i in range(0, len(self.devs)):
cap = self.cams[i]
ret, frame = cap.read()
if ret:
timestamp.extend([time.time()-self.def_time])
image.extend(frame)
return timestamp, image

Mediapipe process() first 'self' argument

I am trying to use mediapipe to track hands. I am using Python 3.7.9 on Windows 10, my code is below:
import cv2
import mediapipe as mp
mp_drawing = mp.solutions.drawing_utils
mp_hands = mp.solutions.hands
cap = cv2.VideoCapture(0)
while (True):
success, img = cap.read()
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
results = mp_hands.Hands.process(imgRGB)
print(result)
if cv2.waitKey(10) & 0xFF == ord('q'):
break
I'm getting this error:
Traceback (most recent call last):
File "C:/Users/Tomáš/PycharmProjects/pythonProject/hand_detect.py", line 11, in <module>
results = mp_hands.Hands.process(imgRGB)
TypeError: process() missing 1 required positional argument: 'image'
[ WARN:1] global D:\a\opencv-python\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (438) `anonymous-namespace'::SourceReaderCB::~SourceReaderCB terminating async callback
Error says that I need to pass one more argument 'self' before I pass argument 'image'. I've been browsing a lot and every related code doesnt use first argument in the process() function. Could anyone help me solve this error?
The problem is that you do not create an object of mp_hands.Hands before you want to process it. The following code solves it and prints some results. By the way, this was well documentated in the documentation link i commented before.. :
import cv2
import mediapipe as mp
mp_drawing = mp.solutions.drawing_utils
mp_hands = mp.solutions.hands
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW) # i had problems before reading webcam feeds, so i added cv2.CAP_DSHOW here
while True:
success, img = cap.read()
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# you have to create an object of mp_hands.Hands to get results
# alternatively you could do: results = mp_hands.Hands().process(imgRGB)
with mp_hands.Hands() as hands:
results = hands.process(imgRGB)
# continue loop if no results were found
if not results.multi_hand_landmarks:
continue
# print some results
for hand_landmarks in results.multi_hand_landmarks:
print(
f'Index finger tip coordinates: (',
f'{hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP].x}, '
f'{hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP].y})'
)
if cv2.waitKey(10) & 0xFF == ord('q'):
break
Edit:
This is more or less the same code from here:
import cv2
import mediapipe as mp
mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_hands = mp.solutions.hands
# initialize webcam
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
with mp_hands.Hands(model_complexity=0,
min_detection_confidence=0.5,
min_tracking_confidence=0.5) as hands:
while cap.isOpened():
success, image = cap.read()
if not success:
print("Ignoring empty camera frame.")
# If loading a video, use 'break' instead of 'continue'.
continue
# To improve performance, optionally mark the image as not writeable to
# pass by reference.
image.flags.writeable = False
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
results = hands.process(image)
# Draw the hand annotations on the image.
image.flags.writeable = True
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
mp_drawing.draw_landmarks(
image,
hand_landmarks,
mp_hands.HAND_CONNECTIONS,
mp_drawing_styles.get_default_hand_landmarks_style(),
mp_drawing_styles.get_default_hand_connections_style())
# Flip the image horizontally for a selfie-view display.
cv2.imshow('MediaPipe Hands', cv2.flip(image, 1))
if cv2.waitKey(5) & 0xFF == 27:
break
cap.release()

Hardware-accelerated JPEG Compression on Raspberry Pi

I have a stereo camera connected to a Raspberry Pi. I want to get images off it, compress them, and send them to a PC continuously. I am trying to use MMAL for this.
I have this code to test it out:
from picamera import mmal, mmalobj
import cv2
import io
from threading import Event
finished = Event() # triggered whenever it finishes compressing an image
image = cv2.imread('image.png')
image = cv2.resize(image, (3200, 1300))
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
encoder = mmalobj.MMALImageEncoder()
encoder.inputs[0].format = mmal.MMAL_ENCODING_I420
encoder.inputs[0].framesize = (3200, 1300)
encoder.inputs[0].commit()
encoder.outputs[0].copy_from(encoder.inputs[0])
encoder.outputs[0].format = mmal.MMAL_ENCODING_JPEG
encoder.outputs[0].commit()
encoder.outputs[0].params[mmal.MMAL_PARAMETER_JPEG_Q_FACTOR] = 90
def image_callback(port, buf):
jpg_data.write(buf.data)
if bool(buf.flags & mmal.MMAL_BUFFER_HEADER_FLAG_FRAME_END):
finished.set()
return True
return False
# perform compression on the image 100 times
for i in range(100):
finished.clear()
encoder.inputs[0].enable(lambda port, buf: True)
encoder.outputs[0].enable(image_callback)
jpg_data = io.BytesIO()
buf = encoder.inputs[0].get_buffer()
buf.data = image[:]
encoder.inputs[0].send_buffer(buf)
finished.wait()
jpg_data.close()
encoder.inputs[0].disable()
encoder.outputs[0].disable()
This only works if I disable and reenable the ports on every iteration. However, it is slower than just using OpenCV:
import cv2
import io
image = cv2.imread('image.png')
image = cv2.resize(image, (3200, 1300))
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# perform compression on the image 100 times
for i in range(100):
success, buffer = cv2.imencode(".jpg", image)
io_buffer = io.BytesIO(buffer)
data = io_buffer.read()
Also, I found that the disabling and reenabling was taking up about half the time. Does anyone know why this is happening, and if there is a faster way? Thanks.

How to differentiating and storing the differentiated frames in a specified place

Have attached the source code for frame differentiating and storing the differentiated frames in a specified place but am getting an error in indentation of error..post this problem as a question in stack overflow..i am restricted to question for a particular period..upload the code too
filename.py
import cv2
import os
import glob
def extractFrames(pathIn, pathOut):
os.mkdir(pathOut)
cap = cv2.VideoCapture(pathIn)
count = 0
while (cap.isOpened()):
# Capture frame-by-frame
ret, frame = cap.read()
current_frame_gray = cv2.cvtColor(current_frame, cv2.COLOR_BGR2GRAY)
previous_frame_gray = cv2.cvtcolor(previous_frame, cv2.COLOR_BGR2GRAY)
frame_diff = cv2.absdiff(current_frame_gray,previous_frame_gray)
if ret == True:
print('Read %d frame: ' % count, ret)
cv2.imwrite(os.path.join(pathOut, "frame{:d}.jpg".format(count)), frame_diff) # save frame as JPEG file
count += 1
else:
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
def main():
extractFrames('C:/Users/yaazmoha/Desktop/BE PROJECT/INPUT/Tiger in field(1080P_HD).mp4', 'fd3')
if __name__=="__main__":
main()
Fixed your code. You had some indentation errors. Since Python does not use braces like C++, it requires proper indentation to separate code.
import cv2
import os
import glob
def extractFrames(pathIn, pathOut):
os.mkdir(pathOut)
cap = cv2.VideoCapture(pathIn)
count = 0
while (cap.isOpened()):
# Capture frame-by-frame
ret, current_frame = cap.read()
current_frame_gray = cv2.cvtColor(current_frame, cv2.COLOR_BGR2GRAY)
if count > 1:
previous_frame_gray = cv2.cvtcolor(previous_frame, cv2.COLOR_BGR2GRAY)
frame_diff = cv2.absdiff(current_frame_gray,previous_frame_gray)
if ret == True:
print('Read %d frame: ' % count, ret)
cv2.imwrite(os.path.join(pathOut, "frame{:d}.jpg".format(count)), frame_diff) # save frame as JPEG file
count += 1
else:
break
previous_frame = current_frame
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
def main():
extractFrames(r"C:\Users\mathesn\Downloads\Wildlife.mp4", 'fd3')
if __name__=="__main__":
main()
I took liberties to fix other sections of your code. But there are some other fixes that this code needs, like creating a directory only if it doesn't exist, maintaining a colored version of the frame so that cv2.cvtColor() does not fail, etc., but I''ll leave those to you.

Categories