There were some addictive points when creating a video processing program with OpenCV on Mac, so this is a memorandum.
The created program performs arbitrary image processing on the image for each frame of the input video, and saves the processed image as a video again. The flow of video processing is as follows.
Install opencv-python with the following command.
pip install opencv-python
The whole picture of the created source code is as follows. The processing for the video is to flip the top, bottom, left, and right in processed_frame = cv2.flip (frame, -1)
on the 67th line. By executing this program, you can create a video in which the input video is flipped vertically and horizontally.
By replacing the up / down / left / right inversion processing with arbitrary image processing, various video processing can be performed with Python.
python:./main.py
import os
import cv2
import argparse
class MovieIter(object):
"""
Video Iterator
"""
def __init__(self, moviefile, inter_method=cv2.INTER_AREA):
if os.path.isfile(moviefile): #When the mp4 file exists
print("[Loading]\tLoading Movie")
self.org = cv2.VideoCapture(moviefile)
self.framecnt = 0
self.inter_method = inter_method
def __iter__(self):
return self
def __next__(self):
self.end_flg, self.frame = self.org.read()
if not self.end_flg: #End the loop when you reach the end of the video
raise StopIteration()
self.framecnt += 1
return self.frame
def __del__(self):
self.org.release()
def get_size(self) -> (int, int):
"""Returns video resolution
Returns:
(int, int): (w, h)
"""
return (
int(self.org.get(cv2.CAP_PROP_FRAME_WIDTH)),
int(self.org.get(cv2.CAP_PROP_FRAME_HEIGHT)),
)
def get_fps(self) -> float:
"""Returns the Fps of the video
Returns:
float: fps
"""
return self.org.get(cv2.CAP_PROP_FPS)
def main(movie_path, save_path):
#Define the video to enter
input_movie = MovieIter(movie_path)
input_moveie_size = input_movie.get_size()
#Definition of video file to output
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
output_movie = cv2.VideoWriter(
os.path.join(save_path, "output.mp4"), #Path to save
fourcc, #Ko-Dick
input_movie.get_fps(), #Video fps
input_moveie_size, #Video resolution
)
for frame in input_movie:
processed_frame = cv2.flip(frame, -1) #Up / down / left / right inversion
#Check if the video resolution is different because it cannot be saved.
assert processed_frame.shape[:2][::-1] == input_moveie_size
output_movie.write(processed_frame)
#Release and save video
output_movie.release()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Purogram to process video")
parser.add_argument("movie_path", help="URL of the video to be processed")
parser.add_argument("--save_path", default="results", help="The path of the directory to save the generated image")
args = parser.parse_args()
main(args.movie_path, args.save_path)
The command at runtime is as follows. If the process is successful, a video with the top, bottom, left, and right of $ {path of the video to be processed}
is created and saved in the folder specified in --save_path
.
python main.py ${Video path to process} --save_path ${Path to save the processed video}
The first addictive point is that if the size of the image specified in cv2.VideoWriter ()
on the 57th line of the source code is different from the size of the image written in output_movie.write (processed_frame)
on the 71st line, The point is that the video export fails.
~~~abridgement~~~~
output_movie = cv2.VideoWriter(
os.path.join(save_path, "output.mp4"), #Path to save
fourcc, #Ko-Dick
input_movie.get_fps(), #Video fps
input_moveie_size, #Video resolution ← here!
)
~~~abridgement~~~~
Generally, the image size of opencv is defined in the order of (height, width, chnnel)
. However, on the other hand, the image size specified by cv2.VideoWriter ()
must be defined in the order of (width, height)
. So, if you usually think that "image size is in the order of(height, width)
~", the phenomenon that video export fails due to the difference in image size between definition and writing occurs. To do.
Moreover, the trouble is that even if the above-mentioned phenomenon that the video export fails due to the difference in size occurs, opencv does not return an error or warning. As a result, I wasted time asking, "Why can't I save the program even though it's normal?", And it took me a long time to notice the mistake in specifying the image size.
As a solution, I put in the process of confirming with assert as follows.
~~~abridgement~~~~
#Check if the video resolution is different because it cannot be saved.
assert processed_frame.shape[:2][::-1] == input_moveie_size
~~~abridgement~~~~
If the format of the created video is grayscale, you need to specify 0 for the 5th argument of cv2.VideoWriter ()
. If you forget to specify this as well, the phenomenon of simply failing to export the video will occur without any error warning, as in the above case.
~~~abridgement~~~~
output_movie = cv2.VideoWriter(
os.path.join(save_path, "output.mp4"), #Path to save
fourcc, #Ko-Dick
input_movie.get_fps(), #Video fps
input_moveie_size, #Video resolution ← here!
0 #← Here!
)
~~~abridgement~~~~
The second point is that it is necessary to specify the corresponding format according to the execution environment for the codec format of the video on the 58th line of the source code.
~~~abridgement~~~~
#Definition of video file to output
fourcc = cv2.VideoWriter_fourcc(*"mp4v") #← Here!
~~~abridgement~~~~
Articles that appear at the top when you search for "opencv python video" etc. are often specified as cv2.VideoWriter_fourcc (*'XVID')
, and the author follows it in the .avi
format as it is. I tried to save it with, but the export did not work. Depending on the version, it seems that it can be saved in .avi
format on MacOS, but saving in mp4
format seems to be the most stable.
The operating status of each format on Mac is summarized by volunteers in the following links. Before writing a program, you should make sure that the format you want to use works well on your Mac.
If you are failing to save due to a different format or size, I would like you to issue a warning ...
-Python + OpenCV to detect anime cuts-Niseneko Memo -[Basic] Handling videos with python + openCV --Qiita
Recommended Posts