Package: vidstab
Python Video StabilizationPython video stabilization using OpenCV. Fullsearchable documentation here.This module contains a single class (VidStab) used for video stabilization. This class is based on the work presented by Nghia Ho inSIMPLE VIDEO STABILIZATION USING OPENCV. The foundation code was found in a comment on Nghia Ho's post by the commenter with username koala.InputOutputVideoused with permission fromHappyLivingContents:InstallationInstallvidstabwithout installing OpenCVInstall vidstab & OpenCVBasic UsageUsing from command lineUsing VidStab classAdvanced UsagePlotting frame to frame transformationsUsing bordersUsing Frame LayeringStabilizing a frame at a timeWorking with live videoTransform File Writing & ReadingInstallation+ Please report issues if you install/try to install and run into problems!Installvidstabwithout installing OpenCVIf you've already built OpenCV with python bindings on your machine it is recommended to installvidstabwithout installing the pypi versions of OpenCV.  Theopencv-pythonpython module can cause issues if you've already built OpenCV from source in your environment.The below commands will installvidstabwithout OpenCV included.From PyPipipinstallvidstabFrom GitHubpipinstallgit+https://github.com/AdamSpannbauer/python_video_stab.gitInstallvidstab& OpenCVIf you don't have OpenCV installed already there are a couple options.You can build OpenCV using one of the great online tutorials fromPyImageSearch,LearnOpenCV, orOpenCVthemselves.  When building from source you have more options (e.g.platform optimization), but more responsibility.  Once installed you can use the pip install command shown above.You can install a pre-built distribution of OpenCV from pypi as a dependency forvidstab(see command below)The below commands will installvidstabwithopencv-contrib-pythonas dependencies.From PyPipipinstallvidstab[cv2]From Githubpipinstall-egit+https://github.com/AdamSpannbauer/python_video_stab.git#egg=vidstab[cv2]Basic usageTheVidStabclass can be used as a command line script or in your own custom python code.Using from command line# Using defaultspython3-mvidstab--inputinput_video.mov--outputstable_video.avi# Using a specific keypoint detectorpython3-mvidstab-iinput_video.mov-ostable_video.avi-kGFTTUsingVidStabclassfromvidstabimportVidStab# Using defaultsstabilizer=VidStab()stabilizer.stabilize(input_path='input_video.mov',output_path='stable_video.avi')# Using a specific keypoint detectorstabilizer=VidStab(kp_method='ORB')stabilizer.stabilize(input_path='input_video.mp4',output_path='stable_video.avi')# Using a specific keypoint detector and customizing keypoint parametersstabilizer=VidStab(kp_method='FAST',threshold=42,nonmaxSuppression=False)stabilizer.stabilize(input_path='input_video.mov',output_path='stable_video.avi')Advanced usagePlotting frame to frame transformationsfromvidstabimportVidStabimportmatplotlib.pyplotaspltstabilizer=VidStab()stabilizer.stabilize(input_path='input_video.mov',output_path='stable_video.avi')stabilizer.plot_trajectory()plt.show()stabilizer.plot_transforms()plt.show()TrajectoriesTransformsUsing bordersfromvidstabimportVidStabstabilizer=VidStab()# black bordersstabilizer.stabilize(input_path='input_video.mov',output_path='stable_video.avi',border_type='black')stabilizer.stabilize(input_path='input_video.mov',output_path='wide_stable_video.avi',border_type='black',border_size=100)# filled in bordersstabilizer.stabilize(input_path='input_video.mov',output_path='ref_stable_video.avi',border_type='reflect')stabilizer.stabilize(input_path='input_video.mov',output_path='rep_stable_video.avi',border_type='replicate')border_size=0border_size=100border_type='reflect'border_type='replicate'Videoused with permission fromHappyLivingUsing Frame LayeringfromvidstabimportVidStab,layer_overlay,layer_blend# init vid stabilizerstabilizer=VidStab()# use vidstab.layer_overlay for generating a trail effectstabilizer.stabilize(input_path=INPUT_VIDEO_PATH,output_path='trail_stable_video.avi',border_type='black',border_size=100,layer_func=layer_overlay)# create custom overlay function# here we use vidstab.layer_blend with custom alpha#   layer_blend will generate a fading trail effect with some motion blurdeflayer_custom(foreground,background):returnlayer_blend(foreground,background,foreground_alpha=.8)# use custom overlay functionstabilizer.stabilize(input_path=INPUT_VIDEO_PATH,output_path='blend_stable_video.avi',border_type='black',border_size=100,layer_func=layer_custom)layer_func=vidstab.layer_overlaylayer_func=vidstab.layer_blendVideoused with permission fromHappyLivingAutomatic border sizingfromvidstabimportVidStab,layer_overlaystabilizer=VidStab()stabilizer.stabilize(input_path=INPUT_VIDEO_PATH,output_path='auto_border_stable_video.avi',border_size='auto',# frame layering to show performance of auto sizinglayer_func=layer_overlay)Stabilizing a frame at a timeThe methodVidStab.stabilize_frame()can acceptnumpyarrays to allow stabilization processing a frame at a time.
This can allow pre/post processing for each frame to be stabilized; see examples below.Simplest formfromvidstab.VidStabimportVidStabstabilizer=VidStab()vidcap=cv2.VideoCapture('input_video.mov')whileTrue:grabbed_frame,frame=vidcap.read()ifframeisnotNone:# Perform any pre-processing of frame before stabilization herepass# Pass frame to stabilizer even if frame is None# stabilized_frame will be an all black frame until iteration 30stabilized_frame=stabilizer.stabilize_frame(input_frame=frame,smoothing_window=30)ifstabilized_frameisNone:# There are no more frames available to stabilizebreak# Perform any post-processing of stabilized frame herepassExample with object trackingimportosimportcv2fromvidstabimportVidStab,layer_overlay,download_ostrich_video# Download test video to stabilizeifnotos.path.isfile("ostrich.mp4"):download_ostrich_video("ostrich.mp4")# Initialize object tracker, stabilizer, and video readerobject_tracker=cv2.TrackerCSRT_create()stabilizer=VidStab()vidcap=cv2.VideoCapture("ostrich.mp4")# Initialize bounding box for drawing rectangle around tracked objectobject_bounding_box=NonewhileTrue:grabbed_frame,frame=vidcap.read()# Pass frame to stabilizer even if frame is Nonestabilized_frame=stabilizer.stabilize_frame(input_frame=frame,border_size=50)# If stabilized_frame is None then there are no frames left to processifstabilized_frameisNone:break# Draw rectangle around tracked object if tracking has startedifobject_bounding_boxisnotNone:success,object_bounding_box=object_tracker.update(stabilized_frame)ifsuccess:(x,y,w,h)=[int(v)forvinobject_bounding_box]cv2.rectangle(stabilized_frame,(x,y),(x+w,y+h),(0,255,0),2)# Display stabilized outputcv2.imshow('Frame',stabilized_frame)key=cv2.waitKey(5)# Select ROI for tracking and begin object tracking# Non-zero frame indicates stabilization process is warmed upifstabilized_frame.sum()>0andobject_bounding_boxisNone:object_bounding_box=cv2.selectROI("Frame",stabilized_frame,fromCenter=False,showCrosshair=True)object_tracker.init(stabilized_frame,object_bounding_box)elifkey==27:breakvidcap.release()cv2.destroyAllWindows()Working with live videoTheVidStabclass can also process live video streams.  The underlying video reader iscv2.VideoCapture(documentation).
The relevant snippet from the documentation for stabilizing live video is:Its argument can be either the device index or the name of a video file. Device index is just the number to specify which camera. Normally one camera will be connected (as in my case). So I simply pass 0 (or -1). You can select the second camera by passing 1 and so on.Theinput_pathargument of theVidStab.stabilizemethod can accept integers that will be passed directly tocv2.VideoCaptureas a device index.  You can also pass a device index to the--inputargument for command line usage.One notable difference between live feeds and video files is that webcam footage does not have a definite end point.
The options for ending a live video stabilization are to set the max length using themax_framesargument or to manually stop the process by pressing theEsckey or theQkey.
Ifmax_framesis not provided then no progress bar can be displayed for live video stabilization processes.ExamplefromvidstabimportVidStabstabilizer=VidStab()stabilizer.stabilize(input_path=0,output_path='stable_webcam.avi',max_frames=1000,playback=True)Transform file writing & readingGenerating and saving transforms to fileimportnumpyasnpfromvidstabimportVidStab,download_ostrich_video# Download video if neededdownload_ostrich_video(INPUT_VIDEO_PATH)# Generate transforms and save to TRANSFORMATIONS_PATH as csv (no headers)stabilizer=VidStab()stabilizer.gen_transforms(INPUT_VIDEO_PATH)np.savetxt(TRANSFORMATIONS_PATH,stabilizer.transforms,delimiter=',')File atTRANSFORMATIONS_PATHis of the form shown below.  The 3 columns represent delta x, delta y, and delta angle respectively.-9.249733913760086068e+01,2.953221378387767970e+01,-2.875918912994855636e-02
-8.801434576214279559e+01,2.741942225927152776e+01,-2.715232319470826938e-02Reading and using transforms from fileBelow example reads a file of transforms and applies to an arbitrary video.  The transform file is of the form shown inabove section.importnumpyasnpfromvidstabimportVidStab# Read in csv transform data, of form (delta x, delta y, delta angle):transforms=np.loadtxt(TRANSFORMATIONS_PATH,delimiter=',')# Create stabilizer and supply numpy array of transformsstabilizer=VidStab()stabilizer.transforms=transforms# Apply stabilizing transforms to INPUT_VIDEO_PATH and save to OUTPUT_VIDEO_PATHstabilizer.apply_transforms(INPUT_VIDEO_PATH,OUTPUT_VIDEO_PATH)