36#include <google/protobuf/util/time_util.h>
42using google::protobuf::util::TimeUtil;
46: processingController(&processingController), json_interval(false){
55 if (trackerType ==
"BOOSTING")
56 return OPENCV_TRACKER_NS::TrackerBoosting::create();
57 if (trackerType ==
"MIL")
58 return OPENCV_TRACKER_NS::TrackerMIL::create();
59 if (trackerType ==
"KCF")
60 return OPENCV_TRACKER_NS::TrackerKCF::create();
61 if (trackerType ==
"TLD")
62 return OPENCV_TRACKER_NS::TrackerTLD::create();
63 if (trackerType ==
"MEDIANFLOW")
64 return OPENCV_TRACKER_NS::TrackerMedianFlow::create();
65 if (trackerType ==
"MOSSE")
66 return OPENCV_TRACKER_NS::TrackerMOSSE::create();
67 if (trackerType ==
"CSRT")
68 return OPENCV_TRACKER_NS::TrackerCSRT::create();
78 start = _start; end = _end;
80 if(!process_interval || end <= 1 || end-start == 0){
82 start = (int)(video.
Start() * video.
Reader()->info.fps.ToFloat()) + 1;
83 end = (int)(video.
End() * video.
Reader()->info.fps.ToFloat()) + 1;
87 start = (int)(start + video.
Start() * video.
Reader()->info.fps.ToFloat()) + 1;
88 end = (int)(video.
End() * video.
Reader()->info.fps.ToFloat()) + 1;
95 processingController->
SetError(
false,
"");
96 bool trackerInit =
false;
100 for (frame = start; frame <= end; frame++)
108 size_t frame_number = frame;
110 std::shared_ptr<openshot::Frame> f = video.
GetFrame(frame_number);
113 cv::Mat cvimage = f->GetImageCV();
117 bbox = cv::Rect2d(bbox.x*cvimage.cols,bbox.y*cvimage.rows,bbox.width*cvimage.cols,
118 bbox.height*cvimage.rows);
125 initTracker(cvimage, frame_number);
131 trackerInit = trackFrame(cvimage, frame_number);
138 processingController->
SetProgress(uint(100*(frame_number-start)/(end-start)));
143bool CVTracker::initTracker(cv::Mat &frame,
size_t frameId){
150 bbox.x = bbox.x - abs(bbox.width);
151 bbox.width = abs(bbox.width);
154 bbox.y = bbox.y - abs(bbox.height);
155 bbox.height = abs(bbox.height);
159 tracker->init(frame, bbox);
161 float fw = frame.size().width;
162 float fh = frame.size().height;
165 trackedDataById[frameId] =
FrameData(frameId, 0, (bbox.x)/fw,
167 (bbox.x+bbox.width)/fw,
168 (bbox.y+bbox.height)/fh);
174bool CVTracker::trackFrame(cv::Mat &frame,
size_t frameId){
176 bool ok = tracker->update(frame, bbox);
182 float fw = frame.size().width;
183 float fh = frame.size().height;
187 trackedDataById[frameId] =
FrameData(frameId, 0, (filtered_box.x)/fw,
189 (filtered_box.x+filtered_box.width)/fw,
190 (filtered_box.y+filtered_box.height)/fh);
195 trackedDataById[frameId] = trackedDataById[frameId-1];
203 float last_box_width = trackedDataById[frameId-1].x2 - trackedDataById[frameId-1].x1;
204 float last_box_height = trackedDataById[frameId-1].y2 - trackedDataById[frameId-1].y1;
206 float curr_box_width = bbox.width;
207 float curr_box_height = bbox.height;
209 float threshold = 0.01;
211 cv::Rect2d filtered_box = bbox;
212 if(std::abs(1-(curr_box_width/last_box_width)) <= threshold){
213 filtered_box.width = last_box_width;
215 if(std::abs(1-(curr_box_height/last_box_height)) <= threshold){
216 filtered_box.height = last_box_height;
225 pb_tracker::Tracker trackerMessage;
228 for(std::map<size_t,FrameData>::iterator it=trackedDataById.begin(); it!=trackedDataById.end(); ++it){
230 pb_tracker::Frame* pbFrameData;
235 *trackerMessage.mutable_last_updated() = TimeUtil::SecondsToTimestamp(time(NULL));
239 std::fstream output(protobuf_data_path, ios::out | ios::trunc | ios::binary);
240 if (!trackerMessage.SerializeToOstream(&output)) {
241 std::cerr <<
"Failed to write protobuf message." << std::endl;
247 google::protobuf::ShutdownProtobufLibrary();
257 pbFrameData->set_id(fData.
frame_id);
258 pbFrameData->set_rotation(0);
260 pb_tracker::Frame::Box* box = pbFrameData->mutable_bounding_box();
262 box->set_x1(fData.
x1);
263 box->set_y1(fData.
y1);
264 box->set_x2(fData.
x2);
265 box->set_y2(fData.
y2);
272 if ( trackedDataById.find(frameId) == trackedDataById.end() ) {
277 return trackedDataById[frameId];
292 catch (
const std::exception& e)
303 if (!root[
"protobuf_data_path"].isNull()){
304 protobuf_data_path = (root[
"protobuf_data_path"].asString());
306 if (!root[
"tracker-type"].isNull()){
307 trackerType = (root[
"tracker-type"].asString());
310 if (!root[
"region"].isNull()){
311 double x = root[
"region"][
"normalized_x"].asDouble();
312 double y = root[
"region"][
"normalized_y"].asDouble();
313 double w = root[
"region"][
"normalized_width"].asDouble();
314 double h = root[
"region"][
"normalized_height"].asDouble();
315 cv::Rect2d prev_bbox(x,y,w,h);
319 processingController->
SetError(
true,
"No initial bounding box selected");
323 if (!root[
"region"][
"first-frame"].isNull()){
324 start = root[
"region"][
"first-frame"].asInt64();
325 json_interval =
true;
328 processingController->
SetError(
true,
"No first-frame");
344 pb_tracker::Tracker trackerMessage;
348 std::fstream input(protobuf_data_path, ios::in | ios::binary);
349 if (!trackerMessage.ParseFromIstream(&input)) {
350 std::cerr <<
"Failed to parse protobuf message." << std::endl;
356 trackedDataById.clear();
359 for (
size_t i = 0; i < trackerMessage.frame_size(); i++) {
360 const pb_tracker::Frame& pbFrameData = trackerMessage.frame(i);
363 size_t id = pbFrameData.id();
364 float rotation = pbFrameData.rotation();
367 const pb_tracker::Frame::Box& box = pbFrameData.bounding_box();
374 trackedDataById[id] =
FrameData(
id, rotation, x1, y1, x2, y2);
378 google::protobuf::ShutdownProtobufLibrary();
Track an object selected by the user.
Header file for OpenCVUtilities (set some common macros)
void SetError(bool err, std::string message)
void trackClip(openshot::Clip &video, size_t _start=0, size_t _end=0, bool process_interval=false)
bool SaveTrackedData()
Save protobuf file.
void SetJsonValue(const Json::Value root)
Load Json::Value into this object.
void SetJson(const std::string value)
Load JSON string into this object.
cv::Rect2d filter_box_jitter(size_t frameId)
Filter current bounding box jitter.
void AddFrameDataToProto(pb_tracker::Frame *pbFrameData, FrameData &fData)
Add frame tracked data into protobuf message.
FrameData GetTrackedData(size_t frameId)
Get tracked data for a given frame.
cv::Ptr< OPENCV_TRACKER_TYPE > selectTracker(std::string trackerType)
float Start() const
Get start position (in seconds) of clip (trim start of video)
This class represents a clip (used to arrange readers on the timeline)
void Open() override
Open the internal reader.
float End() const
Get end position (in seconds) of clip (trim end of video), which can be affected by the time curve.
std::shared_ptr< openshot::Frame > GetFrame(int64_t frame_number) override
Get an openshot::Frame object for a specific frame number of this clip. The image size and number of ...
void Reader(openshot::ReaderBase *new_reader)
Set the current reader.
Exception for invalid JSON.
This namespace is the default namespace for all code in the openshot library.
const Json::Value stringToJson(const std::string value)