Blob detection in Python - Video not opening - python

import numpy as np
import cv2
cap = cv2.VideoCapture('car.avi')
size = (int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT)))
fourcc = cv2.cv.CV_FOURCC(*'AVID')
video = cv2.VideoWriter('6.avi', fourcc, 25, size)
while(1):
ret, frame = cap.read()
if not ret:
break
frame = cv2.convertScaleAbs(frame)
params = cv2.SimpleBlobDetector_Params()
params.blobColor = 0
params.filterByColor = True
params.minArea = 0
params.filterByArea = False
params.minThreshold = 120;
params.maxThreshold = 255;
detector = cv2.SimpleBlobDetector(params)
keypoints = detector.detect(frame)
im_with_keypoints = cv2.drawKeypoints(frame, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
if ret == True:
video.write(im_with_keypoints)
cv2.imshow('frame', im_with_keypoints)
else:
cap.release()
video.release()
break
k = cv2.waitKey(10) & 0xff
if k == 27:
break

I modified the code you have, and now it can run. I used python3.5.
import numpy as np
import cv2
cap = cv2.VideoCapture(r'E:/test.mp4')
size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
fourcc = cv2.VideoWriter_fourcc(*'DIVX')
video = cv2.VideoWriter(r'E:/6.avi', fourcc, 25, size)
while(1):
ret, frame = cap.read()
if not ret:
break
frame = cv2.convertScaleAbs(frame)
params = cv2.SimpleBlobDetector_Params()
params.blobColor = 0
params.filterByColor = True
params.minArea = 0
params.filterByArea = False
params.minThreshold = 120;
params.maxThreshold = 255;
ver = (cv2.__version__).split('.')
if int(ver[0]) < 3:
detector = cv2.SimpleBlobDetector(params)
else:
detector = cv2.SimpleBlobDetector_create(params)
keypoints = detector.detect(frame)
im_with_keypoints = cv2.drawKeypoints(frame, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
if ret == True:
video.write(im_with_keypoints)
cv2.imshow('frame', im_with_keypoints)
else:
cap.release()
break
k = cv2.waitKey(10) & 0xff
if k == 27:
break

Related

Why is OpenCV VideCapture(0) not working on a Mac OS?

I have a MacBook Air M1 2020, Ventura, 13.1 OS.
This is my code to capture a video
cap = cv2.VideoCapture(0)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
writer = cv2.VideoWriter('video_out.mp4', cv2.VideoWriter_fourcc('m', 'p', '4', 'v'),12, (width, height))
while True:
ret, frame = cap.read()
frame = detect_face(frame)
writer.write(frame)
cv2.imshow('Video Face Detection', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
writer.release()
cv2.destroyAllWindows()
The detect face function.
def detect_face(img):
flag = False
face_img = img.copy()
face_rects = face_cascade.detectMultiScale(face_img)
for (x,y,w,h) in face_rects:
cv2.rectangle(face_img, (x,y), (x+w,y+h), (255,255,255), 2)
crop_img = face_img[y:y+h,x:x+w]
flag = True
crop = crop_img.copy()
crop = cv2.resize(crop,(48,48))
crop = crop.reshape(1,48,48,3)
crop = crop.astype('float64')
pred = model_pred.predict(crop)
n1 = int(np.random.randint(0,256,1))
n2 = int(np.random.randint(0,256,1))
n3 = int(np.random.randint(0,256,1))
text = exp[pred.argmax()]
cv2.putText(face_img,text,(x,y-30),fontFace = cv2.FONT_ITALIC,
fontScale = 2,color=[n1,n2,n3],thickness=7)
crop_img = cv2.resize(crop_img,(227,227))
blob = cv2.dnn.blobFromImage(crop_img, 1, (227, 227), MODEL_MEAN_VALUES, swapRB=False)
age_net.setInput(blob)
age_preds = age_net.forward()
age = age_list[age_preds[0].argmax()]
text = 'Age : ' + age
cv2.putText(face_img,text,(x-20,y+h+50),fontFace = cv2.FONT_HERSHEY_SIMPLEX,
fontScale = 1,color=[0,220,0],thickness=3)
gender_net.setInput(blob)
gender_preds = gender_net.forward()
gender = gender_list[gender_preds[0].argmax()]
text = 'Gender : '+ gender
cv2.putText(face_img,text,(x+w+2,y+int(h/2)+20),fontFace = cv2.FONT_ITALIC,
fontScale = 1,color=[0,0,255],thickness=3)
if(flag):
return face_img
else:
return face_img
I have tried so many versions but I am unable to capture a video. I always end up getting this image in a frame.
I don't understand how or why this is getting captured. Any help is appreciated.
How about first making sure the camera has captured something?
ret, frame = cap.read()
if ret:
# run the face detector
else:
break

Is there any alternative for pixel by pixel for loops in opencv?

I am trying to perform pixel by pixel operation to threshold the frames from live camera but it shows Not Responding. I think its because of for loops used for comparing each pixel. It would really help if there's an alternative for thresholding images based on specific conditions. Below is the code for better understanding :
import cv2
import numpy as np
import imutils
import time
import argparse
ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video", help="path to the video file")
args = vars(ap.parse_args())
if args.get("video", None) is None:
cap = cv2.VideoCapture(0)
time.sleep(2.0)
else:
cap = cv2.VideoCapture(args["video"])
firstFrame = None
while True:
_,frame = cap.read()
if np.shape(frame) == ():
cap = cv2.VideoCapture(args["video"])
continue
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray,(21,21),0)
if firstFrame is None:
firstFrame = gray
continue
frameDelta = cv2.absdiff(firstFrame, gray)
thresh = cv2.threshold(frameDelta, 25,255,cv2.THRESH_BINARY)[1]
thresh = cv2.dilate(thresh, None, iterations = 2)
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
if len(cnts) != 0:
c = max(cnts, key = cv2.contourArea)
(x,y,w,h) = cv2.boundingRect(c)
ROI = frame[x:x+w, y:y+h]
(a,b,c) = np.shape(ROI)
if a==0 or b==0 or c==0:
continue
img = ROI
Rule1 = img.copy()
Rule2 = img.copy()
Rule3 = img.copy()
Rule4 = img.copy()
Rule5 = img.copy()
YCrCb = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
Y = YCrCb[:,:,0]
Cr = YCrCb[:,:,1]
Cb = YCrCb[:,:,2]
Ym = int(np.mean(Y))
Crm = int(np.mean(Cr))
Cbm = int(np.mean(Cb))
h = img.shape[0]
w = img.shape[1]
for x in range(0,h) :
for y in range(0,w) :
Rule1[x,y] = 255 if Y[x,y] > Cb[x,y] else 0
Rule2[x,y] = 255 if Cr[x,y] > Cb[x,y] else 0
Rule3[x,y] = 255 if abs(int(Cb[x,y])-int(Cr[x,y]))>=70 else 0
Rule4[x,y] = 255 if Y[x,y]>Ym or Cb[x,y]>Cbm or Cr[x,y]>Crm else 0
Rule5[x,y] = 255 if Cb[x,y]<=120 and Cr[x,y]>=150 else 0
FireRegion = cv2.bitwise_and(Rule1,Rule2)
FireRegion = cv2.bitwise_and(FireRegion,Rule3)
FireRegion = cv2.bitwise_and(FireRegion,Rule4)
FireRegion = cv2.bitwise_and(FireRegion,Rule5)
else :
continue
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)
cv2.imshow("frame",frame)
cv2.imshow("FireRegion",FireRegion)
time.sleep(0.2)
else :
cv2.imshow("frame",frame)
key = cv2.waitKey(1)
if key ==27 :
break

How to get last processed frame from video using opencv?

I want to extract last frame of video that have been processed before with Motion History Image (MHI) and I want to save last image processed by MHI.
Here is my code:
import numpy as np
import cv2
MHI_DURATION = 35
DEFAULT_THRESHOLD = 30
def main():
live_video = False
video_src = 1
if not live_video:
video_src = "data/vid1.mp4"
cv2.namedWindow('motion-history')
cv2.namedWindow('raw')
cv2.moveWindow('raw', 200, 0)
cam = cv2.VideoCapture(video_src)
ret, frame = cam.read()
h, w = frame.shape[:2]
prev_frame = frame.copy()
motion_history = np.zeros((h, w), np.float32)
timestamp = 0
while True:
ret, frame = cam.read()
if not ret:
break
frame_diff = cv2.absdiff(frame, prev_frame)
gray_diff = cv2.cvtColor(frame_diff, cv2.COLOR_BGR2GRAY)
ret, fgmask = cv2.threshold(gray_diff, DEFAULT_THRESHOLD, 1, cv2.THRESH_BINARY)
timestamp += 1
# update motion history
cv2.motempl.updateMotionHistory(fgmask, motion_history, timestamp, MHI_DURATION)
# normalize motion history
mh = np.uint8(np.clip((motion_history - (timestamp - MHI_DURATION)) / MHI_DURATION, 0, 1) * 255)
cv2.imshow('motion-history', mh)
# cv2.imshow('raw', frame)
prev_frame = frame.copy()
if 0xFF & cv2.waitKey(5) == 27:
break
cv2.destroyAllWindows()
And, can we process faster without loop through all frame in the video?

(cv2,capture) object is not callable

Basically, this code will detect object's motion in the scene. When the motion is detected, a red rectangle frame will track the object's motion. But, I added a new function into the code which is frame differencing. In general it is thresholding. When i run the code it says:"cv2.capture" object is not callable.
import cv2.cv as cv
class Target:
def __init__(self):
self.capture = cv.CaptureFromCAM(0)
cv.NamedWindow("Target", 1)
def run(self):
# Capture first frame to get size
ret, current_frame = self.capture()
previous_frame = current_frame
frame = cv.QueryFrame(self.capture)
frame_size = cv.GetSize(frame)
color_image = cv.CreateImage(cv.GetSize(frame), 8, 3)
grey_image = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_8U, 1)
moving_average = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_32F, 3)
first = True
while True:
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)
closest_to_left = cv.GetSize(frame)[0]
closest_to_right = cv.GetSize(frame)[1]
color_image = cv.QueryFrame(self.capture)
# Smooth to get rid of false positives
cv.Smooth(color_image, color_image, cv.CV_GAUSSIAN, 3, 0)
if first:
difference = cv.CloneImage(color_image)
temp = cv.CloneImage(color_image)
cv.ConvertScale(color_image, moving_average, 1.0, 0.0)
first = False
else:
cv.RunningAvg(color_image, moving_average, 0.020, None)
# Convert the scale of the moving average.
cv.ConvertScale(moving_average, temp, 1.0, 0.0)
# Minus the current frame from the moving average.
cv.AbsDiff(color_image, temp, difference)
# Convert the image to grayscale.
cv.CvtColor(difference, grey_image, cv.CV_RGB2GRAY)
# Convert the image to black and white.
cv.Threshold(grey_image, grey_image, 70, 255, cv.CV_THRESH_BINARY)
# Dilate and erode to get people blobs
cv.Dilate(grey_image, grey_image, None, 18)
cv.Erode(grey_image, grey_image, None, 10)
storage = cv.CreateMemStorage(0)
contour = cv.FindContours(grey_image, storage, cv.CV_RETR_CCOMP, cv.CV_CHAIN_APPROX_SIMPLE)
points = []
while contour:
bound_rect = cv.BoundingRect(list(contour))
contour = contour.h_next()
pt1 = (bound_rect[0], bound_rect[1])
pt2 = (bound_rect[0] + bound_rect[2], bound_rect[1] + bound_rect[3])
points.append(pt1)
points.append(pt2)
cv.Rectangle(color_image, pt1, pt2, cv.CV_RGB(255,0,0), 1)
cv.ShowImage("Target", color_image)
cv.ShowImage("frame_diff", frame_diff)
# Listen for ESC key
c = cv.WaitKey(7) % 0x100
if c == 27:
break
if __name__=="__main__":
t = Target()
t.run()
This is the original frame differencing code that I wanted transfer from:
import cv2
cap = cv2.VideoCapture(0)
ret, current_frame = cap.read()
previous_frame = current_frame
while(cap.isOpened()):
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)
cv2.imshow('frame diff ',frame_diff)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
previous_frame = current_frame.copy()
ret, current_frame = cap.read()
cap.release()
cv2.destroyAllWindows()
You can't call the capture object, but you can read from it by calling its read method. Changing your frame return code to:
ret, current_frame = self.capture.read()
Should fix this.
Edit:
The two lines:
ret, current_frame = self.capture.read()
previous_frame = current_frame
Will work for VideoCapture but not CaptureFromCAM. You apparently don't need them since you can take a frame by doing:
frame = cv.QueryFrame(self.capture)

