22 #include "objdetectdata.pb.h"
28 #include <QStringList>
34 ObjectDetection::ObjectDetection()
35 : display_box_text(1.0)
39 init_effect_details();
46 void ObjectDetection::init_effect_details()
64 std::shared_ptr<QImage> frame_image = frame->GetImage();
67 if(!frame_image || frame_image->isNull()) {
71 QPainter painter(frame_image.get());
72 painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
74 if (detectionsData.find(frame_number) != detectionsData.end()) {
76 for (
int i = 0; i < detections.
boxes.size(); i++) {
77 if (detections.
confidences.at(i) < confidence_threshold ||
78 (!display_classes.empty() &&
79 std::find(display_classes.begin(), display_classes.end(), classNames[detections.
classIds.at(i)]) == display_classes.end())) {
83 int objectId = detections.
objectIds.at(i);
87 std::shared_ptr<TrackedObjectBBox> trackedObject = std::static_pointer_cast<TrackedObjectBBox>(trackedObject_it->second);
90 if (parentClip && trackedObject->Contains(frame_number) && trackedObject->visible.GetValue(frame_number) == 1) {
91 BBox trackedBox = trackedObject->GetBox(frame_number);
92 QRectF boxRect((trackedBox.
cx - trackedBox.
width / 2) * frame_image->width(),
93 (trackedBox.
cy - trackedBox.
height / 2) * frame_image->height(),
94 trackedBox.
width * frame_image->width(),
95 trackedBox.
height * frame_image->height());
98 std::vector<int> stroke_rgba = trackedObject->stroke.GetColorRGBA(frame_number);
99 std::vector<int> bg_rgba = trackedObject->background.GetColorRGBA(frame_number);
100 int stroke_width = trackedObject->stroke_width.GetValue(frame_number);
101 float stroke_alpha = trackedObject->stroke_alpha.GetValue(frame_number);
102 float bg_alpha = trackedObject->background_alpha.GetValue(frame_number);
103 float bg_corner = trackedObject->background_corner.GetValue(frame_number);
106 QPen pen(QColor(stroke_rgba[0], stroke_rgba[1], stroke_rgba[2], 255 * stroke_alpha));
107 pen.setWidthF(trackedObject->ScaledStrokeWidth(
108 frame_number, frame_image->width(), frame_image->height()));
112 QBrush brush(QColor(bg_rgba[0], bg_rgba[1], bg_rgba[2], 255 * bg_alpha));
113 painter.setBrush(brush);
115 if (display_boxes.
GetValue(frame_number) == 1 && trackedObject->draw_box.GetValue(frame_number) == 1) {
117 painter.drawRoundedRect(boxRect, bg_corner, bg_corner);
120 if(display_box_text.
GetValue(frame_number) == 1) {
123 int classId = detections.
classIds.at(i);
126 QString label = QString::number(objectId);
127 if (!classNames.empty()) {
128 label = QString::fromStdString(classNames[classId]) +
":" + label;
133 font.setPixelSize(14);
134 painter.setFont(font);
137 QFontMetrics fontMetrics(font);
138 QSize labelSize = fontMetrics.size(Qt::TextSingleLine, label);
141 double left = boxRect.center().x() - (labelSize.width() / 2.0);
142 double top = std::max(
static_cast<int>(boxRect.top()), labelSize.height()) - 4.0;
145 painter.drawText(QPointF(left, top), label);
162 pb_objdetect::ObjDetect objMessage;
163 std::fstream input(inputFilePath, std::ios::in | std::ios::binary);
164 if (!objMessage.ParseFromIstream(&input)) {
165 std::cerr <<
"Failed to parse protobuf message." << std::endl;
171 detectionsData.clear();
176 for (
int i = 0; i < objMessage.classnames_size(); ++i) {
177 classNames.push_back(objMessage.classnames(i));
178 classesColor.push_back(cv::Scalar(
179 std::rand() % 205 + 50,
180 std::rand() % 205 + 50,
181 std::rand() % 205 + 50
186 for (
size_t fi = 0; fi < objMessage.frame_size(); ++fi) {
187 const auto &pbFrame = objMessage.frame(fi);
188 size_t frameId = pbFrame.id();
191 std::vector<int> classIds;
192 std::vector<float> confidences;
193 std::vector<cv::Rect_<float>> boxes;
194 std::vector<int> objectIds;
197 for (
int di = 0; di < pbFrame.bounding_box_size(); ++di) {
198 const auto &b = pbFrame.bounding_box(di);
199 float x = b.x(), y = b.y(), w = b.w(), h = b.h();
200 int classId = b.classid();
201 float confidence= b.confidence();
202 int objectId = b.objectid();
205 classIds.push_back(classId);
206 confidences.push_back(confidence);
207 boxes.emplace_back(x, y, w, h);
208 objectIds.push_back(objectId);
213 it->second->AddBox(frameId, x + w/2, y + h/2, w, h, 0.0);
218 (
int)classesColor[classId][0],
219 (
int)classesColor[classId][1],
220 (
int)classesColor[classId][2],
224 tmpObj.
AddBox(frameId, x + w/2, y + h/2, w, h, 0.0);
226 auto ptr = std::make_shared<TrackedObjectBBox>(tmpObj);
230 std::string prefix = this->
Id();
233 ptr->Id(prefix + std::to_string(objectId));
240 classIds, confidences, boxes, frameId, objectIds
244 google::protobuf::ShutdownProtobufLibrary();
259 root[
"visible_objects_index"] = Json::Value(Json::arrayValue);
260 root[
"visible_objects_id"] = Json::Value(Json::arrayValue);
261 root[
"visible_class_names"] = Json::Value(Json::arrayValue);
264 if (detectionsData.find(frame_number) == detectionsData.end()){
265 return root.toStyledString();
270 for(
int i = 0; i<detections.
boxes.size(); i++){
272 if(detections.
confidences.at(i) < confidence_threshold){
277 auto className = classNames[detections.
classIds.at(i)];
280 if (!display_classes.empty()) {
281 auto it = std::find(display_classes.begin(), display_classes.end(), className);
282 if (it == display_classes.end()) {
286 root[
"visible_class_names"].append(className);
289 root[
"visible_class_names"].append(className);
292 int objectId = detections.
objectIds.at(i);
297 Json::Value trackedObjectJSON = trackedObject->second->PropertiesJSON(frame_number);
299 if (trackedObjectJSON[
"visible"][
"value"].asBool() &&
300 trackedObject->second->ExactlyContains(frame_number)){
302 root[
"visible_objects_index"].append(trackedObject->first);
303 root[
"visible_objects_id"].append(trackedObject->second->Id());
307 return root.toStyledString();
323 root[
"protobuf_data_path"] = protobuf_data_path;
325 root[
"confidence_threshold"] = confidence_threshold;
326 root[
"display_box_text"] = display_box_text.
JsonValue();
327 root[
"display_boxes"] = display_boxes.
JsonValue();
332 Json::Value trackedObjectJSON = trackedObject.second->JsonValue();
334 objects[trackedObject.second->Id()] = trackedObjectJSON;
336 root[
"objects"] = objects;
352 catch (
const std::exception& e)
355 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
366 if (!root[
"protobuf_data_path"].isNull()) {
367 std::string new_path = root[
"protobuf_data_path"].asString();
369 protobuf_data_path = new_path;
371 throw InvalidFile(
"Invalid protobuf data path",
"");
377 if (!root[
"selected_object_index"].isNull())
379 if (!root[
"confidence_threshold"].isNull())
380 confidence_threshold = root[
"confidence_threshold"].asFloat();
381 if (!root[
"display_box_text"].isNull())
382 display_box_text.
SetJsonValue(root[
"display_box_text"]);
383 if (!root[
"display_boxes"].isNull())
386 if (!root[
"class_filter"].isNull()) {
387 class_filter = root[
"class_filter"].asString();
388 QStringList parts = QString::fromStdString(class_filter).split(
',');
389 display_classes.clear();
390 for (
auto &p : parts) {
391 auto s = p.trimmed().toLower();
393 display_classes.push_back(s.toStdString());
399 if (!root[
"objects"].isNull()) {
401 const auto memberNames = root[
"objects"].getMemberNames();
402 for (
const auto& name : memberNames)
406 bool numeric_key = std::all_of(name.begin(), name.end(), ::isdigit);
408 index = std::stoi(name);
412 size_t pos = name.find_last_of(
'-');
413 if (pos != std::string::npos) {
415 index = std::stoi(name.substr(pos + 1));
426 obj_it->second->Id(name);
427 obj_it->second->SetJsonValue(root[
"objects"][name]);
432 if (!root[
"objects_id"].isNull()) {
434 if (!root[
"objects_id"][kv.first].isNull())
435 kv.second->Id(root[
"objects_id"][kv.first].asString());
450 Json::Value trackedObjectJSON = selectedObject->PropertiesJSON(requested_frame);
452 objects[selectedObject->Id()] = trackedObjectJSON;
455 root[
"objects"] = objects;
458 root[
"confidence_threshold"] =
add_property_json(
"Confidence Theshold", confidence_threshold,
"float",
"", NULL, 0, 1,
false, requested_frame);
459 root[
"class_filter"] =
add_property_json(
"Class Filter", 0.0,
"string", class_filter, NULL, -1, -1,
false, requested_frame);
461 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);
465 root[
"display_boxes"] =
add_property_json(
"Draw All Boxes", display_boxes.
GetValue(requested_frame),
"int",
"", &display_boxes, 0, 1,
false, requested_frame);
470 return root.toStyledString();