23 #include "trackerdata.pb.h"
24 #include <google/protobuf/util/time_util.h>
26 using google::protobuf::util::TimeUtil;
31 std::vector<uint32_t> encode_object_mask_rle(
const std::vector<uint8_t>& mask)
33 std::vector<uint32_t> rle;
36 for (uint8_t value : mask) {
37 value = value ? 1 : 0;
38 if (value == current) {
50 std::vector<uint8_t> decode_object_mask_rle(
const ObjectMaskData& mask)
52 std::vector<uint8_t> decoded(
static_cast<size_t>(mask.
width * mask.
height), 0);
55 for (uint32_t count : mask.
rle) {
56 const int end = std::min(mask.
width * mask.
height, offset +
static_cast<int>(count));
58 std::fill(decoded.begin() + offset, decoded.begin() + end,
static_cast<uint8_t
>(1));
69 const BBox& source_box,
70 const BBox& target_box)
74 source_box.
width <= 0.0f || source_box.
height <= 0.0f ||
75 target_box.
width <= 0.0f || target_box.
height <= 0.0f)
78 const float source_left = (source_box.
cx - source_box.
width / 2.0f) * source_mask.
width;
79 const float source_top = (source_box.
cy - source_box.
height / 2.0f) * source_mask.
height;
80 const float source_width = source_box.
width * source_mask.
width;
81 const float source_height = source_box.
height * source_mask.
height;
82 const float target_left = (target_box.
cx - target_box.
width / 2.0f) * source_mask.
width;
83 const float target_top = (target_box.
cy - target_box.
height / 2.0f) * source_mask.
height;
84 const float target_width = target_box.
width * source_mask.
width;
85 const float target_height = target_box.
height * source_mask.
height;
86 if (source_width <= 0.0f || source_height <= 0.0f || target_width <= 0.0f || target_height <= 0.0f)
89 const std::vector<uint8_t> source = decode_object_mask_rle(source_mask);
90 std::vector<uint8_t> transformed(
static_cast<size_t>(source_mask.
width * source_mask.
height), 0);
91 const int min_x = std::max(0,
static_cast<int>(std::floor(target_left)));
92 const int min_y = std::max(0,
static_cast<int>(std::floor(target_top)));
93 const int max_x = std::min(source_mask.
width,
static_cast<int>(std::ceil(target_left + target_width)));
94 const int max_y = std::min(source_mask.
height,
static_cast<int>(std::ceil(target_top + target_height)));
95 for (
int y = min_y; y < max_y; ++y) {
96 for (
int x = min_x; x < max_x; ++x) {
97 const float source_x = source_left + (
static_cast<float>(x) - target_left) * source_width / target_width;
98 const float source_y = source_top + (
static_cast<float>(y) - target_top) * source_height / target_height;
99 const int sx =
static_cast<int>(std::round(source_x));
100 const int sy =
static_cast<int>(std::round(source_y));
101 if (sx < 0 || sx >= source_mask.
width || sy < 0 || sy >= source_mask.
height)
103 if (source[
static_cast<size_t>(sy * source_mask.
width + sx)])
104 transformed[
static_cast<size_t>(y * source_mask.
width + x)] = 1;
108 if (std::none_of(transformed.begin(), transformed.end(), [](uint8_t value) { return value != 0; }))
112 result.
rle = encode_object_mask_rle(transformed);
124 : delta_x(0.0), delta_y(0.0),
125 scale_x(1.0), scale_y(1.0),
126 background_alpha(0.0), background_corner(12),
127 mask_alpha(120.0 / 255.0),
128 stroke_width(2) , stroke_alpha(0.7),
129 stroke(Red, Green, Blue, Alfa),
130 background(Red, Green, Blue, Alfa),
131 mask_color(Red, Green, Blue, Alfa)
133 this->TimeScale = 1.0;
144 BBox newBBox =
BBox(_cx, _cy, _width, _height, _angle);
149 auto BBoxIterator =
BoxVec.find(time);
151 if (BBoxIterator !=
BoxVec.end())
154 BBoxIterator->second = newBBox;
159 BoxVec.insert({time, newBBox});
165 if (frame_num < 0 || !mask.
HasData())
188 if (max_frame_gap <= 0 ||
MaskVec.empty())
191 auto after =
MaskVec.lower_bound(time);
195 auto before = std::prev(after);
197 if (time - before->first <= max_gap_time + 0.000001) {
198 auto source_box =
BoxVec.find(before->first);
199 auto target_box =
BoxVec.find(time);
200 if (source_box !=
BoxVec.end() && target_box !=
BoxVec.end())
201 return transform_mask_between_boxes(before->second, source_box->second, target_box->second);
202 return before->second;
223 auto it =
BoxVec.lower_bound(time);
237 auto it =
BoxVec.find(time);
251 auto it =
BoxVec.find(time);
264 double time = this->
FrameNToTime(frame_number, this->TimeScale);
268 auto currentBBoxIterator =
BoxVec.lower_bound(time);
271 if (currentBBoxIterator ==
BoxVec.end())
279 if ((currentBBoxIterator->first == time) || (currentBBoxIterator ==
BoxVec.begin()))
282 BBox currentBBox = currentBBoxIterator->second;
293 BBox currentBBox = currentBBoxIterator->second;
295 BBox previousBBox = prev(currentBBoxIterator, 1)->second;
298 BBox interpolatedBBox =
InterpolateBoxes(prev(currentBBoxIterator, 1)->first, currentBBoxIterator->first,
299 previousBBox, currentBBox, time);
306 return interpolatedBBox;
311 const double base_width = std::max(0.0,
static_cast<double>(
stroke_width.
GetValue(frame_number)));
313 if (!parent_clip || image_width <= 0 || image_height <= 0)
316 int target_width = image_width;
317 int target_height = image_height;
326 QSize output_size(image_width, image_height);
327 switch (parent_clip->
scale) {
329 output_size.scale(target_width, target_height, Qt::KeepAspectRatio);
332 output_size.scale(target_width, target_height, Qt::IgnoreAspectRatio);
335 output_size.scale(target_width, target_height, Qt::KeepAspectRatioByExpanding);
341 if (output_size.width() <= 0 || output_size.height() <= 0)
344 const double raster_scale_x =
static_cast<double>(output_size.width()) / image_width;
345 const double raster_scale_y =
static_cast<double>(output_size.height()) / image_height;
346 const double raster_scale = std::sqrt(raster_scale_x * raster_scale_y);
347 return base_width * std::max(raster_scale, 1.0 / std::max(raster_scale, 0.000001));
381 return interpolatedBox;
397 double time = ((double)frame_number) * this->BaseFps.
Reciprocal().
ToDouble() * (1.0 / time_scale);
404 this->TimeScale = time_scale;
413 pb_tracker::Tracker bboxMessage;
416 std::fstream input(inputFilePath, ios::in | ios::binary);
419 if (!bboxMessage.ParseFromIstream(&input))
421 std::cerr <<
"Failed to parse protobuf message." << std::endl;
428 for (
size_t i = 0; i < bboxMessage.frame_size(); i++)
431 const pb_tracker::Frame &pbFrameData = bboxMessage.frame(i);
434 size_t frame_number = pbFrameData.id();
437 const pb_tracker::Frame::Box &box = pbFrameData.bounding_box();
439 float width = box.x2() - box.x1();
440 float height = box.y2() - box.y1();
441 float cx = box.x1() + width/2;
442 float cy = box.y1() + height/2;
446 if ( (cx >= 0.0) && (cy >= 0.0) && (width >= 0.0) && (height >= 0.0) )
449 this->
AddBox(frame_number, cx, cy, width, height, angle);
454 if (bboxMessage.has_last_updated())
456 std::cout <<
" Loaded Data. Saved Time Stamp: "
457 << TimeUtil::ToString(bboxMessage.last_updated()) << std::endl;
461 google::protobuf::ShutdownProtobufLibrary();
487 root[
"box_id"] =
Id();
488 root[
"BaseFPS"][
"num"] = BaseFps.
num;
489 root[
"BaseFPS"][
"den"] = BaseFps.
den;
490 root[
"TimeScale"] = TimeScale;
526 catch (
const std::exception &e)
529 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
539 if (!root[
"box_id"].isNull() && root[
"box_id"].asString() !=
"")
540 Id(root[
"box_id"].asString());
543 if (!root[
"BaseFPS"].isNull() && root[
"BaseFPS"].isObject())
545 if (!root[
"BaseFPS"][
"num"].isNull())
546 BaseFps.
num = (int)root[
"BaseFPS"][
"num"].asInt();
547 if (!root[
"BaseFPS"][
"den"].isNull())
548 BaseFps.
den = (
int)root[
"BaseFPS"][
"den"].asInt();
551 if (!root[
"TimeScale"].isNull())
553 double scale = (double)root[
"TimeScale"].asDouble();
557 if (!root[
"protobuf_data_path"].isNull())
561 if (!root[
"delta_x"].isNull())
563 if (!root[
"delta_y"].isNull())
565 if (!root[
"scale_x"].isNull())
567 if (!root[
"scale_y"].isNull())
569 if (!root[
"visible"].isNull())
571 if (!root[
"draw_box"].isNull())
573 if (!root[
"draw_text"].isNull())
575 if (!root[
"draw_mask"].isNull())
577 if (!root[
"mask_alpha"].isNull())
579 if (!root[
"mask_color"].isNull())
581 if (!root[
"stroke"].isNull())
583 if (!root[
"background_alpha"].isNull())
585 if (!root[
"background_corner"].isNull())
587 if (!root[
"background"].isNull())
589 if (!root[
"stroke_width"].isNull())
591 if (!root[
"stroke_alpha"].isNull())
605 root[
"box_id"] =
add_property_json(
"Box ID", 0.0,
"string",
Id(), NULL, -1, -1,
true, requested_frame);
633 root[
"mask_color"] =
add_property_json(
"Mask Color", 0.0,
"color",
"", NULL, 0, 255,
false, requested_frame);
640 root[
"stroke"] =
add_property_json(
"Border", 0.0,
"color",
"", NULL, 0, 255,
false, requested_frame);
650 root[
"background"] =
add_property_json(
"Background", 0.0,
"color",
"", NULL, 0, 255,
false, requested_frame);
664 const Point requested_point(requested_frame, requested_frame);
667 Json::Value prop = Json::Value(Json::objectValue);
669 prop[
"value"] = value;
672 prop[
"min"] = min_value;
673 prop[
"max"] = max_value;
675 prop[
"keyframe"] = keyframe->
Contains(requested_point);
676 prop[
"points"] = int(keyframe->
GetCount());
679 prop[
"closest_point_x"] = closest_point.
co.
X;
683 prop[
"keyframe"] =
false;
686 prop[
"closest_point_x"] = -1;
687 prop[
"previous_point_x"] = -1;
690 prop[
"readonly"] = readonly;
691 prop[
"choices"] = Json::Value(Json::arrayValue);
701 std::map<std::string, float> boxValues;
707 boxValues[
"cx"] = box.
cx;
708 boxValues[
"cy"] = box.
cy;
709 boxValues[
"w"] = box.
width;
710 boxValues[
"h"] = box.
height;
711 boxValues[
"ang"] = box.
angle;