提交 d18c5334 authored 作者: blu's avatar blu

revert to non-object-detection

上级 9da62c6e
...@@ -23,7 +23,6 @@ update: 2019/09/10 ...@@ -23,7 +23,6 @@ update: 2019/09/10
#include "common.hpp" #include "common.hpp"
#include "avcvhelpers.hpp" #include "avcvhelpers.hpp"
#include "database.h" #include "database.h"
#include "yolo.hpp"
using namespace std; using namespace std;
using namespace zmqhelper; using namespace zmqhelper;
...@@ -82,7 +81,6 @@ private: ...@@ -82,7 +81,6 @@ private:
long long packetTsDelta = 0; long long packetTsDelta = 0;
float pps = 0; float pps = 0;
int pktLag = 0; int pktLag = 0;
unique_ptr<YoloDectect> pYolo = nullptr;
// //
int handleCloudMsg(vector<vector<uint8_t> > v) int handleCloudMsg(vector<vector<uint8_t> > v)
...@@ -360,9 +358,6 @@ private: ...@@ -360,9 +358,6 @@ private:
} }
//ping //ping
ret = ping(); ret = ping();
//
pYolo = unique_ptr<YoloDectect>(new YoloDectect("../opencv-yolo"));
} }
catch(exception &e) { catch(exception &e) {
spdlog::error("evmlmotion {} exception in EvPuller.init {:s} retrying", selfId, e.what()); spdlog::error("evmlmotion {} exception in EvPuller.init {:s} retrying", selfId, e.what());
...@@ -564,26 +559,10 @@ private: ...@@ -564,26 +559,10 @@ private:
void detectMotion(AVPixelFormat format,AVFrame *pFrame, bool detect = true) void detectMotion(AVPixelFormat format,AVFrame *pFrame, bool detect = true)
{ {
static bool first = true; static bool first = true;
static unsigned long detCnt = 0;
static cv::Mat avg; static cv::Mat avg;
static vector<vector<cv::Point> > cnts; static vector<vector<cv::Point> > cnts;
cv::Mat origin, gray, thresh; cv::Mat origin, gray, thresh;
avcvhelpers::frame2mat(format, pFrame, origin); avcvhelpers::frame2mat(format, pFrame, origin);
if(detCnt % 6 == 0) {
auto objDetRes = pYolo->process(origin, nullptr);
if(objDetRes.size() > 0) {
string s = fmt::format("{} {} object detected:\n", selfId, objDetRes.size());
int i = 0;
for(auto &[n, c, _]: objDetRes) {
i++;
s += fmt::format("\t\tobj {}:{}, prob: {}, x:{}, y:{}, w: {}, h:{}\n", i, n, c, _.x, _.y, _.width, _.height);
}
spdlog::info(s);
}
}
detCnt++;
cv::resize(origin, gray, cv::Size(FRAME_SIZE,FRAME_SIZE)); cv::resize(origin, gray, cv::Size(FRAME_SIZE,FRAME_SIZE));
cv::cvtColor(gray, thresh, cv::COLOR_BGR2GRAY); cv::cvtColor(gray, thresh, cv::COLOR_BGR2GRAY);
float fent = avcvhelpers::getEntropy(thresh); float fent = avcvhelpers::getEntropy(thresh);
......
#ifndef _MY_YOLO_HPP_
#define _MY_YOLO_HPP_
#include <fstream>
#include <sstream>
#include <iostream>
#include <tuple>
#include "fs.h"
#include "spdlog/spdlog.h"
#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
using namespace cv;
using namespace dnn;
using namespace std;
class YoloDectect {
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;
VideoWriter video;
bool bOutputIsImg = false;
string outFileBase;
bool cmdStop = false;
unsigned int wrapNum = 0;
unsigned long numFrameProcessed = 0;
unsigned int numLogSkip = 0;
// 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;
}
// 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);
}
// post process
vector<tuple<string, double, Rect>> postprocess(Mat& frame, const vector<Mat>& outs, bool bModify = false)
{
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);
vector<tuple<string, double, Rect>> ret;
for (size_t i = 0; i < indices.size(); ++i) {
int idx = indices[i];
Rect box = boxes[idx];
ret.push_back(tuple<string, double, Rect>(classes[classIds[idx]], confidences[idx], box));
if(bModify)
drawPred(classIds[idx], confidences[idx], box.x, box.y, box.x + box.width, box.y + box.height, frame);
}
return ret;
}
//
protected:
//
public:
typedef int (*callback)(vector<tuple<string, double, Rect>>&, Mat);
YoloDectect(string path = "", unsigned int _wrapNum = 10, unsigned int _numLogSkip = 380)
{
if(path.empty()) {
path = ".";
}
wrapNum = _wrapNum;
numLogSkip = _numLogSkip;
// Load names of classes
string classesFile = path + "/coco.names";
// Give the configuration and weight files for the model
String modCfg = path + "/yolov3-tiny.cfg";
String modWeights = path + "/yolov3-tiny.weights";
if(!fs::exists(classesFile) || !fs::exists(modCfg) || !fs::exists(modWeights)) {
spdlog::error("{} failed to load configration files", selfId);
exit(1);
}
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);
spdlog::info("{} inited", selfId);
}
vector<tuple<string, double, Rect>> process(Mat &inFrame, Mat* pOutFrame)
{
if(inFrame.empty()) {
return vector<tuple<string, double, Rect>>();
}
// Create a 4D blob from a frame.
blobFromImage(inFrame, 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
auto ret = postprocess(inFrame, outs, true);
// The function getPerfProfile returns the overall time for inference(t) and the timings for each of the layers(in layersTimes)
vector<double> layersTimes;
if(numLogSkip == 0 || numFrameProcessed % numLogSkip == 0) {
double freq = getTickFrequency() / 1000;
double t = net.getPerfProfile(layersTimes) / freq;
spdlog::info("{} infer time: {} ms", selfId, t);
}
if(pOutFrame != nullptr){
inFrame.convertTo(*pOutFrame, CV_8U);
}
numFrameProcessed++;
return ret;
}
int process(string inVideoUri, string outFile = "processed.jpg", callback cb = nullptr)
{
if(inVideoUri.empty()) {
inVideoUri = "0";
}
if(!cap.open(inVideoUri)) {
spdlog::error("{} failed to open input video {}", selfId, inVideoUri);
return -1;
}
ghc::filesystem::path p(outFile);
auto dir = p.parent_path();
if((outFile.substr(outFile.find_last_of(".") + 1) == "jpg")) {
bOutputIsImg = true;
outFileBase = string(dir / p.stem());
spdlog::info("{} outFileBase {}", selfId, outFileBase);
}
else {
bOutputIsImg = false;
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, outFile);
return -1;
}
}
spdlog::info("{} try to process video {} to {}", selfId, inVideoUri, outFile);
unsigned long frameCnt = 0;
unsigned long detCnt = 0, skipCnt = 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(cb == nullptr) {
if(ret.size() == 0 && bOutputIsImg) {
// no detection
if(numLogSkip == 0|| skipCnt % numLogSkip == 0) {
spdlog::info("{} no valid object detected skipped frame count {}", selfId, skipCnt);
}
skipCnt++;
continue;
}
if (bOutputIsImg) {
if(wrapNum > 0) {
detCnt = detCnt % wrapNum;
}
string ofname = outFileBase + to_string(detCnt) + ".jpg";
imwrite(ofname, outFrame);
detCnt++;
}
else {
video.write(outFrame);
}
}else{
cb(ret, outFrame);
}
}
cap.release();
if(!bOutputIsImg) video.release();
return 0;
}
};
#endif
\ No newline at end of file
...@@ -35,9 +35,6 @@ private: ...@@ -35,9 +35,6 @@ private:
bool bOutputIsImg = false; bool bOutputIsImg = false;
string outFileBase; string outFileBase;
bool cmdStop = false; bool cmdStop = false;
unsigned int wrapNum = 0;
unsigned long numFrameProcessed = 0;
unsigned int numLogSkip = 0;
// 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)
...@@ -80,7 +77,7 @@ private: ...@@ -80,7 +77,7 @@ private:
} }
// post process // post process
vector<tuple<string, double, Rect>> postprocess(Mat& frame, const vector<Mat>& outs, bool bModify = true) vector<tuple<string, double, Rect>> postprocess(Mat& frame, const vector<Mat>& outs)
{ {
vector<int> classIds; vector<int> classIds;
vector<float> confidences; vector<float> confidences;
...@@ -120,7 +117,6 @@ private: ...@@ -120,7 +117,6 @@ private:
int idx = indices[i]; int idx = indices[i];
Rect box = boxes[idx]; Rect box = boxes[idx];
ret.push_back(tuple<string, double, Rect>(classes[classIds[idx]], confidences[idx], box)); ret.push_back(tuple<string, double, Rect>(classes[classIds[idx]], confidences[idx], box));
if(bModify)
drawPred(classIds[idx], confidences[idx], box.x, box.y, 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);
} }
...@@ -133,15 +129,12 @@ protected: ...@@ -133,15 +129,12 @@ protected:
// //
public: public:
typedef int (*callback)(vector<tuple<string, double, Rect>>&, Mat); typedef int (*callback)(vector<tuple<string, double, Rect>>&, Mat);
YoloDectect(string path = "", unsigned int _wrapNum = 10, unsigned int _numLogSkip = 380) YoloDectect(string path = "")
{ {
if(path.empty()) { if(path.empty()) {
path = "."; path = ".";
} }
wrapNum = _wrapNum;
numLogSkip = _numLogSkip;
// Load names of classes // Load names of classes
string classesFile = path + "/coco.names"; string classesFile = path + "/coco.names";
// Give the configuration and weight files for the model // Give the configuration and weight files for the model
...@@ -166,7 +159,7 @@ public: ...@@ -166,7 +159,7 @@ public:
spdlog::info("{} inited", selfId); spdlog::info("{} inited", selfId);
} }
vector<tuple<string, double, Rect>> process(Mat &inFrame, Mat* pOutFrame) vector<tuple<string, double, Rect>> process(Mat &inFrame, Mat &outFrame)
{ {
if(inFrame.empty()) { if(inFrame.empty()) {
return vector<tuple<string, double, Rect>>(); return vector<tuple<string, double, Rect>>();
...@@ -183,20 +176,15 @@ public: ...@@ -183,20 +176,15 @@ public:
net.forward(outs, getOutputsNames(net)); net.forward(outs, getOutputsNames(net));
// Remove the bounding boxes with low confidence // Remove the bounding boxes with low confidence
auto ret = postprocess(inFrame, outs, true); 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) // The function getPerfProfile returns the overall time for inference(t) and the timings for each of the layers(in layersTimes)
vector<double> layersTimes; vector<double> layersTimes;
if(numLogSkip == 0 || numFrameProcessed % numLogSkip == 0) { double freq = getTickFrequency() / 1000;
double freq = getTickFrequency() / 1000; double t = net.getPerfProfile(layersTimes) / freq;
double t = net.getPerfProfile(layersTimes) / freq; spdlog::info("{} infer time: {} ms", selfId, t);
spdlog::info("{} infer time: {} ms", selfId, t);
} inFrame.convertTo(outFrame, CV_8U);
if(pOutFrame != nullptr){
inFrame.convertTo(*pOutFrame, CV_8U);
}
numFrameProcessed++;
return ret; return ret;
} }
...@@ -229,8 +217,8 @@ public: ...@@ -229,8 +217,8 @@ public:
spdlog::info("{} try to process video {} to {}", selfId, inVideoUri, outFile); spdlog::info("{} try to process video {} to {}", selfId, inVideoUri, outFile);
unsigned long frameCnt = 0; long frameCnt = 0;
unsigned long detCnt = 0, skipCnt = 0; long detCnt = 0, skipCnt = 0;
Mat frame, outFrame; Mat frame, outFrame;
while (waitKey(1) < 0) { while (waitKey(1) < 0) {
// get frame from the video // get frame from the video
...@@ -250,11 +238,11 @@ public: ...@@ -250,11 +238,11 @@ public:
continue; continue;
} }
vector<tuple<string, double, Rect>> ret = process(frame, &outFrame); vector<tuple<string, double, Rect>> ret = process(frame, outFrame);
if(cb == nullptr) { if(cb == nullptr) {
if(ret.size() == 0 && bOutputIsImg) { if(ret.size() == 0 && bOutputIsImg) {
// no detection // no detection
if(numLogSkip == 0|| skipCnt % numLogSkip == 0) { if(skipCnt % 100 == 0) {
spdlog::info("{} no valid object detected skipped frame count {}", selfId, skipCnt); spdlog::info("{} no valid object detected skipped frame count {}", selfId, skipCnt);
} }
skipCnt++; skipCnt++;
...@@ -262,10 +250,6 @@ public: ...@@ -262,10 +250,6 @@ public:
} }
if (bOutputIsImg) { if (bOutputIsImg) {
if(wrapNum > 0) {
detCnt = detCnt % wrapNum;
}
string ofname = outFileBase + to_string(detCnt) + ".jpg"; string ofname = outFileBase + to_string(detCnt) + ".jpg";
imwrite(ofname, outFrame); imwrite(ofname, outFrame);
detCnt++; detCnt++;
...@@ -288,7 +272,7 @@ public: ...@@ -288,7 +272,7 @@ public:
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
YoloDectect det; YoloDectect det;
det.process("rtsp://admin:ZQEAAI@192.168.0.101:554/h264/ch1/main/av_stream", "a.jpg"); det.process("rtsp://admin:ZQEAAI@192.168.0.101:554/h264/ch1/main/av_stream", "a.avi");
return 0; return 0;
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论