Skip to content

Commit fc8d4d1

Browse files
committed
included CVStabilization into Clip
1 parent 791961c commit fc8d4d1

File tree

6 files changed

+151
-79
lines changed

6 files changed

+151
-79
lines changed

include/CVStabilization.h

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,59 @@
1+
/**
2+
* @file
3+
* @brief Header file for CVStabilization class
4+
* @author Jonathan Thomas <[email protected]>
5+
*
6+
* @ref License
7+
*/
8+
9+
/* LICENSE
10+
*
11+
* Copyright (c) 2008-2019 OpenShot Studios, LLC
12+
* <http://www.openshotstudios.com/>. This file is part of
13+
* OpenShot Library (libopenshot), an open-source project dedicated to
14+
* delivering high quality video editing and animation solutions to the
15+
* world. For more information visit <http://www.openshot.org/>.
16+
*
17+
* OpenShot Library (libopenshot) is free software: you can redistribute it
18+
* and/or modify it under the terms of the GNU Lesser General Public License
19+
* as published by the Free Software Foundation, either version 3 of the
20+
* License, or (at your option) any later version.
21+
*
22+
* OpenShot Library (libopenshot) is distributed in the hope that it will be
23+
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
24+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25+
* GNU Lesser General Public License for more details.
26+
*
27+
* You should have received a copy of the GNU Lesser General Public License
28+
* along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
29+
*/
30+
31+
#ifndef OPENSHOT_STABILIZATION_H
32+
#define OPENSHOT_STABILIZATION_H
33+
134
#define int64 opencv_broken_int
235
#define uint64 opencv_broken_uint
336
#include <opencv2/opencv.hpp>
437
#include <opencv2/core.hpp>
538
#undef uint64
639
#undef int64
740
#include <cmath>
8-
#include "Clip.h"
941

1042
using namespace std;
1143

12-
// struct TransformParam
13-
// {
14-
// TransformParam() {}
15-
// TransformParam(double _dx, double _dy, double _da) {
16-
// dx = _dx;
17-
// dy = _dy;
18-
// da = _da;
19-
// }
44+
struct TransformParam
45+
{
46+
TransformParam() {}
47+
TransformParam(double _dx, double _dy, double _da) {
48+
dx = _dx;
49+
dy = _dy;
50+
da = _da;
51+
}
2052

21-
// double dx;
22-
// double dy;
23-
// double da; // angle
24-
// };
53+
double dx;
54+
double dy;
55+
double da; // angle
56+
};
2557

