added YOLO output
This commit is contained in:
+133
-99
@@ -3,11 +3,13 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
#include <opencv2/core/core.hpp>
|
#include <opencv2/core/core.hpp>
|
||||||
#include <opencv2/highgui/highgui.hpp>
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
#include <opencv2/imgproc/imgproc.hpp>
|
#include <opencv2/imgproc/imgproc.hpp>
|
||||||
@@ -21,39 +23,42 @@
|
|||||||
#include <opencv2/cudaarithm.hpp>
|
#include <opencv2/cudaarithm.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace tk
|
||||||
|
{
|
||||||
|
namespace dnn
|
||||||
|
{
|
||||||
|
|
||||||
namespace tk { namespace dnn {
|
class DetectionNN
|
||||||
|
{
|
||||||
|
|
||||||
class DetectionNN {
|
protected:
|
||||||
|
tk::dnn::NetworkRT *netRT = nullptr;
|
||||||
|
dnnType *input_d;
|
||||||
|
|
||||||
protected:
|
std::vector<cv::Size> originalSize;
|
||||||
tk::dnn::NetworkRT *netRT = nullptr;
|
|
||||||
dnnType *input_d;
|
|
||||||
|
|
||||||
std::vector<cv::Size> originalSize;
|
cv::Scalar colors[256];
|
||||||
|
|
||||||
cv::Scalar colors[256];
|
int nBatches = 1;
|
||||||
|
|
||||||
int nBatches = 1;
|
|
||||||
|
|
||||||
#ifdef OPENCV_CUDACONTRIB
|
#ifdef OPENCV_CUDACONTRIB
|
||||||
cv::cuda::GpuMat bgr[3];
|
cv::cuda::GpuMat bgr[3];
|
||||||
cv::cuda::GpuMat imagePreproc;
|
cv::cuda::GpuMat imagePreproc;
|
||||||
#else
|
#else
|
||||||
cv::Mat bgr[3];
|
cv::Mat bgr[3];
|
||||||
cv::Mat imagePreproc;
|
cv::Mat imagePreproc;
|
||||||
dnnType *input;
|
dnnType *input;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method preprocess the image, before feeding it to the NN.
|
* This method preprocess the image, before feeding it to the NN.
|
||||||
*
|
*
|
||||||
* @param frame original frame to adapt for inference.
|
* @param frame original frame to adapt for inference.
|
||||||
* @param bi batch index
|
* @param bi batch index
|
||||||
*/
|
*/
|
||||||
virtual void preprocess(cv::Mat &frame, const int bi=0) = 0;
|
virtual void preprocess(cv::Mat &frame, const int bi = 0) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method postprocess the output of the NN to obtain the correct
|
* This method postprocess the output of the NN to obtain the correct
|
||||||
* boundig boxes.
|
* boundig boxes.
|
||||||
*
|
*
|
||||||
@@ -61,21 +66,21 @@ class DetectionNN {
|
|||||||
* @param mAP set to true only if all the probabilities for a bounding
|
* @param mAP set to true only if all the probabilities for a bounding
|
||||||
* box are needed, as in some cases for the mAP calculation
|
* box are needed, as in some cases for the mAP calculation
|
||||||
*/
|
*/
|
||||||
virtual void postprocess(const int bi=0,const bool mAP=false) = 0;
|
virtual void postprocess(const int bi = 0, const bool mAP = false) = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int classes = 0;
|
int classes = 0;
|
||||||
float confThreshold = 0.3; /*threshold on the confidence of the boxes*/
|
float confThreshold = 0.3; /*threshold on the confidence of the boxes*/
|
||||||
|
|
||||||
std::vector<tk::dnn::box> detected; /*bounding boxes in output*/
|
std::vector<tk::dnn::box> detected; /*bounding boxes in output*/
|
||||||
std::vector<std::vector<tk::dnn::box>> batchDetected; /*bounding boxes in output*/
|
std::vector<std::vector<tk::dnn::box>> batchDetected; /*bounding boxes in output*/
|
||||||
std::vector<double> stats; /*keeps track of inference times (ms)*/
|
std::vector<double> stats; /*keeps track of inference times (ms)*/
|
||||||
std::vector<std::string> classesNames;
|
std::vector<std::string> classesNames;
|
||||||
|
|
||||||
DetectionNN() {};
|
DetectionNN(){};
|
||||||
~DetectionNN(){};
|
~DetectionNN(){};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method used to inialize the class, allocate memory and compute
|
* Method used to inialize the class, allocate memory and compute
|
||||||
* needed data.
|
* needed data.
|
||||||
*
|
*
|
||||||
@@ -84,9 +89,9 @@ class DetectionNN {
|
|||||||
* @param n_batches maximum number of batches to use in inference
|
* @param n_batches maximum number of batches to use in inference
|
||||||
* @return true if everything is correct, false otherwise.
|
* @return true if everything is correct, false otherwise.
|
||||||
*/
|
*/
|
||||||
virtual bool init(const std::string& tensor_path, const int n_classes=80, const int n_batches=1) = 0;
|
virtual bool init(const std::string &tensor_path, const int n_classes = 80, const int n_batches = 1) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method performs the whole detection of the NN.
|
* This method performs the whole detection of the NN.
|
||||||
*
|
*
|
||||||
* @param frames frames to run detection on.
|
* @param frames frames to run detection on.
|
||||||
@@ -97,87 +102,116 @@ class DetectionNN {
|
|||||||
* @param mAP set to true only if all the probabilities for a bounding
|
* @param mAP set to true only if all the probabilities for a bounding
|
||||||
* box are needed, as in some cases for the mAP calculation
|
* box are needed, as in some cases for the mAP calculation
|
||||||
*/
|
*/
|
||||||
void update(std::vector<cv::Mat>& frames, const int cur_batches=1, bool save_times=false, std::ofstream *times=nullptr, const bool mAP=false){
|
void update(std::vector<cv::Mat> &frames, const int cur_batches = 1, bool save_times = false, std::ofstream *times = nullptr, const bool mAP = false)
|
||||||
if(save_times && times==nullptr)
|
|
||||||
FatalError("save_times set to true, but no valid ofstream given");
|
|
||||||
if(cur_batches > nBatches)
|
|
||||||
FatalError("A batch size greater than nBatches cannot be used");
|
|
||||||
|
|
||||||
originalSize.clear();
|
|
||||||
if(TKDNN_VERBOSE) printCenteredTitle(" TENSORRT detection ", '=', 30);
|
|
||||||
{
|
{
|
||||||
TKDNN_TSTART
|
if (save_times && times == nullptr)
|
||||||
for(int bi=0; bi<cur_batches;++bi){
|
FatalError("save_times set to true, but no valid ofstream given");
|
||||||
if(!frames[bi].data)
|
if (cur_batches > nBatches)
|
||||||
FatalError("No image data feed to detection");
|
FatalError("A batch size greater than nBatches cannot be used");
|
||||||
originalSize.push_back(frames[bi].size());
|
|
||||||
preprocess(frames[bi], bi);
|
originalSize.clear();
|
||||||
|
if (TKDNN_VERBOSE)
|
||||||
|
printCenteredTitle(" TENSORRT detection ", '=', 30);
|
||||||
|
{
|
||||||
|
TKDNN_TSTART
|
||||||
|
for (int bi = 0; bi < cur_batches; ++bi)
|
||||||
|
{
|
||||||
|
if (!frames[bi].data)
|
||||||
|
FatalError("No image data feed to detection");
|
||||||
|
originalSize.push_back(frames[bi].size());
|
||||||
|
preprocess(frames[bi], bi);
|
||||||
|
}
|
||||||
|
TKDNN_TSTOP
|
||||||
|
if (save_times)
|
||||||
|
*times << t_ns << ";";
|
||||||
|
}
|
||||||
|
|
||||||
|
//do inference
|
||||||
|
tk::dnn::dataDim_t dim = netRT->input_dim;
|
||||||
|
dim.n = cur_batches;
|
||||||
|
{
|
||||||
|
if (TKDNN_VERBOSE)
|
||||||
|
dim.print();
|
||||||
|
TKDNN_TSTART
|
||||||
|
netRT->infer(dim, input_d);
|
||||||
|
TKDNN_TSTOP
|
||||||
|
if (TKDNN_VERBOSE)
|
||||||
|
dim.print();
|
||||||
|
stats.push_back(t_ns);
|
||||||
|
if (save_times)
|
||||||
|
*times << t_ns << ";";
|
||||||
|
}
|
||||||
|
|
||||||
|
batchDetected.clear();
|
||||||
|
{
|
||||||
|
TKDNN_TSTART
|
||||||
|
for (int bi = 0; bi < cur_batches; ++bi)
|
||||||
|
postprocess(bi, mAP);
|
||||||
|
TKDNN_TSTOP
|
||||||
|
if (save_times)
|
||||||
|
*times << t_ns << "\n";
|
||||||
}
|
}
|
||||||
TKDNN_TSTOP
|
|
||||||
if(save_times) *times<<t_ns<<";";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//do inference
|
/**
|
||||||
tk::dnn::dataDim_t dim = netRT->input_dim;
|
|
||||||
dim.n = cur_batches;
|
|
||||||
{
|
|
||||||
if(TKDNN_VERBOSE) dim.print();
|
|
||||||
TKDNN_TSTART
|
|
||||||
netRT->infer(dim, input_d);
|
|
||||||
TKDNN_TSTOP
|
|
||||||
if(TKDNN_VERBOSE) dim.print();
|
|
||||||
stats.push_back(t_ns);
|
|
||||||
if(save_times) *times<<t_ns<<";";
|
|
||||||
}
|
|
||||||
|
|
||||||
batchDetected.clear();
|
|
||||||
{
|
|
||||||
TKDNN_TSTART
|
|
||||||
for(int bi=0; bi<cur_batches;++bi)
|
|
||||||
postprocess(bi, mAP);
|
|
||||||
TKDNN_TSTOP
|
|
||||||
if(save_times) *times<<t_ns<<"\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to draw boundixg boxes and labels on a frame.
|
* Method to draw boundixg boxes and labels on a frame.
|
||||||
*
|
*
|
||||||
* @param frames orginal frame to draw bounding box on.
|
* @param frames orginal frame to draw bounding box on.
|
||||||
|
* @param ext_yolo exports yolo style coorinates of bounding boxes on the terminal
|
||||||
*/
|
*/
|
||||||
void draw(std::vector<cv::Mat>& frames) {
|
void draw(std::vector<cv::Mat> &frames, bool ext_yolo)
|
||||||
tk::dnn::box b;
|
{
|
||||||
int x0, w, x1, y0, h, y1;
|
tk::dnn::box b;
|
||||||
int objClass;
|
int x0, w, x1, y0, h, y1;
|
||||||
std::string det_class;
|
int objClass;
|
||||||
|
std::string det_class;
|
||||||
|
|
||||||
int baseline = 0;
|
//yolo detctions output
|
||||||
float font_scale = 0.5;
|
std::string yoloBox;
|
||||||
int thickness = 2;
|
float Yx, Yy, Yw, Yh;
|
||||||
|
cv::Size sz = frames[0].size();
|
||||||
|
int imageWidth = sz.width;
|
||||||
|
int imageHeight = sz.height;
|
||||||
|
|
||||||
for(int bi=0; bi<frames.size(); ++bi){
|
int baseline = 0;
|
||||||
// draw dets
|
float font_scale = 0.5;
|
||||||
for(int i=0; i<batchDetected[bi].size(); i++) {
|
int thickness = 2;
|
||||||
b = batchDetected[bi][i];
|
|
||||||
x0 = b.x;
|
|
||||||
x1 = b.x + b.w;
|
|
||||||
y0 = b.y;
|
|
||||||
y1 = b.y + b.h;
|
|
||||||
det_class = classesNames[b.cl];
|
|
||||||
|
|
||||||
// draw rectangle
|
for (int bi = 0; bi < frames.size(); ++bi)
|
||||||
cv::rectangle(frames[bi], cv::Point(x0, y0), cv::Point(x1, y1), colors[b.cl], 2);
|
{
|
||||||
|
// draw dets
|
||||||
|
for (int i = 0; i < batchDetected[bi].size(); i++)
|
||||||
|
{
|
||||||
|
b = batchDetected[bi][i];
|
||||||
|
x0 = b.x;
|
||||||
|
x1 = b.x + b.w;
|
||||||
|
y0 = b.y;
|
||||||
|
y1 = b.y + b.h;
|
||||||
|
det_class = classesNames[b.cl];
|
||||||
|
|
||||||
// draw label
|
//yolo stuff
|
||||||
cv::Size text_size = getTextSize(det_class, cv::FONT_HERSHEY_SIMPLEX, font_scale, thickness, &baseline);
|
if (ext_yolo)
|
||||||
cv::rectangle(frames[bi], cv::Point(x0, y0), cv::Point((x0 + text_size.width - 2), (y0 - text_size.height - 2)), colors[b.cl], -1);
|
{
|
||||||
cv::putText(frames[bi], det_class, cv::Point(x0, (y0 - (baseline / 2))), cv::FONT_HERSHEY_SIMPLEX, font_scale, cv::Scalar(255, 255, 255), thickness);
|
Yx = (b.x + (int)(b.w / 2)) / imageWidth;
|
||||||
|
Yy = (b.y + (int)(b.h / 2)) / imageHeight;
|
||||||
|
Yw = b.w / imageWidth;
|
||||||
|
Yh = b.h / imageHeight;
|
||||||
|
std::cout << std::fixed << std::setprecision(6)<<b.cl<<" "<<Yx<<" "<<Yy<<" "<<Yw<<" "<<Yh<<"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw rectangle
|
||||||
|
cv::rectangle(frames[bi], cv::Point(x0, y0), cv::Point(x1, y1), colors[b.cl], 2);
|
||||||
|
|
||||||
|
// draw label
|
||||||
|
cv::Size text_size = getTextSize(det_class, cv::FONT_HERSHEY_SIMPLEX, font_scale, thickness, &baseline);
|
||||||
|
cv::rectangle(frames[bi], cv::Point(x0, y0), cv::Point((x0 + text_size.width - 2), (y0 - text_size.height - 2)), colors[b.cl], -1);
|
||||||
|
cv::putText(frames[bi], det_class, cv::Point(x0, (y0 - (baseline / 2))), cv::FONT_HERSHEY_SIMPLEX, font_scale, cv::Scalar(255, 255, 255), thickness);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
};
|
} // namespace dnn
|
||||||
|
} // namespace tk
|
||||||
}}
|
|
||||||
|
|
||||||
#endif /* DETECTIONNN_H*/
|
#endif /* DETECTIONNN_H*/
|
||||||
|
|||||||
Reference in New Issue
Block a user