22 #include "objdetectdata.pb.h"
30 #include <QStringList>
36 ObjectDetection::ObjectDetection()
37 : display_box_text(1.0)
41 init_effect_details();
48 void ObjectDetection::init_effect_details()
66 std::shared_ptr<QImage> frame_image = frame->GetImage();
69 if(!frame_image || frame_image->isNull()) {
73 QPainter painter(frame_image.get());
74 painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
76 if (detectionsData.find(frame_number) != detectionsData.end()) {
78 for (
int i = 0; i < detections.
boxes.size(); i++) {
79 if (detections.
confidences.at(i) < confidence_threshold ||
80 (!display_classes.empty() &&
81 std::find(display_classes.begin(), display_classes.end(), classNames[detections.
classIds.at(i)]) == display_classes.end())) {
85 int objectId = detections.
objectIds.at(i);
89 std::shared_ptr<TrackedObjectBBox> trackedObject = std::static_pointer_cast<TrackedObjectBBox>(trackedObject_it->second);
92 if (parentClip && trackedObject->Contains(frame_number) && trackedObject->visible.GetValue(frame_number) == 1) {
93 BBox trackedBox = trackedObject->GetBox(frame_number);
94 QRectF boxRect((trackedBox.
cx - trackedBox.
width / 2) * frame_image->width(),
95 (trackedBox.
cy - trackedBox.
height / 2) * frame_image->height(),
96 trackedBox.
width * frame_image->width(),
97 trackedBox.
height * frame_image->height());
100 std::vector<int> stroke_rgba = trackedObject->stroke.GetColorRGBA(frame_number);
101 std::vector<int> bg_rgba = trackedObject->background.GetColorRGBA(frame_number);
102 int stroke_width = trackedObject->stroke_width.GetValue(frame_number);
103 float stroke_alpha = trackedObject->stroke_alpha.GetValue(frame_number);
104 float bg_alpha = trackedObject->background_alpha.GetValue(frame_number);
105 float bg_corner = trackedObject->background_corner.GetValue(frame_number);
108 QPen pen(QColor(stroke_rgba[0], stroke_rgba[1], stroke_rgba[2], 255 * stroke_alpha));
109 pen.setWidthF(trackedObject->ScaledStrokeWidth(
110 frame_number, frame_image->width(), frame_image->height()));
114 QBrush brush(QColor(bg_rgba[0], bg_rgba[1], bg_rgba[2], 255 * bg_alpha));
115 painter.setBrush(brush);
117 if (display_boxes.
GetValue(frame_number) == 1 && trackedObject->draw_box.GetValue(frame_number) == 1) {
119 painter.drawRoundedRect(boxRect, bg_corner, bg_corner);
122 if(display_box_text.
GetValue(frame_number) == 1) {
125 int classId = detections.
classIds.at(i);
128 QString label = QString::number(objectId);
129 if (!classNames.empty()) {
130 label = QString::fromStdString(classNames[classId]) +
":" + label;
135 font.setPixelSize(14);
136 painter.setFont(font);
139 QFontMetrics fontMetrics(font);
140 QSize labelSize = fontMetrics.size(Qt::TextSingleLine, label);
143 double left = boxRect.center().x() - (labelSize.width() / 2.0);
144 double top = std::max(
static_cast<int>(boxRect.top()), labelSize.height()) - 4.0;
147 painter.drawText(QPointF(left, top), label);
164 pb_objdetect::ObjDetect objMessage;
165 std::fstream input(inputFilePath, std::ios::in | std::ios::binary);
166 if (!objMessage.ParseFromIstream(&input)) {
167 std::cerr <<
"Failed to parse protobuf message." << std::endl;
173 detectionsData.clear();
178 for (
int i = 0; i < objMessage.classnames_size(); ++i) {
179 classNames.push_back(objMessage.classnames(i));
180 classesColor.push_back(cv::Scalar(
181 std::rand() % 205 + 50,
182 std::rand() % 205 + 50,
183 std::rand() % 205 + 50
188 for (
size_t fi = 0; fi < objMessage.frame_size(); ++fi) {
189 const auto &pbFrame = objMessage.frame(fi);
190 size_t frameId = pbFrame.id();
193 std::vector<int> classIds;
194 std::vector<float> confidences;
195 std::vector<cv::Rect_<float>> boxes;
196 std::vector<int> objectIds;
199 for (
int di = 0; di < pbFrame.bounding_box_size(); ++di) {
200 const auto &b = pbFrame.bounding_box(di);
201 float x = b.x(), y = b.y(), w = b.w(), h = b.h();
202 int classId = b.classid();
203 float confidence= b.confidence();
204 int objectId = b.objectid();
207 classIds.push_back(classId);
208 confidences.push_back(confidence);
209 boxes.emplace_back(x, y, w, h);
210 objectIds.push_back(objectId);
215 it->second->AddBox(frameId, x + w/2, y + h/2, w, h, 0.0);
220 (
int)classesColor[classId][0],
221 (
int)classesColor[classId][1],
222 (
int)classesColor[classId][2],
226 tmpObj.
AddBox(frameId, x + w/2, y + h/2, w, h, 0.0);
228 auto ptr = std::make_shared<TrackedObjectBBox>(tmpObj);
232 std::string prefix = this->
Id();
235 ptr->Id(prefix + std::to_string(objectId));
242 classIds, confidences, boxes, frameId, objectIds
246 google::protobuf::ShutdownProtobufLibrary();
261 root[
"visible_objects_index"] = Json::Value(Json::arrayValue);
262 root[
"visible_objects_id"] = Json::Value(Json::arrayValue);
263 root[
"visible_class_names"] = Json::Value(Json::arrayValue);
266 if (detectionsData.find(frame_number) == detectionsData.end()){
267 return root.toStyledString();
272 for(
int i = 0; i<detections.
boxes.size(); i++){
274 if(detections.
confidences.at(i) < confidence_threshold){
279 auto className = classNames[detections.
classIds.at(i)];
282 if (!display_classes.empty()) {
283 auto it = std::find(display_classes.begin(), display_classes.end(), className);
284 if (it == display_classes.end()) {
288 root[
"visible_class_names"].append(className);
291 root[
"visible_class_names"].append(className);
294 int objectId = detections.
objectIds.at(i);
299 Json::Value trackedObjectJSON = trackedObject->second->PropertiesJSON(frame_number);
301 if (trackedObjectJSON[
"visible"][
"value"].asBool() &&
302 trackedObject->second->ExactlyContains(frame_number)){
304 root[
"visible_objects_index"].append(trackedObject->first);
305 root[
"visible_objects_id"].append(trackedObject->second->Id());
309 return root.toStyledString();
313 if (!target_image || target_image->isNull())
316 auto detections_it = detectionsData.find(frame_number);
317 if (detections_it == detectionsData.end())
320 auto mask_image = std::make_shared<QImage>(
321 target_image->width(), target_image->height(), QImage::Format_RGBA8888_Premultiplied);
322 mask_image->fill(QColor(0, 0, 0, 255));
324 QPainter painter(mask_image.get());
325 painter.setRenderHint(QPainter::Antialiasing,
false);
326 painter.setPen(Qt::NoPen);
327 painter.setBrush(QBrush(QColor(255, 255, 255, 255)));
329 bool drew_any_box =
false;
331 for (
int i = 0; i < detections.
boxes.size(); i++) {
332 if (detections.
confidences.at(i) < confidence_threshold)
335 const int class_id = detections.
classIds.at(i);
336 if (class_id < 0 || class_id >= classNames.size())
339 const std::string class_name = classNames[class_id];
340 if (!display_classes.empty() &&
341 std::find(display_classes.begin(), display_classes.end(), class_name) == display_classes.end()) {
345 int object_id = detections.
objectIds.at(i);
347 if (tracked_object_it ==
trackedObjects.end() || !tracked_object_it->second)
350 auto tracked_object = std::static_pointer_cast<TrackedObjectBBox>(tracked_object_it->second);
351 if (!tracked_object->ExactlyContains(frame_number) ||
352 tracked_object->visible.GetValue(frame_number) != 1) {
356 BBox box = tracked_object->GetBox(frame_number);
357 if (box.
width <= 0.0f || box.
height <= 0.0f || box.
cx < 0.0f || box.
cy < 0.0f)
360 const double x = (box.
cx - box.
width / 2.0) * target_image->
width();
361 const double y = (box.
cy - box.
height / 2.0) * target_image->height();
362 const double w = box.
width * target_image->width();
363 const double h = box.
height * target_image->height();
364 painter.drawRect(QRectF(x, y, w, h));
387 root[
"protobuf_data_path"] = protobuf_data_path;
389 root[
"confidence_threshold"] = confidence_threshold;
390 root[
"display_box_text"] = display_box_text.
JsonValue();
391 root[
"display_boxes"] = display_boxes.
JsonValue();
396 Json::Value trackedObjectJSON = trackedObject.second->JsonValue();
398 objects[trackedObject.second->Id()] = trackedObjectJSON;
400 root[
"objects"] = objects;
416 catch (
const std::exception& e)
419 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
430 if (!root[
"protobuf_data_path"].isNull()) {
431 std::string new_path = root[
"protobuf_data_path"].asString();
433 protobuf_data_path = new_path;
435 throw InvalidFile(
"Invalid protobuf data path",
"");
441 if (!root[
"selected_object_index"].isNull())
443 if (!root[
"confidence_threshold"].isNull())
444 confidence_threshold = root[
"confidence_threshold"].asFloat();
445 if (!root[
"display_box_text"].isNull())
446 display_box_text.
SetJsonValue(root[
"display_box_text"]);
447 if (!root[
"display_boxes"].isNull())
450 if (!root[
"class_filter"].isNull()) {
451 class_filter = root[
"class_filter"].asString();
452 QStringList parts = QString::fromStdString(class_filter).split(
',');
453 display_classes.clear();
454 for (
auto &p : parts) {
455 auto s = p.trimmed().toLower();
457 display_classes.push_back(s.toStdString());
463 if (!root[
"objects"].isNull()) {
465 const auto memberNames = root[
"objects"].getMemberNames();
466 for (
const auto& name : memberNames)
470 bool numeric_key = std::all_of(name.begin(), name.end(), ::isdigit);
472 index = std::stoi(name);
476 size_t pos = name.find_last_of(
'-');
477 if (pos != std::string::npos) {
479 index = std::stoi(name.substr(pos + 1));
490 obj_it->second->Id(name);
491 obj_it->second->SetJsonValue(root[
"objects"][name]);
496 if (!root[
"objects_id"].isNull()) {
498 if (!root[
"objects_id"][kv.first].isNull())
499 kv.second->Id(root[
"objects_id"][kv.first].asString());
514 Json::Value trackedObjectJSON = selectedObject->PropertiesJSON(requested_frame);
516 objects[selectedObject->Id()] = trackedObjectJSON;
519 root[
"objects"] = objects;
522 root[
"confidence_threshold"] =
add_property_json(
"Confidence Theshold", confidence_threshold,
"float",
"", NULL, 0, 1,
false, requested_frame);
523 root[
"class_filter"] =
add_property_json(
"Class Filter", 0.0,
"string", class_filter, NULL, -1, -1,
false, requested_frame);
525 root[
"display_box_text"] =
add_property_json(
"Draw All Text", display_box_text.
GetValue(requested_frame),
"int",
"", &display_box_text, 0, 1,
false, requested_frame);
529 root[
"display_boxes"] =
add_property_json(
"Draw All Boxes", display_boxes.
GetValue(requested_frame),
"int",
"", &display_boxes, 0, 1,
false, requested_frame);
534 return root.toStyledString();