36 #include <google/protobuf/util/time_util.h> 42 using 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)));
143 bool 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);
174 bool 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();
cv::Ptr< OPENCV_TRACKER_TYPE > selectTracker(std::string trackerType)
float Start() const
Get start position (in seconds) of clip (trim start of video)
Track an object selected by the user.
void SetJsonValue(const Json::Value root)
Load Json::Value into this object.
cv::Rect2d filter_box_jitter(size_t frameId)
Filter current bounding box jitter.
const Json::Value stringToJson(const std::string value)
FrameData GetTrackedData(size_t frameId)
Get tracked data for a given frame.
void Open() override
Open the internal reader.
CVTracker(std::string processInfoJson, ProcessingController &processingController)
void trackClip(openshot::Clip &video, size_t _start=0, size_t _end=0, bool process_interval=false)
This class represents a clip (used to arrange readers on the timeline)
Header file for OpenCVUtilities (set some common macros)
float End() const
Get end position (in seconds) of clip (trim end of video), which can be affected by the time curve...
void SetError(bool err, std::string message)
bool SaveTrackedData()
Save protobuf file.
void SetJson(const std::string value)
Load JSON string into this object.
This namespace is the default namespace for all code in the openshot library.
void AddFrameDataToProto(pb_tracker::Frame *pbFrameData, FrameData &fData)
Add frame tracked data into protobuf message.
Exception for invalid JSON.
void Reader(openshot::ReaderBase *new_reader)
Set the current reader.
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 ...