I want to create a motion gesture dataset and I'm trying to isolate skin color using bgr2hsv. So far, my output window displays the exact 'black and white video' feed that i aim to achieve. But the video file that i store isn't the same. Do help me fix this.
I'm new to this, i tried doing what i could. If there's a silly mistake, do guide me.
import numpy as np
import os
import cv2
filename = 'video.mp4'
frames_per_second = 10.0
res = '720p'
def change_res(cap, width, height):
cap.set(3, width)
cap.set(4, height)
STD_DIMENSIONS = {
"480p": (640, 480),
"720p": (1280, 720),
"1080p": (1920, 1080),
"4k": (3840, 2160),
}
def get_dims(cap, res='1080p'):
width, height = STD_DIMENSIONS["720p"]
if res in STD_DIMENSIONS:
width,height = STD_DIMENSIONS[res]
change_res(cap, width, height)
return width, height
VIDEO_TYPE = {
'avi': cv2.VideoWriter_fourcc(*'XVID'),
'mp4': cv2.VideoWriter_fourcc(*'XVID'),
}
def get_video_type(filename):
filename, ext = os.path.splitext(filename)
if ext in VIDEO_TYPE:
return VIDEO_TYPE[ext]
return VIDEO_TYPE['mp4']
cap = cv2.VideoCapture(1)
out = cv2.VideoWriter(filename, get_video_type(filename), 25, get_dims(cap, res))
while True:
ret, frame = cap.read()
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
lower_blue = np.array([0, 48, 80])
upper_blue = np.array([20, 255, 255])
mask = cv2.inRange(hsv, lower_blue, upper_blue)
result = cv2.bitwise_and(frame, frame, mask = mask)
out.write(result)
cv2.imshow('frame', mask)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
out.release()
cv2.destroyAllWindows()
I found the Solution!
frame = cv2.cvtColor(mask, cv2.COLOR_GRAY2RGB)
source:
How to save masks of videos in openCV2 python
Related
I'm making a Python script to save the landmarks obtained when using mediapipe. I want to save only the landmarks but I don't want to save the rest of the frame content. Is this possible?
My first idea was to create a black image and put on top of it the landmarks that are obtained when processing the frame that has a person, and when I show it with cv2.imshow(img) I get the landmarks but when I want to save the video I only see black frames. Can anyone help me, I leave below the function that I have done.
import cv2
import numpy as np
import mediapipe as mp
from mediapipe.python.solutions.face_mesh_connections import FACEMESH_CONTOURS
mp_drawing = mp.solutions.drawing_utils
mp_holistic = mp.solutions.holistic
def extract_bones(video_path, new_video_path):
# Captura de los videos
#cap = cv2.VideoCapture(video_path)
cap = cv2.VideoCapture(video_path)
# Se toma el ancho y alto del video
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# Se crea el formato del nuevo video.
output = cv2.VideoWriter(new_video_path,cv2.VideoWriter_fourcc('M','J','P','G'), 30, (width,height))
# Initialize holistic model
with mp_holistic.Holistic(min_detection_confidence = 0.5, min_tracking_confidence = 0.5) as holistic:
while cap.isOpened():
# Read frame
ret, frame = cap.read()
if ret == True:
img = np.zeros((frame.shape[0], frame.shape[1], frame.shape[2]))
# Resize frame
#frame = cv2.resize(frame, (WIDTH, HEIGHT), interpolation = cv2.INTER_AREA)
# Change color from BGR to RGB
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frame.flags.writeable = False
# Detect landmarks
results = holistic.process(frame)
# Left hand (azul)
mp_drawing.draw_landmarks(
img, results.left_hand_landmarks, mp_holistic.HAND_CONNECTIONS,
mp_drawing.DrawingSpec(color=(255, 255, 0), thickness=2, circle_radius=1),
mp_drawing.DrawingSpec(color=(255, 0, 0), thickness=2))
print(img)
# Right hand (verde)
mp_drawing.draw_landmarks(
img, results.right_hand_landmarks, mp_holistic.HAND_CONNECTIONS,
mp_drawing.DrawingSpec(color=(0, 255, 0), thickness=2, circle_radius=1),
mp_drawing.DrawingSpec(color=(57, 143, 0), thickness=2))
print(img)
# Pose
mp_drawing.draw_landmarks(
img, results.pose_landmarks, mp_holistic.POSE_CONNECTIONS,
mp_drawing.DrawingSpec(color=(128, 0, 255), thickness=2, circle_radius=1),
mp_drawing.DrawingSpec(color=(255, 255, 255), thickness=2))
print(img)
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
cv2.imshow("Frame", frame)
cv2.imshow("Black", img)
output.write(img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
Thank you very much
Here is my code
I need to draw a color line and rectangle on my gray video stream.
In my code some bug because my line and rectangle are black but they are not.
import cv2
cap = cv2.VideoCapture(0)
if (cap.isOpened() == False):
print("Unable to read camera feed")
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
out = cv2.VideoWriter('output.avi',cv2.VideoWriter_fourcc('M','J','P','G'), 10, (frame_width,frame_height),0)
while(cap.isOpened()):
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# draw line
start_point = (0, 0)
end_point = (250, 250)
color = (0, 255, 0)
thickness = 5
gray = cv2.line(img=gray, pt1=start_point, pt2=end_point, color=color, thickness=thickness, lineType=8, shift=0)
# draw rectangle
x1,y1 = 200, 200
x2,y2 = 250, 250
gray = cv2.rectangle(gray,(x1, y1), (x2, y2),color, 2)
cv2.imshow('webcam(1)', gray)
out.write(gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
out.release()
cv2.destroyAllWindows()
To draw color elements you have to convert image back to BGR
gray_BGR = cv2.cvtColor(gray cv2.COLOR_GRAY2BGR)
Converting to GRAY not only converts colors to gray but it also reduces every pixel from three values (B,G,R) to single value which can keep only gray color.
If you check frame.shape and gray.shape then you see difference.
First will have (height, width, 3) second will have only (height, width) which means (height, width, 1)
What I'm trying to make:
A OpenCV program that can record a video and mask my face by using an image of a mask.
My Code:
import numpy as np
import cv2
import os
import time
import face_recognition as fr
import pkg_resources
filename = "THIS_IS_A_TEST.mp4"
frames_per_seconds = 24.0
my_res = "720p"
face_cascade = cv2.CascadeClassifier('C:\\Users\\jack\\Desktop\\haarcascade_frontalface_default.xml')
#eyes_cascade = cv2.CascadeClassifier('C:\\Users\\jack\\Desktop\\frontalEyes35x16.xml')
mask = cv2.imread("C:\\Users\\jack\\Desktop\\Blogger_Video_Recorder\\TheMask.png", -1)
def change_res(cap, width, height):
cap.set(3, width)
cap.set(4, height)
STD_DIMENSIONS = {
"480p": (640,480),
"720p": (1280, 720),
"1080p": (1920, 1080),
"4k": (3840, 2160),
}
def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA):
# initialize the dimensions of the image to be resized and
# grab the image size
dim = None
(h, w) = image.shape[:2]
# if both the width and height are None, then return the
# original image
if width is None and height is None:
return image
# check to see if the width is None
if width is None:
# calculate the ratio of the height and construct the
# dimensions
r = height / float(h)
dim = (int(w * r), height)
# otherwise, the height is None
else:
# calculate the ratio of the width and construct the
# dimensions
r = width / float(w)
dim = (width, int(h * r))
# resize the image
resized = cv2.resize(image, dim, interpolation = inter)
# return the resized image
return resized
def get_dims(cap, res="1080p"):
width, height = STD_DIMENSIONS["480p"]
if res in STD_DIMENSIONS:
width, height = STD_DIMENSIONS[res]
change_res(cap, width, height)
return width, height
VIDEO_TYPE = {
"mp4": cv2.VideoWriter_fourcc(*"XVID")
}
def get_video_type(filename):
filename, ext = os.path.splitext(filename)
if ext in VIDEO_TYPE:
return VIDEO_TYPE[ext]
return VIDEO_TYPE["mp4"]
cap = cv2.VideoCapture(0)
dims = get_dims(cap, res = my_res)
video_type_cv2 = get_video_type(filename)
out = cv2.VideoWriter(filename, video_type_cv2, frames_per_seconds, dims)
while True:
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.5, minNeighbors=5)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA)
for (x, y, w, h) in faces:
roi_gray = gray[y:y+h, x:x+h]
roi_color = frame[y:y+h, x:x+h]
roi_faces = roi_gray[y:y+h, x:x+w]
mask2 = image_resize(mask.copy(), width=w)
mw, mh, mc = mask2.shape
for i in range(0,mw):
for j in range(0, mh):
if mask2[i, j][3] != 0:
roi_color[y + i, x + j] = mask2[i, j]
frame = cv2.cvtColor(frame, cv2.COLOR_BGRA2BGR)
out.write(frame)
cv2.imshow("frame", frame)
if cv2.waitKey(20) & 0xFF == ord("q"):
break
cap.release()
out.release()
cv2.destroyAllWindows()
Traceback (most recent call last):
File "C:\Users\jack\Desktop\Blogger_Video_Recorder\tutorial#1.py", line 93, in <module>
roi_color[y + i, x + j] = mask2[i, j]
IndexError: index 426 is out of bounds for axis 0 with size 273
BTW I am also running this on the Python IDLE, so any help is appreciated :)
You do not have to do most of the existing phases. You can use the following method:
draw[y:y+h, x:x+w] = mask2
But in reality there are several errors, the first of which is that the height of the mask is less than the height of the face, so we will not be able to use the values surrounding the face that were found
However, it is possible to know the mask height and reset the print dimensions on the basic frame.
The next line
mask2 = image_resize(mask.copy(), width=w)
mw, mh, mc = mask2.shape
draw[y:y+mw, x:x+w] = mask2
Note Please do not use 'cv2.COLOR_BGR2BGRA' Or the conversion line:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA)
Except for necessity, because it increases the depth of the image to 4 dimensions, and an error will occur when you start printing the mask with the three dimensions,Like:
ValueError: could not broadcast input array from shape (273,410,3) into shape (273,410,4)
Of course it is possible to find another solution but it remains unlikely because you did not use BGRA at all in this code.
Imagine ->full code:
import numpy as np
import cv2
import os
import time
import face_recognition as fr
import pkg_resources
filename = "THIS_IS_A_TEST.mp4"
frames_per_seconds = 24.0
my_res = "720p"
face_cascade = cv2.CascadeClassifier(os.path.join(cv2.data.haarcascades ,'haarcascade_frontalface_default.xml'))
#eyes_cascade = cv2.CascadeClassifier(os.path.join(cv2.data.haarcascades ,'frontalEyes35x16.xml')
mask = cv2.imread("test.jpg", -1)
def change_res(cap, width, height):
cap.set(3, width)
cap.set(4, height)
STD_DIMENSIONS = {
"480p": (640,480),
"720p": (1280, 720),
"1080p": (1920, 1080),
"4k": (3840, 2160),
}
def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA):
# initialize the dimensions of the image to be resized and
# grab the image size
dim = None
(h, w) = image.shape[:2]
# if both the width and height are None, then return the
# original image
if width is None and height is None:
return image
# check to see if the width is None
if width is None:
# calculate the ratio of the height and construct the
# dimensions
r = height / float(h)
dim = (int(w * r), height)
# otherwise, the height is None
else:
# calculate the ratio of the width and construct the
# dimensions
r = width / float(w)
dim = (width, int(h * r))
# resize the image
resized = cv2.resize(image, dim, interpolation = inter)
# return the resized image
return resized
def get_dims(cap, res="1080p"):
width, height = STD_DIMENSIONS["480p"]
if res in STD_DIMENSIONS:
width, height = STD_DIMENSIONS[res]
change_res(cap, width, height)
return width, height
VIDEO_TYPE = {
"mp4": cv2.VideoWriter_fourcc(*"XVID")
}
def get_video_type(filename):
filename, ext = os.path.splitext(filename)
if ext in VIDEO_TYPE:
return VIDEO_TYPE[ext]
return VIDEO_TYPE["mp4"]
cap = cv2.VideoCapture(0)
dims = get_dims(cap, res = my_res)
video_type_cv2 = get_video_type(filename)
out = cv2.VideoWriter(filename, video_type_cv2, frames_per_seconds, dims)
while True:
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.5, minNeighbors=5)
draw = frame.copy()
for (x, y, w, h) in faces:
roi_gray = gray[y:y+h, x:x+w]
roi_color = frame[y:y+h, x:x+w]
roi_faces = roi_gray[y:y+h, x:x+w]
mask2 = image_resize(mask.copy(), width=w)
mw, mh, mc = mask2.shape
draw[y:y+mw, x:x+w] = mask2
out.write(draw)
cv2.imshow("frame", draw)
if cv2.waitKey(5) & 0xFF == ord("q"):
break
cap.release()
out.release()
cv2.destroyAllWindows()
Side note:
It is best to use the expression cv2.data.haarcascades to find the path of the xml files included in the library
can be used os.path.join(cv2.data.haarcascades ,'u_file.xml') to find a valid path for most operating systems.
example of this
import os
import cv2
root_data = cv2.data.haarcascades
face_cascade = cv2.CascadeClassifier(os.path.join(root_data ,'haarcascade_frontalface_default.xml'))
eyes_cascade = cv2.CascadeClassifier(os.path.join(root_data ,'frontalEyes35x16.xml'))
Done..
It's my beginning with coding and this site. I'm working on project, where I want to use openCV, but I've got an issue with that. I need to resize output frame, for recognizing object. I have read, that frame should be in size 416x416, but when I'm trying to release the frame, it's still in regular size.
Here's the code:
import pafy
import youtube_dl
import cv2
import numpy as np
url = "https://www.youtube.com/watch?v=WOn7m0_aYBw"
video = pafy.new(url)
best = video.getbest(preftype="mp4")
cap = cv2.VideoCapture()
cap.open(best.url)
net = cv2.dnn.readNet("yolov3.weights", "yolov3.cfg")
classes = []
with open("coco.names", "r") as f:
classes = [line.strip() for line in f.readlines()]
layer_names = net.getLayerNames()
output_layers =[layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()]
colors = np.random.uniform(0, 255, size=(len(classes), 3))
while True:
ret, frame = cap.read()
# if ret == True:
img = cv2.imshow('frame',frame)
#cap.set(cv2.CAP_PROP_FRAME_WIDTH, 416)
#cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 416)
width = 416
height = 416
dim = (width, height)
img = cv2.resize(frame, dim, interpolation = cv2.INTER_AREA)
print(img.shape)
if cv2.waitKey(20) & 0xFF == ord('q'):
break
blob = cv2.dnn.blobFromImage(img, 0.00392, (416, 416), (0, 0, 0), True, crop=False)
net.setInput(blob)
outs = net.forward(output_layers)
print(img.shape) returns correct size, but I think I'm releasing wrong window. How to change this code to releasing window in correct size?
You were showing the frame before resizing
while True:
ret, frame = cap.read()
width = 416
height = 416
dim = (width, height)
img = cv2.resize(frame, dim, interpolation = cv2.INTER_AREA)
print(img.shape)
cv2.imshow('frame',img)
if cv2.waitKey(20) & 0xFF == ord('q'):
break
I was following this tutorial and I tried to save the video to an avi file, but every time I tried the file was corrupted. I was able to save the frames individually using cv2.imwrite(), but stitching together the individual frames was a lot of work, and would lag the entire program. Here is my code:
from imutils.video import VideoStream
import imutils
import time
import cv2
MINIMUM_AREA = 500
# For Video Recording Purposes
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('vibralert_test001.avi', fourcc, 20, (640, 480))
vs = VideoStream(src=0).start()
print("Setting up feed.")
time.sleep(2)
print("Live")
firstFrame = None
while True:
frame = vs.read()
text = "No Movement Detected"
frame = imutils.resize(frame, width=500)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (21, 21), 0)
if firstFrame is None:
firstFrame = gray
continue
delta = cv2.absdiff(firstFrame, gray)
thresh = cv2.threshold(delta, 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)
for c in cnts:
if cv2.contourArea(c) < MINIMUM_AREA:
continue
(x, y, w, h) = cv2.boundingRect(c)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
text = "Movement Detected"
cv2.putText(frame, "Room Status: {}".format(text), (10, 20),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
cv2.imshow("VibrAlert v0.1", frame)
out.write(frame)
key = cv2.waitKey(1) & 0xFF
if key == 27:
break
vs.stop()
out.release()
cv2.destroyAllWindows()
print('End Feed')
The size of the frame images need to be the same as the frameSize given to the VideoWriter, (640,480). The frame is being resized to have a width of 500, while the videoWriter is expecting a width of 640.
However, changing the resize to frame = imutils.resize(frame, width=640) probably won't work either. imutils.resize will return images with the same aspect ratio as the original image, so the height won't necessarily be 480. I would suggest replacing that line with the opencv.resize:
frame = cv2.resize(frame, (640,480))