提交 00b9954e authored 作者: blu's avatar blu

yolo

上级 eb73e47d
CC = g++ CC = g++
CFLAGS = -g -Wall -std=c++11 CFLAGS = -g -Wall -std=c++2a
SRCS = main.cpp SRCS = main.origin.cpp
PROG = main PROG = main
SRCS2 = main.cpp
PROG2 = yolo
OPENCV = `pkg-config opencv4 --cflags --libs` OPENCV = `pkg-config opencv4 --cflags --libs`
LIBS = $(OPENCV) LIBS = $(OPENCV)
all: $(PROG) $(PROG2)
$(PROG):$(SRCS) $(PROG):$(SRCS)
$(CC) $(CFLAGS) -o $(PROG) $(SRCS) $(LIBS) $(CC) $(CFLAGS) -o $(PROG) $(SRCS) $(LIBS)
$(PROG2):$(SRCS2)
$(CC) $(CFLAGS) -o $(PROG2) $(SRCS2) $(LIBS) -I../opencv-motion-detect/inc -I../opencv-motion-detect/vendor/include
\ No newline at end of file
// This code is written at BigVision LLC. It is based on the OpenCV project. It is subject to the license terms in the LICENSE file found in this distribution and at http://opencv.org/license.html
// Usage example: ./object_detection_yolo.out --video=run.mp4
// ./object_detection_yolo.out --image=bird.jpg
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include <tuple>
#include "fs.h"
#include "spdlog/spdlog.h"
#ifdef _MY_HEADERS_ #ifdef _MY_HEADERS_
#include <opencv2/core/types_c.h> #include <opencv2/core/types_c.h>
...@@ -16,22 +15,10 @@ ...@@ -16,22 +15,10 @@
#include <opencv2/opencv.hpp> #include <opencv2/opencv.hpp>
#endif #endif
const char* keys =
"{help h usage ? | | Usage examples: \n\t\t./PROG --image=dog.jpg \n\t\t./object_detection_yolo.out --video=run_sm.mp4}"
"{image i |<none>| input image }"
"{video v |<none>| input video }"
;
using namespace cv; using namespace cv;
using namespace dnn; using namespace dnn;
using namespace std; using namespace std;
// Initialize the parameters
float confThreshold = 0.5; // Confidence threshold
float nmsThreshold = 0.4; // Non-maximum suppression threshold
int inpWidth = 416; // Width of network's input image
int inpHeight = 416; // Height of network's input image
vector<string> classes;
// Remove the bounding boxes with low confidence using non-maxima suppression // Remove the bounding boxes with low confidence using non-maxima suppression
int postprocess(Mat& frame, const vector<Mat>& out); int postprocess(Mat& frame, const vector<Mat>& out);
...@@ -41,167 +28,83 @@ void drawPred(int classId, float conf, int left, int top, int right, int bottom, ...@@ -41,167 +28,83 @@ void drawPred(int classId, float conf, int left, int top, int right, int bottom,
// Get the names of the output layers // Get the names of the output layers
vector<String> getOutputsNames(const Net& net); vector<String> getOutputsNames(const Net& net);
int main(int argc, char** argv)
{
CommandLineParser parser(argc, argv, keys);
parser.about("Use this script to run object detection using YOLO3 in OpenCV.");
if (parser.has("help"))
{
parser.printMessage();
return 0;
}
// Load names of classes
string classesFile = "coco.names";
ifstream ifs(classesFile.c_str());
string line;
while (getline(ifs, line)) classes.push_back(line);
// Give the configuration and weight files for the model
String modelConfiguration = "yolov3-tiny.cfg";
String modelWeights = "yolov3-tiny.weights";
// Load the network
Net net = readNetFromDarknet(modelConfiguration, modelWeights);
net.setPreferableBackend(DNN_BACKEND_OPENCV);
net.setPreferableTarget(DNN_TARGET_CPU);
// Open a video file or an image file or a camera stream. class YoloDectect {
string str, outputFile; private:
// Initialize the parameters
const string selfId = "YoloDetector";
float confThreshold = 0.5; // Confidence threshold
float nmsThreshold = 0.4; // Non-maximum suppression threshold
int inpWidth = 416; // Width of network's input image
int inpHeight = 416; // Height of network's input image
vector<string> classes;
Net net;
Mat blob;
VideoCapture cap; VideoCapture cap;
VideoWriter video; VideoWriter video;
Mat frame, blob; bool bOutputIsImg = false;
string outFileBase;
bool cmdStop = false;
try { // Get the names of the output layers
outputFile = "yolo_out_cpp.avi"; vector<String> getOutputsNames(const Net& net)
if (parser.has("image"))
{
// Open the image file
str = parser.get<String>("image");
ifstream ifile(str);
if (!ifile) throw("error");
cap.open(str);
str.replace(str.end()-4, str.end(), "_yolo_out_cpp"); //.jpg
outputFile = str;
}
else if (parser.has("video"))
{ {
// Open the video file static vector<String> names;
str = parser.get<String>("video"); if (names.empty()) {
//ifstream ifile(str); //Get the indices of the output layers, i.e. the layers with unconnected outputs
//if (!ifile) throw("error"); vector<int> outLayers = net.getUnconnectedOutLayers();
cout << "open video stream: " << str << endl;
if(!cap.open(str)){
cout << "failed to open video stream: " << str << endl;
}
str.replace(str.end()-4, str.end(), "_yolo_out_cpp.avi");
}else{
// Open the webcaom
cap.open(parser.get<int>("device"));
}
cout << "output file: " << outputFile << endl; //get the names of all the layers in the network
vector<String> layersNames = net.getLayerNames();
// Get the names of the output layers in names
names.resize(outLayers.size());
for (size_t i = 0; i < outLayers.size(); ++i)
names[i] = layersNames[outLayers[i] - 1];
} }
catch(...) { return names;
cout << "Could not open the input image/video stream" << endl;
return 0;
}
// Get the video writer initialized to save the output video
if (!parser.has("image")) {
video.open(outputFile, VideoWriter::fourcc('M','J','P','G'), 28, Size(cap.get(CAP_PROP_FRAME_WIDTH), cap.get(CAP_PROP_FRAME_HEIGHT)));
} }
// Create a window // draw the predicted bounding box
//static const string kWinName = "Deep learning object detection in OpenCV"; void drawPred(int classId, float conf, int left, int top, int right, int bottom, Mat& frame)
//namedWindow(kWinName, WINDOW_NORMAL);
// Process frames.
long frameCnt = 0;
long detCnt = 0;
while (waitKey(1) < 0)
{ {
// get frame from the video // draw a rectangle displaying the bounding box
if(!cap.read(frame)) { rectangle(frame, Point(left, top), Point(right, bottom), Scalar(255, 178, 50), 3);
cout << "failed to open video stream" << endl;
break;
}
cout << "frameCnt: " << frameCnt << endl;
frameCnt++;
// Stop the program if reached end of video
if (frame.empty()) {
cout << "Done processing !!!" << endl;
cout << "Output file is stored as " << outputFile << endl;
waitKey(3000);
break;
}
// Create a 4D blob from a frame.
blobFromImage(frame, blob, 1/255.0, cvSize(inpWidth, inpHeight), Scalar(0,0,0), true, false);
//Sets the input to the network
net.setInput(blob);
// Runs the forward pass to get output of the output layers
vector<Mat> outs;
net.forward(outs, getOutputsNames(net));
// Remove the bounding boxes with low confidence //get the label for the class name and its confidence
int numDet = postprocess(frame, outs); string label = format("%.2f", conf);
if(numDet == 0 && parser.has("image")) { if (!classes.empty()) {
continue; CV_Assert(classId < (int)classes.size());
label = classes[classId] + ":" + label;
} }
// Put efficiency information. The function getPerfProfile returns the overall time for inference(t) and the timings for each of the layers(in layersTimes) // display the label at the top of the bounding box
vector<double> layersTimes; int baseLine;
double freq = getTickFrequency() / 1000; Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
double t = net.getPerfProfile(layersTimes) / freq; top = max(top, labelSize.height);
string label = format("Inference time for a frame : %.2f ms", t); rectangle(frame, Point(left, top - round(1.5*labelSize.height)), Point(left + round(1.5*labelSize.width), top + baseLine), Scalar(255, 255, 255), FILLED);
putText(frame, label, Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 0)); putText(frame, label, Point(left, top), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0,0,0),1);
// Write the frame with the detection boxes
Mat detectedFrame;
frame.convertTo(detectedFrame, CV_8U);
if (parser.has("image")) {
string ofname = outputFile + to_string(detCnt) + ".jpg";
imwrite(ofname, detectedFrame);
detCnt++;
}
else {
video.write(detectedFrame);
}
//imshow(kWinName, frame);
} }
cap.release(); // post process
if (!parser.has("image")) video.release(); vector<tuple<string, double, Rect>> postprocess(Mat& frame, const vector<Mat>& outs)
{
return 0;
}
// Remove the bounding boxes with low confidence using non-maxima suppression
int postprocess(Mat& frame, const vector<Mat>& outs)
{
vector<int> classIds; vector<int> classIds;
vector<float> confidences; vector<float> confidences;
vector<Rect> boxes; vector<Rect> boxes;
for (size_t i = 0; i < outs.size(); ++i) for (size_t i = 0; i < outs.size(); ++i) {
{
// Scan through all the bounding boxes output from the network and keep only the // Scan through all the bounding boxes output from the network and keep only the
// ones with high confidence scores. Assign the box's class label as the class // ones with high confidence scores. Assign the box's class label as the class
// with the highest score for the box. // with the highest score for the box.
float* data = (float*)outs[i].data; float* data = (float*)outs[i].data;
for (int j = 0; j < outs[i].rows; ++j, data += outs[i].cols) for (int j = 0; j < outs[i].rows; ++j, data += outs[i].cols) {
{
Mat scores = outs[i].row(j).colRange(5, outs[i].cols); Mat scores = outs[i].row(j).colRange(5, outs[i].cols);
Point classIdPoint; Point classIdPoint;
double confidence; double confidence;
// Get the value and location of the maximum score // Get the value and location of the maximum score
minMaxLoc(scores, 0, &confidence, 0, &classIdPoint); minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);
if (confidence > confThreshold) if (confidence > confThreshold) {
{
int centerX = (int)(data[0] * frame.cols); int centerX = (int)(data[0] * frame.cols);
int centerY = (int)(data[1] * frame.rows); int centerY = (int)(data[1] * frame.rows);
int width = (int)(data[2] * frame.cols); int width = (int)(data[2] * frame.cols);
...@@ -216,59 +119,160 @@ int postprocess(Mat& frame, const vector<Mat>& outs) ...@@ -216,59 +119,160 @@ int postprocess(Mat& frame, const vector<Mat>& outs)
} }
} }
// Perform non maximum suppression to eliminate redundant overlapping boxes with // Perform non maximum suppression to eliminate redundant overlapping boxes with lower confidences
// lower confidences
vector<int> indices; vector<int> indices;
NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices); NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);
for (size_t i = 0; i < indices.size(); ++i) vector<tuple<string, double, Rect>> ret;
{ for (size_t i = 0; i < indices.size(); ++i) {
int idx = indices[i]; int idx = indices[i];
Rect box = boxes[idx]; Rect box = boxes[idx];
drawPred(classIds[idx], confidences[idx], box.x, box.y, ret.push_back(tuple<string, double, Rect>(classes[classIds[idx]], confidences[idx], box));
box.x + box.width, box.y + box.height, frame); drawPred(classIds[idx], confidences[idx], box.x, box.y, box.x + box.width, box.y + box.height, frame);
} }
return indices.size(); return ret;
} }
// Draw the predicted bounding box //
void drawPred(int classId, float conf, int left, int top, int right, int bottom, Mat& frame) protected:
{
//Draw a rectangle displaying the bounding box
rectangle(frame, Point(left, top), Point(right, bottom), Scalar(255, 178, 50), 3);
//Get the label for the class name and its confidence //
string label = format("%.2f", conf); public:
if (!classes.empty()) typedef int (*callback)(vector<tuple<string, double, Rect>>, Mat);
YoloDectect(string path = "")
{ {
CV_Assert(classId < (int)classes.size()); if(path.empty()) {
label = classes[classId] + ":" + label; path = ".";
} }
//Display the label at the top of the bounding box // Load names of classes
int baseLine; string classesFile = path + "/coco.names";
Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine); // Give the configuration and weight files for the model
top = max(top, labelSize.height); String modCfg = path + "/yolov3-tiny.cfg";
rectangle(frame, Point(left, top - round(1.5*labelSize.height)), Point(left + round(1.5*labelSize.width), top + baseLine), Scalar(255, 255, 255), FILLED); String modWeights = path + "/yolov3-tiny.weights";
putText(frame, label, Point(left, top), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0,0,0),1);
}
// Get the names of the output layers if(!fs::exists(classesFile) || !fs::exists(modCfg) || !fs::exists(modWeights)) {
vector<String> getOutputsNames(const Net& net) spdlog::error("{} failed to load configration files", selfId);
{ exit(1);
static vector<String> names; }
if (names.empty())
ifstream ifs(classesFile.c_str());
string line;
while (getline(ifs, line)) {
classes.push_back(line);
}
// Load the network
net = readNetFromDarknet(modCfg, modWeights);
net.setPreferableBackend(DNN_BACKEND_OPENCV);
net.setPreferableTarget(DNN_TARGET_CPU);
}
vector<tuple<string, double, Rect>> process(Mat &inFrame, Mat &outFrame)
{ {
//Get the indices of the output layers, i.e. the layers with unconnected outputs if(inFrame.empty()) {
vector<int> outLayers = net.getUnconnectedOutLayers(); return vector<tuple<string, double, Rect>>();
}
//get the names of all the layers in the network // Create a 4D blob from a frame.
vector<String> layersNames = net.getLayerNames(); blobFromImage(inFrame, blob, 1/255.0, cvSize(inpWidth, inpHeight), Scalar(0,0,0), true, false);
// Get the names of the output layers in names //Sets the input to the network
names.resize(outLayers.size()); net.setInput(blob);
for (size_t i = 0; i < outLayers.size(); ++i)
names[i] = layersNames[outLayers[i] - 1]; // Runs the forward pass to get output of the output layers
vector<Mat> outs;
net.forward(outs, getOutputsNames(net));
// Remove the bounding boxes with low confidence
auto ret = postprocess(inFrame, outs);
// The function getPerfProfile returns the overall time for inference(t) and the timings for each of the layers(in layersTimes)
vector<double> layersTimes;
double freq = getTickFrequency() / 1000;
double t = net.getPerfProfile(layersTimes) / freq;
spdlog::info("{} infer time: {} ms", selfId, t);
inFrame.convertTo(outFrame, CV_8U);
return ret;
} }
return names;
int process(string inVideoUri, callback cb = nullptr, string outFile = "processed.jpg")
{
if(inVideoUri.empty()) {
inVideoUri = "0";
}
ghc::filesystem::path p(outFile);
auto dir = p.parent_path();
if((inVideoUri.substr(inVideoUri.find_last_of(".") + 1) == "jpg")) {
bOutputIsImg = true;
outFileBase = string(dir / p.stem());
}
else {
bOutputIsImg = false;
if(!cap.open(inVideoUri)) {
spdlog::error("{} failed to open input video {}", selfId, inVideoUri);
return -1;
}
if(!video.open(outFile, VideoWriter::fourcc('M','J','P','G'), 28, Size(cap.get(CAP_PROP_FRAME_WIDTH), cap.get(CAP_PROP_FRAME_HEIGHT)))) {
spdlog::error("{} failed to open output video {}", selfId, inVideoUri);
return -1;
}
}
long frameCnt = 0;
long detCnt = 0;
Mat frame, outFrame;
while (waitKey(1) < 0) {
// get frame from the video
if(cmdStop) {
break;
}
if(!cap.read(frame)) {
spdlog::error("{} failed to read frame from {}", selfId, inVideoUri);
break;
}
frameCnt++;
// Stop the program if reached end of video
if (frame.empty()) {
continue;
}
vector<tuple<string, double, Rect>> ret = process(frame, outFrame);
if(ret.size() == 0 && bOutputIsImg) {
// no detection
continue;
}
if (bOutputIsImg) {
string ofname = outFileBase + to_string(detCnt) + ".jpg";
imwrite(ofname, outFrame);
detCnt++;
}
else {
video.write(outFrame);
}
}
cap.release();
if(!bOutputIsImg) video.release();
return 0;
}
};
int main(int argc, char** argv)
{
YoloDectect det;
det.process("rtsp://admin:ZQEAAI@192.168.0.101:554/h264/ch1/main/av_stream");
return 0;
} }
// This code is written at BigVision LLC. It is based on the OpenCV project. It is subject to the license terms in the LICENSE file found in this distribution and at http://opencv.org/license.html
// Usage example: ./object_detection_yolo.out --video=run.mp4
// ./object_detection_yolo.out --image=bird.jpg
#include <fstream>
#include <sstream>
#include <iostream>
#ifdef _MY_HEADERS_
#include <opencv2/core/types_c.h>
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#else
#include <opencv2/core/types_c.h>
#include <opencv2/opencv.hpp>
#endif
const char* keys =
"{help h usage ? | | Usage examples: \n\t\t./PROG --image=dog.jpg \n\t\t./object_detection_yolo.out --video=run_sm.mp4}"
"{image i |<none>| input image }"
"{video v |<none>| input video }"
;
using namespace cv;
using namespace dnn;
using namespace std;
// Initialize the parameters
float confThreshold = 0.5; // Confidence threshold
float nmsThreshold = 0.4; // Non-maximum suppression threshold
int inpWidth = 416; // Width of network's input image
int inpHeight = 416; // Height of network's input image
vector<string> classes;
// Remove the bounding boxes with low confidence using non-maxima suppression
int postprocess(Mat& frame, const vector<Mat>& out);
// Draw the predicted bounding box
void drawPred(int classId, float conf, int left, int top, int right, int bottom, Mat& frame);
// Get the names of the output layers
vector<String> getOutputsNames(const Net& net);
int main(int argc, char** argv)
{
CommandLineParser parser(argc, argv, keys);
parser.about("Use this script to run object detection using YOLO3 in OpenCV.");
if (parser.has("help"))
{
parser.printMessage();
return 0;
}
// Load names of classes
string classesFile = "coco.names";
ifstream ifs(classesFile.c_str());
string line;
while (getline(ifs, line)) classes.push_back(line);
// Give the configuration and weight files for the model
String modelConfiguration = "yolov3-tiny.cfg";
String modelWeights = "yolov3-tiny.weights";
// Load the network
Net net = readNetFromDarknet(modelConfiguration, modelWeights);
net.setPreferableBackend(DNN_BACKEND_OPENCV);
net.setPreferableTarget(DNN_TARGET_CPU);
// Open a video file or an image file or a camera stream.
string str, outputFile;
VideoCapture cap;
VideoWriter video;
Mat frame, blob;
try {
outputFile = "yolo_out_cpp.avi";
if (parser.has("image"))
{
// Open the image file
str = parser.get<String>("image");
ifstream ifile(str);
if (!ifile) throw("error");
cap.open(str);
str.replace(str.end()-4, str.end(), "_yolo_out_cpp"); //.jpg
outputFile = str;
}
else if (parser.has("video"))
{
// Open the video file
str = parser.get<String>("video");
//ifstream ifile(str);
//if (!ifile) throw("error");
cout << "open video stream: " << str << endl;
if(!cap.open(str)){
cout << "failed to open video stream: " << str << endl;
}
str.replace(str.end()-4, str.end(), "_yolo_out_cpp.avi");
}else{
// Open the webcaom
cap.open(parser.get<int>("device"));
}
cout << "output file: " << outputFile << endl;
}
catch(...) {
cout << "Could not open the input image/video stream" << endl;
return 0;
}
// Get the video writer initialized to save the output video
if (!parser.has("image")) {
video.open(outputFile, VideoWriter::fourcc('M','J','P','G'), 28, Size(cap.get(CAP_PROP_FRAME_WIDTH), cap.get(CAP_PROP_FRAME_HEIGHT)));
}
// Create a window
//static const string kWinName = "Deep learning object detection in OpenCV";
//namedWindow(kWinName, WINDOW_NORMAL);
// Process frames.
long frameCnt = 0;
long detCnt = 0;
while (waitKey(1) < 0)
{
// get frame from the video
if(!cap.read(frame)) {
cout << "failed to open video stream" << endl;
break;
}
cout << "frameCnt: " << frameCnt << endl;
frameCnt++;
// Stop the program if reached end of video
if (frame.empty()) {
cout << "Done processing !!!" << endl;
cout << "Output file is stored as " << outputFile << endl;
waitKey(3000);
break;
}
// Create a 4D blob from a frame.
blobFromImage(frame, blob, 1/255.0, cvSize(inpWidth, inpHeight), Scalar(0,0,0), true, false);
//Sets the input to the network
net.setInput(blob);
// Runs the forward pass to get output of the output layers
vector<Mat> outs;
net.forward(outs, getOutputsNames(net));
// Remove the bounding boxes with low confidence
int numDet = postprocess(frame, outs);
if(numDet == 0 && parser.has("image")) {
continue;
}
// Put efficiency information. The function getPerfProfile returns the overall time for inference(t) and the timings for each of the layers(in layersTimes)
vector<double> layersTimes;
double freq = getTickFrequency() / 1000;
double t = net.getPerfProfile(layersTimes) / freq;
string label = format("Inference time for a frame : %.2f ms", t);
putText(frame, label, Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 0));
// Write the frame with the detection boxes
Mat detectedFrame;
frame.convertTo(detectedFrame, CV_8U);
if (parser.has("image")) {
string ofname = outputFile + to_string(detCnt) + ".jpg";
imwrite(ofname, detectedFrame);
detCnt++;
}
else {
video.write(detectedFrame);
}
//imshow(kWinName, frame);
}
cap.release();
if (!parser.has("image")) video.release();
return 0;
}
// Remove the bounding boxes with low confidence using non-maxima suppression
int postprocess(Mat& frame, const vector<Mat>& outs)
{
vector<int> classIds;
vector<float> confidences;
vector<Rect> boxes;
for (size_t i = 0; i < outs.size(); ++i)
{
// Scan through all the bounding boxes output from the network and keep only the
// ones with high confidence scores. Assign the box's class label as the class
// with the highest score for the box.
float* data = (float*)outs[i].data;
for (int j = 0; j < outs[i].rows; ++j, data += outs[i].cols)
{
Mat scores = outs[i].row(j).colRange(5, outs[i].cols);
Point classIdPoint;
double confidence;
// Get the value and location of the maximum score
minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);
if (confidence > confThreshold)
{
int centerX = (int)(data[0] * frame.cols);
int centerY = (int)(data[1] * frame.rows);
int width = (int)(data[2] * frame.cols);
int height = (int)(data[3] * frame.rows);
int left = centerX - width / 2;
int top = centerY - height / 2;
classIds.push_back(classIdPoint.x);
confidences.push_back((float)confidence);
boxes.push_back(Rect(left, top, width, height));
}
}
}
// Perform non maximum suppression to eliminate redundant overlapping boxes with
// lower confidences
vector<int> indices;
NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);
for (size_t i = 0; i < indices.size(); ++i)
{
int idx = indices[i];
Rect box = boxes[idx];
drawPred(classIds[idx], confidences[idx], box.x, box.y,
box.x + box.width, box.y + box.height, frame);
}
return indices.size();
}
// Draw the predicted bounding box
void drawPred(int classId, float conf, int left, int top, int right, int bottom, Mat& frame)
{
//Draw a rectangle displaying the bounding box
rectangle(frame, Point(left, top), Point(right, bottom), Scalar(255, 178, 50), 3);
//Get the label for the class name and its confidence
string label = format("%.2f", conf);
if (!classes.empty())
{
CV_Assert(classId < (int)classes.size());
label = classes[classId] + ":" + label;
}
//Display the label at the top of the bounding box
int baseLine;
Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
top = max(top, labelSize.height);
rectangle(frame, Point(left, top - round(1.5*labelSize.height)), Point(left + round(1.5*labelSize.width), top + baseLine), Scalar(255, 255, 255), FILLED);
putText(frame, label, Point(left, top), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0,0,0),1);
}
// Get the names of the output layers
vector<String> getOutputsNames(const Net& net)
{
static vector<String> names;
if (names.empty())
{
//Get the indices of the output layers, i.e. the layers with unconnected outputs
vector<int> outLayers = net.getUnconnectedOutLayers();
//get the names of all the layers in the network
vector<String> layersNames = net.getLayerNames();
// Get the names of the output layers in names
names.resize(outLayers.size());
for (size_t i = 0; i < outLayers.size(); ++i)
names[i] = layersNames[outLayers[i] - 1];
}
return names;
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论