MCPcopy Create free account
hub / github.com/OpenShot/libopenshot / TrackFrameFeatures

Method TrackFrameFeatures

src/CVStabilization.cpp:106–185  ·  view source on GitHub ↗

Track current frame features and find the relative transformation

Source from the content-addressed store, hash-verified

104
105// Track current frame features and find the relative transformation
106bool CVStabilization::TrackFrameFeatures(cv::Mat frame, size_t frameNum){
107 // Check if there are black frames
108 if(cv::countNonZero(frame) < 1){
109 return false;
110 }
111
112 // Initialize prev_grey if not
113 if(prev_grey.empty()){
114 prev_grey = frame;
115 return true;
116 }
117
118 // OpticalFlow features vector
119 std::vector <cv::Point2f> prev_corner, cur_corner;
120 std::vector <cv::Point2f> prev_corner2, cur_corner2;
121 std::vector <uchar> status;
122 std::vector <float> err;
123 // Extract new image features
124 cv::goodFeaturesToTrack(prev_grey, prev_corner, 200, 0.01, 30);
125 // Track features
126 cv::calcOpticalFlowPyrLK(prev_grey, frame, prev_corner, cur_corner, status, err);
127 // Remove untracked features
128 for(size_t i=0; i < status.size(); i++) {
129 if(status[i]) {
130 prev_corner2.push_back(prev_corner[i]);
131 cur_corner2.push_back(cur_corner[i]);
132 }
133 }
134 // In case no feature was detected
135 if(prev_corner2.empty() || cur_corner2.empty()){
136 last_T = cv::Mat();
137 // prev_grey = cv::Mat();
138 return false;
139 }
140
141 // Translation + rotation only
142 cv::Mat T = cv::estimateAffinePartial2D(prev_corner2, cur_corner2); // false = rigid transform, no scaling/shearing
143
144 double da, dx, dy;
145 // If T has nothing inside return (probably a segment where there is nothing to stabilize)
146 if(T.size().width == 0 || T.size().height == 0){
147 return false;
148 }
149 else{
150 // If no transformation is found, just use the last known good transform
151 if(T.data == NULL){
152 if(!last_T.empty())
153 last_T.copyTo(T);
154 else
155 return false;
156 }
157 // Decompose T
158 dx = T.at<double>(0,2);
159 dy = T.at<double>(1,2);
160 da = atan2(T.at<double>(1,0), T.at<double>(0,0));
161 }
162
163 // Filter transformations parameters, if they are higher than these: return

Callers

nothing calls this directly

Calls 1

TransformParamClass · 0.85

Tested by

no test coverage detected