2658
struct CamTrajectory
2759
{
@@ -44,13 +76,14 @@ class CVStabilization {
4476
cv::Mat prev, prev_grey;
4577

4678
public:
47-
const int SMOOTHING_RADIUS = 30; // In frames. The larger the more stable the video, but less reactive to sudden panning
48-
const int HORIZONTAL_BORDER_CROP = 20; // In pixels. Crops the border to reduce the black borders from stabilisation being too noticeable.
79+
const int smoothingWindow; // In frames. The larger the more stable the video, but less reactive to sudden panning
4980
std::vector <TransformParam> prev_to_cur_transform; // previous to current
5081

5182
CVStabilization();
5283

53-
void ProcessVideo(openshot::Clip &video);
84+
CVStabilization(int _smoothingWindow);
85+
86+
// void ProcessVideo(openshot::Clip &video);
5487

5588
// Track current frame features and find the relative transformation
5689
void TrackFrameFeatures(cv::Mat frame, int frameNum);
@@ -62,6 +95,8 @@ class CVStabilization {
6295
std::vector<TransformParam> GenNewCamPosition(std::vector <CamTrajectory> &smoothed_trajectory);
6396

6497
// Send smoothed camera transformation to be applyed on clip
65-
void ApplyNewTrajectoryToClip(openshot::Clip &video, std::vector <TransformParam> &new_prev_to_cur_transform);
98+
// void ApplyNewTrajectoryToClip(openshot::Clip &video, std::vector <TransformParam> &new_prev_to_cur_transform);
99+
100+
};
66101

67-
};
102+
#endif

include/Clip.h

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
#include <opencv2/core.hpp>
3939
#undef uint64
4040
#undef int64
41+
42+
#include "CVStabilization.h"
4143
#endif
4244

4345
#include <memory>
@@ -56,26 +58,9 @@
5658
#include "JuceHeader.h"
5759

5860

59-
60-
61-
// TODO: move to stabilization effect
62-
struct TransformParam
63-
{
64-
TransformParam() {}
65-
TransformParam(double _dx, double _dy, double _da) {
66-
dx = _dx;
67-
dy = _dy;
68-
da = _da;
69-
}
70-
71-
double dx;
72-
double dy;
73-
double da; // angle
74-
};
75-
76-
7761
namespace openshot {
7862

63+
7964
/// Comparison method for sorting effect pointers (by Position, Layer, and Order). Effects are sorted
8065
/// from lowest layer to top layer (since that is sequence clips are combined), and then by
8166
/// position, and then by effect order.
@@ -140,6 +125,14 @@ namespace openshot {
140125
/// (reader member variable itself may have been replaced)
141126
openshot::ReaderBase* allocated_reader;
142127

128+
#ifdef USE_OPENCV
129+
/// Smoothed transformation for all the clip frames
130+
std::vector <TransformParam> new_prev_to_cur_transform;
131+
/// apply the smoothed transformation warp when retrieving a frame
132+
bool hasStabilization = false;
133+
void apply_stabilization(std::shared_ptr<openshot::Frame> f, int64_t frame_number);
134+
#endif
135+
143136
/// Adjust frame number minimum value
144137
int64_t adjust_frame_number_minimum(int64_t frame_number);
145138

@@ -167,21 +160,15 @@ namespace openshot {
167160
/// Reverse an audio buffer
168161
void reverse_buffer(juce::AudioSampleBuffer* buffer);
169162

163+
164+
170165
public:
171166
openshot::GravityType gravity; ///< The gravity of a clip determines where it snaps to its parent
172167
openshot::ScaleType scale; ///< The scale determines how a clip should be resized to fit its parent
173168
openshot::AnchorType anchor; ///< The anchor determines what parent a clip should snap to
174169
openshot::FrameDisplayType display; ///< The format to display the frame number (if any)
175170
openshot::VolumeMixType mixing; ///< What strategy should be followed when mixing audio with other clips
176171

177-
178-
#ifdef USE_OPENCV
179-
std::vector <TransformParam> new_prev_to_cur_transform;
180-
bool hasStabilization = false;
181-
void apply_stabilization(std::shared_ptr<openshot::Frame> f, int64_t frame_number);
182-
#endif
183-
184-
185172
/// Default Constructor
186173
Clip();
187174

@@ -244,6 +231,9 @@ namespace openshot {
244231
bool Waveform() { return waveform; } ///< Get the waveform property of this clip
245232
void Waveform(bool value) { waveform = value; } ///< Set the waveform property of this clip
246233

234+
/// Stabilize the clip using opencv and opticalflow
235+
void stabilize_video();
236+
247237
// Scale, Location, and Alpha curves
248238
openshot::Keyframe scale_x; ///< Curve representing the horizontal scaling in percent (0 to 1)
249239
openshot::Keyframe scale_y; ///< Curve representing the vertical scaling in percent (0 to 1)

src/CVStabilization.cpp

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,48 @@
11
#include "../include/CVStabilization.h"
22

3-
CVStabilization::CVStabilization(){
43

5-
}
4+
CVStabilization::CVStabilization():smoothingWindow(30) {}
5+
6+
CVStabilization::CVStabilization(int _smoothingWindow): smoothingWindow(_smoothingWindow){}
7+
8+
// void CVStabilization::ProcessVideo(openshot::Clip &video){
9+
// // Make sure Clip is opened
10+
// video.Open();
11+
// // Get total number of frames
12+
// int videoLenght = video.Reader()->info.video_length;
13+
14+
// // Get first Opencv image
15+
// std::shared_ptr<openshot::Frame> f = video.GetFrame(0);
16+
// cv::Mat prev = f->GetImageCV();
17+
// // OpticalFlow works with grayscale images
18+
// cv::cvtColor(prev, prev_grey, cv::COLOR_BGR2GRAY);
619

7-
void CVStabilization::ProcessVideo(openshot::Clip &video){
8-
// Make sure Clip is opened
9-
video.Open();
10-
// Get total number of frames
11-
int videoLenght = video.Reader()->info.video_length;
12-
13-
// Get first Opencv image
14-
std::shared_ptr<openshot::Frame> f = video.GetFrame(0);
15-
cv::Mat prev = f->GetImageCV();
16-
// OpticalFlow works with grayscale images
17-
cv::cvtColor(prev, prev_grey, cv::COLOR_BGR2GRAY);
18-
19-
// Extract and track opticalflow features for each frame
20-
for (long int frame_number = 1; frame_number <= videoLenght; frame_number++)
21-
{
22-
std::shared_ptr<openshot::Frame> f = video.GetFrame(frame_number);
20+
// // Extract and track opticalflow features for each frame
21+
// for (long int frame_number = 1; frame_number <= videoLenght; frame_number++)
22+
// {
23+
// std::shared_ptr<openshot::Frame> f = video.GetFrame(frame_number);
2324

24-
// Grab Mat image
25-
cv::Mat cvimage = f->GetImageCV();
26-
cv::cvtColor(cvimage, cvimage, cv::COLOR_RGB2GRAY);
27-
TrackFrameFeatures(cvimage, frame_number);
28-
}
25+
// // Grab Mat image
26+
// cv::Mat cvimage = f->GetImageCV();
27+
// cv::cvtColor(cvimage, cvimage, cv::COLOR_RGB2GRAY);
28+
// TrackFrameFeatures(cvimage, frame_number);
29+
// }
2930

30-
vector <CamTrajectory> trajectory = ComputeFramesTrajectory();
31+
// vector <CamTrajectory> trajectory = ComputeFramesTrajectory();
3132

32-
vector <CamTrajectory> smoothed_trajectory = SmoothTrajectory(trajectory);
33+
// vector <CamTrajectory> smoothed_trajectory = SmoothTrajectory(trajectory);
3334

34-
vector <TransformParam> new_prev_to_cur_transform = GenNewCamPosition(smoothed_trajectory);
35+
// vector <TransformParam> new_prev_to_cur_transform = GenNewCamPosition(smoothed_trajectory);
3536

36-
ApplyNewTrajectoryToClip(video, new_prev_to_cur_transform);
37-
}
37+
// ApplyNewTrajectoryToClip(video, new_prev_to_cur_transform);
38+
// }
3839

3940
// Track current frame features and find the relative transformation
4041
void CVStabilization::TrackFrameFeatures(cv::Mat frame, int frameNum){
42+
if(prev_grey.empty()){
43+
prev_grey = frame;
44+
return;
45+
}
4146

4247
// OpticalFlow features vector
4348
vector <cv::Point2f> prev_corner, cur_corner;
@@ -113,7 +118,7 @@ vector <CamTrajectory> CVStabilization::SmoothTrajectory(vector <CamTrajectory>
113118
double sum_a = 0;
114119
int count = 0;
115120

116-
for(int j=-SMOOTHING_RADIUS; j <= SMOOTHING_RADIUS; j++) {
121+
for(int j=-smoothingWindow; j <= smoothingWindow; j++) {
117122
if(i+j >= 0 && i+j < trajectory.size()) {
118123
sum_x += trajectory[i+j].x;
119124
sum_y += trajectory[i+j].y;
@@ -164,9 +169,9 @@ vector <TransformParam> CVStabilization::GenNewCamPosition(vector <CamTrajectory
164169
return new_prev_to_cur_transform;
165170
}
166171

167-
// Send smoothed camera transformation to be applyed on clip
168-
void CVStabilization::ApplyNewTrajectoryToClip(openshot::Clip &video, vector <TransformParam> &new_prev_to_cur_transform){
172+
// // Send smoothed camera transformation to be applyed on clip
173+
// void CVStabilization::ApplyNewTrajectoryToClip(openshot::Clip &video, vector <TransformParam> &new_prev_to_cur_transform){
169174

170-
video.new_prev_to_cur_transform = new_prev_to_cur_transform;
171-
video.hasStabilization = true;
172-
}
175+
// video.new_prev_to_cur_transform = new_prev_to_cur_transform;
176+
// video.hasStabilization = true;
177+
// }

src/Clip.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,3 +1075,45 @@ std::shared_ptr<Frame> Clip::apply_effects(std::shared_ptr<Frame> frame)
10751075
// Return modified frame
10761076
return frame;
10771077
}
1078+
1079+
#ifdef USE_OPENCV
1080+
void Clip::stabilize_video(){
1081+
// create CVStabilization object
1082+
CVStabilization stabilizer;
1083+
1084+
// Make sure Clip is opened
1085+
Open();
1086+
// Get total number of frames
1087+
int videoLenght = Reader()->info.video_length;
1088+
1089+
// Get first Opencv image
1090+
// std::shared_ptr<openshot::Frame> f = GetFrame(0);
1091+
// cv::Mat prev = f->GetImageCV();
1092+
// // OpticalFlow works with grayscale images
1093+
// cv::cvtColor(prev, prev_grey, cv::COLOR_BGR2GRAY);
1094+
1095+
// Extract and track opticalflow features for each frame
1096+
for (long int frame_number = 0; frame_number <= videoLenght; frame_number++)
1097+
{
1098+
std::shared_ptr<openshot::Frame> f = GetFrame(frame_number);
1099+
1100+
// Grab Mat image
1101+
cv::Mat cvimage = f->GetImageCV();
1102+
cv::cvtColor(cvimage, cvimage, cv::COLOR_RGB2GRAY);
1103+
stabilizer.TrackFrameFeatures(cvimage, frame_number);
1104+
}
1105+
1106+
vector <CamTrajectory> trajectory = stabilizer.ComputeFramesTrajectory();
1107+
1108+
vector <CamTrajectory> smoothed_trajectory = stabilizer.SmoothTrajectory(trajectory);
1109+
1110+
// Get the smoothed trajectory
1111+
new_prev_to_cur_transform = stabilizer.GenNewCamPosition(smoothed_trajectory);
1112+
// Will apply the smoothed transformation warp when retrieving a frame
1113+
hasStabilization = true;
1114+
}
1115+
#else
1116+
void Clip::stabilize_video(){
1117+
throw "Please compile libopenshot with OpenCV to use this feature";
1118+
}
1119+
#endif

src/examples/Boneyard Memories.mp4

-78.8 MB
Binary file not shown.

src/examples/Example_opencv.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ int main(int argc, char* argv[]) {
164164
displayTrackedData(r9);
165165
if(SMOOTH_VIDEO){
166166
CVStabilization stabilization;
167-
stabilization.ProcessVideo(r9);
167+
r9.stabilize_video();
168168
displayStabilization(r9);
169169
}
170170

0 commit comments

Comments
 (0)