I am applying Canny edge detector in a video using OpenCV. I can see the result in a window and then I am writing the video. Even though I can see the right result on the window, the result in the output file is not the same.
Here is the code and what I can see in the window and in the output file. Any idea what can cause this?
I am not sure what is the output of Canny and if I have to turn it to type of data that will fit with the rest of the video.
`
import cv2
import numpy as np
cap = cv2.VideoCapture('New_video.mp4')
if (cap.isOpened() == False):
print("Unable to read camera feed")
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
fps = int(round(cap.get(5)))
out = cv2.VideoWriter('output.mp4', cv2.VideoWriter_fourcc(*'mp4v'), fps,
(frame_width, frame_height))
while (True):
ret, frame = cap.read()
if ret == False:
break
if between (cap,40000,45000):
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
frame = cv2.blur(gray,(5,5))
frame = cv2.Canny(frame,20,60)
if between (cap,45000,50000):
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
frame = cv2.blur(gray,(5,5))
frame = cv2.Canny(frame,150,250)`
out.write(frame)
cv2.imshow('frame',frame)
Try using XVID fourcc codec instead of mp4v. Also,VideoWriter method has one more parameter isColor which is set to be true by default. It should be set to False whenever we use gray scale images.
https://docs.opencv.org/3.4/dd/d9e/classcv_1_1VideoWriter.html
Related
I want to save a video after converting to gray scale. I don't know where exactly put the line out.write(gray_video). I use jupyter notebook with Python 3, and the Opencv library.
the code is:
import cv2
import numpy as np
video = cv2.VideoCapture("video1.mp4")
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('out_gray_scale.mp4', fourcc, 10.0, (640, 480),0)
while (True):
(ret, frame) = video.read()
if not ret:
print("Video Completed")
break
# Convert the frames into Grayscaleo
gray_video = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#writing
gray_frame = cv2.flip(gray_video, 0)
out.write(gray_video) #it suppose to save the gray video
#Show the binary frames
if ret == True:
cv2.imshow("video grayscale",gray_video)
#out.write(gray_video)
# Press q to exit the video
if cv2.waitKey(25) & 0xFF == ord('q'):
break
else:
break
video.release()
cv2.destroyAllWindows()
The working video writer module of OpenCV depends on three main things:
the available/supported/installed codecs on the OS
getting the right codec and file extension combinations
the input video resolution should be same as output video resolution otherwise resize the frames before writing
If any of this is wrong openCV will probably write a very small video file which will not open in video player. The following code should work fine:
import cv2
import numpy as np
video = cv2.VideoCapture("inp.mp4")
video_width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH)) # float `width`
video_height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT)) # float `height`
video_fps = int(video.get(cv2.CAP_PROP_FPS))
print(video_width, video_height, video_fps)
fourcc = cv2.VideoWriter_fourcc('M','J','P','G')
out = cv2.VideoWriter('out_gray_scale1.avi', fourcc, video_fps, (video_width, video_height),0)
while (True):
ret, frame = video.read()
if not ret:
print("Video Completed")
break
# Convert the frames into Grayscale
gray_video = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#Show the binary frames
if ret == True:
cv2.imshow("video grayscale",gray_video)
#Writing video
out.write(gray_video)
# Press q to exit the video
if cv2.waitKey(25) & 0xFF == ord('q'):
break
else:
break
video.release()
out.release()
cv2.destroyAllWindows()
I read all pictures from my pic directory and then convert them each to gray-scale with canny edge detections before writing it all to a video.
But, when I use my video software to play it, it shows a green background, and I can't read video frames from it. Could someone show me how to solve it?
Sample code
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
fourcc = cv.VideoWriter_fourcc(*"I420")
out = cv.VideoWriter("t2.avi", fourcc, 1, (640, 480), 0)
for pic in glob.glob1("./pic/", "A*"):
img = cv.imread(f"./pic/{pic}", -1)
edge = cv.Canny(img, 100, 200)
edge = cv.resize(edge, (640, 480))
out.write(edge)
out.release()
# Cant read video frame here:
cap = cv.VideoCapture("t2.avi")
ret, frame = cap.read()
if ret:
plt.imshow(frame)
else:
print("end")
cap.release()
Video plays with green background
It looks like a compatibility issue between I420 FOURCC and Grayscale format.
Replace fourcc = cv.VideoWriter_fourcc(*"I420") with:
fourcc = cv.VideoWriter_fourcc(*"GREY")
Note:
I am using OpenCV 4.5.5 in Windows 10, and it's working with "GREY".
I am not sure it's going to work in all platforms and versions.
I420 applies colored video.
You may use I420 with colored video:
Replace out = cv.VideoWriter("t2.avi", fourcc, 1, (640, 480), 0) with:
out = cv.VideoWriter("t2.avi", fourcc, 1, (640, 480), 1)
Convert edge to BGR before writing:
edge = cv.cvtColor(edge, cv.COLOR_GRAY2BGR)
out.write(edge)
Code sample using "GREY" FOURCC:
import numpy as np
import cv2 as cv
#import matplotlib.pyplot as plt
import glob
#fourcc = cv.VideoWriter_fourcc(*"I420")
fourcc = cv.VideoWriter_fourcc(*"GREY")
out = cv.VideoWriter("t2.avi", fourcc, 1, (640, 480), 0)
for pic in glob.glob1("./pic/", "A*"):
img = cv.imread(f"./pic/{pic}", -1)
edge = cv.Canny(img, 100, 200)
edge = cv.resize(edge, (640, 480))
out.write(edge)
out.release()
# Cant read video frame here:
cap = cv.VideoCapture("t2.avi")
while True:
ret, frame = cap.read()
if ret:
#plt.imshow(frame)
cv.imshow('frame', frame)
cv.waitKey(1000)
else:
print("end")
cap.release()
break
cv.destroyAllWindows()
I want to detect edges of a video file (640x640 9sn.) and save the result. I followed OpenCV documents and some other examples. Most of the examples that I found was reading from camera.
Here is my code. I checked cap.isOpened(), it returns True but ret does False and frame is NoneType object. What is confusing is that I'm having the gray array which depends the condition if ret == True. How can I get gray matrix if ret = False?
(I installed ffmpeg pip install ffmpeg-python)
(andy.avi was saved in folder but it's broke, empty)
import cv2
import numpy as np
cap = cv2.VideoCapture("...\\video.mp4")
while(cap.isOpened()):
ret, frame = cap.read()
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
size = (frame_width, frame_height)
result = cv2.VideoWriter('andy.avi',
cv2.VideoWriter_fourcc(*'DIVX'),
30, size)
if ret == True:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 45, 90)
result.write(edges)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
result.release()
cv2.destroyAllWindows()
your code should be changed like this
# importing the module
import cv2
import numpy as np
# reading the vedio
source = cv2.VideoCapture("...\\video.mp4")
# We need to set resolutions.
# so, convert them from float to integer.
frame_width = int(source.get(3))
frame_height = int(source.get(4))
size = (frame_width, frame_height)
result = cv2.VideoWriter('andy.avi',
cv2.VideoWriter_fourcc(*'DIVX'),
30, size, 0)
# running the loop
while True:
# extracting the frames
ret, img = source.read()
# converting to gray-scale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 45, 90)
# write to gray-scale
result.write(edges)
# displaying the video
cv2.imshow("Live", gray)
# exiting the loop
key = cv2.waitKey(1)
if key == ord("q"):
break
# closing the window
result.release()
source.release()
cv2.destroyAllWindows()
If helpful this for you give 👍
I'mm writing this piece of python to display a stream of video from my webcam while at the same time record the video - which I've got working, however I've grayscaled the video streaming to my screen and time stamped it - but my recorded video is in colour! I've included the code below - I've tried using some global variables but nothing worked - any help, greatly appreciated
import cv2
import numpy as np
import time, datetime
import os
genericfilename = "recording"
filetime = str(time.time())
extension = '.avi'
filename = genericfilename + filetime +extension
frames_per_second = 100
res = '720p'
print("NEW FILE NAME: " + filename)
# Set resolution for the video capture
def change_res(cap, width, height):
cap.set(3, width)
cap.set(4, height)
# Standard Video Dimensions Sizes
STD_DIMENSIONS = {
"480p": (640, 480),
"720p": (1280, 720),
"1080p": (1920, 1080),
"4k": (3840, 2160),
}
# grab resolution dimensions and set video capture to it.
def get_dims(cap, res='1080p'):
width, height = STD_DIMENSIONS["480p"]
if res in STD_DIMENSIONS:
width,height = STD_DIMENSIONS[res]
## change the current caputre device
## to the resulting resolution
change_res(cap, width, height)
return width, height
# Video Encoding, might require additional installs
VIDEO_TYPE = {
'avi': cv2.VideoWriter_fourcc(*'XVID'),
#'mp4': cv2.VideoWriter_fourcc(*'H264'),
'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['avi']
capture = cv2.VideoCapture(0)
out = cv2.VideoWriter(filename, get_video_type(filename), 60,
get_dims(capture, res))
while(True):
ret, frame = capture.read()
out.write(frame)
grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
font = cv2.FONT_ITALIC = 1
cv2.putText(grayFrame, str(datetime.datetime.now()), (-330, 460), font, 3,
(200, 200, 200), 2, cv2.LINE_AA)
cv2.imshow('combilift output', grayFrame)
# Press Q on keyboard to exit
if cv2.waitKey(1) & 0xFF == ord('q'):
break
if cv2.waitKey(1) & 0xFF == ord('r'):
print(datetime.datetime.now())
capture.release()
out.release()
cv2.destroyAllWindows()
You save the frame to video, then convert frame to gray.
out.write(frame)
grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
If you want your recorded video to be gray, maybe reverse the order of operations and save grayFrame?
grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
out.write(grayFrame)
If you want to also save the texts, put the text before writing frame to output.
Lets take a look at ur code
out = cv2.VideoWriter(filename, get_video_type(filename), 60,
.....
while(True):
ret, frame = capture.read()
out.write(frame)
grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
You first save out then convert color
The correct sequence should be
out = cv2.VideoWriter(filename, get_video_type(filename), 60,
.....
while(True):
ret, frame = capture.read()
grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
out.write(grayFrame)
I don't have data to test. Just in case you experience some issue with channels. You can use opencv merge(grayFrame,grayFrame,grayFrame) to create a normal 3 channel grey scale image and save to video
Why does the following code not save the video?
Also is it mandatory that the frame rate of the webcam matches exactly with the VideoWriter frame size?
import numpy as np
import cv2
import time
def videoaufzeichnung(video_wdth, video_hight, video_fps, seconds):
cap = cv2.VideoCapture(6)
cap.set(3, video_wdth) # wdth
cap.set(4, video_hight) #hight
cap.set(5, video_fps) #hight
# Define the codec and create VideoWriter object
fps = cap.get(5)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi', fourcc, video_fps, (video_wdth, video_hight))
#out = cv2.VideoWriter('output.avi', fourcc, 20.0, (640, 480))
start = time.time()
zeitdauer = 0
while(zeitdauer < seconds):
end = time.time()
zeitdauer = end - start
ret, frame = cap.read()
if ret == True:
frame = cv2.flip(frame, 180)
# write the flipped frame
out.write(frame)
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
# Release everything if job is finished
cap.release()
out.release()
cv2.destroyAllWindows()
videoaufzeichnung.videoaufzeichnung(1024, 720, 10, 30)
I suspect you're using the libv4l version of OpenCV for video I/O. There's a bug in OpenCV's libv4l API that prevents VideoCapture::set method from changing the video resolution. See links 1, 2 and 3. If you do the following:
...
frame = cv2.flip(frame,180)
print(frame.shape[:2] # check to see frame size
out.write(frame)
...
You'll notice that the frame size has not been modified to match the resolution provided in the function arguments. One way to overcome this limitation is to manually resize the frame to match resolution arguments.
...
frame = cv2.flip(frame,180)
frame = cv2.resize(frame,(video_wdth,video_hight)) # manually resize frame
print(frame.shape[:2] # check to see frame size
out.write(frame)
...
output-frame & input-frame sizes must be same for writing...