when calculating optical flow, why frame has no value?

so I'm trying to implement this code for optical flow
but when I try to call cv2.imshow('frame',img) I get an error because img, frame, and mask are all "None".
can anybody help me understand where the problem is?
here's my code:
import cv2
import numpy as np
feature_params = dict( maxCorners = 100,
qualityLevel = 0.3,
minDistance = 7,
blockSize = 7 )
lk_params = dict( winSize = (15,15),
maxLevel = 2,
criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
color = np.random.randint(0,255,(100,3))
cap = cv2.VideoCapture(0)
while( cap.isOpened() ) :
ret,old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
p0 = cv2.goodFeaturesToTrack(old_gray, mask = None, **feature_params)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
mask = np.zeros_like(old_frame)
while (1):
ret,frame = cap.read()
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)
good_new = p1[st==1]
good_old = p0[st==1]
for i,(new,old) in enumerate(zip(good_new,good_old)):
a,b = new.ravel()
c,d = old.ravel()
mask = cv2.line(mask, (a,b),(c,d), color[i].tolist(), 2)
frame = cv2.circle(frame,(a,b),5,color[i].tolist(),-1)
img = cv2.add(frame,mask)
cv2.imshow('frame',img)
k = cv2.waitKey(30) & 0xff
old_gray = frame_gray.copy()
p0 = good_new.reshape(-1,1,2)
cv2.destroyAllWindows()
cap.release()
You have
mask = cv2.line(...)
frame = cv2.circle(...)
But cv2.line and cv2.circle return None.

Categories