opencv调用yolo模型的C++代码(用于测试)

opencv调用yolo模型的C++代码,用于测试视频效果,以及模型部署,使用opencv库调用darknet模型部署相对比较简单,只需引用#include "opencv2/dnn.hpp"头文件,调用opencv的接口即可。

main.cpp

#include <iostream>
#include <time.h>
#include<sys/io.h>
#include<iostream>
#include<vector>
#include <string>
#include <list>
#include <dirent.h>
#include <sys/stat.h>
#include<opencv2/opencv.hpp>
#include "fire_smoke_detector.h"

#define FRAME_PER_NUME 1
using namespace std;
using namespace ia;

int main()
{
    time_t t;
    struct tm * lt;
    bool f_stop = false;
    int g_currentpercent;
    int g_ncurrentframe;
    cv::Mat Input;
    string input_video_path = "/home/video/fire_smoke/suidao0/yunfuyanhuo2.mp4";
    cv::VideoCapture capture(input_video_path);

    if (!capture.isOpened())
    std::cout << "fail to open!" << std::endl;
    int g_ntotalFrameNumber = capture.get(CV_CAP_PROP_FRAME_COUNT);
    std::cout << "整个视频共" << g_ntotalFrameNumber << "帧" << std::endl;
    //获得帧的宽高
    int w = static_cast<int>(capture.get(CV_CAP_PROP_FRAME_WIDTH));
    int h = static_cast<int>(capture.get(CV_CAP_PROP_FRAME_HEIGHT));
    cv::Size S(w, h);
    // 视频写入对象
    cv::VideoWriter writer("./result.avi", CV_FOURCC('m', 'p', '4', ' v'),25, cv::Size(1280, 720));
    FireSmokeDetector detector = FireSmokeDetector();

    while (!f_stop )
    {
        time (&t);
        lt = localtime (&t);
        for (int i = 0;i < FRAME_PER_NUME;i++) {
            capture >> Input;
            if(Input.empty())
            {
                break;
            }
        }
        if(Input.empty())
        {
            break;
        }
        detector.detect(Input);
        cv::Size show_size = cv::Size((int)(Input.cols/2), (int)(Input.rows/2));
        cv::Mat show_image;
        cv::resize(Input, show_image, show_size);
        //cv::resize()
        cv::imshow("test",show_image);
        cv::waitKey(1);
        writer<<Input;
        g_currentpercent = int(g_ncurrentframe * 100 / g_ntotalFrameNumber);
        g_ncurrentframe += FRAME_PER_NUME;
    }
    //释放对象
    capture.release();
    return 0;
}

fire_smoke_detector.h

#pragma once
/****************************************************************************
*
*	 Roadblock detector
*
******************************************************************************/
#ifndef __IMAGE_ANALYSIS_FIRESMOKE_DETECTOR_H__
#define __IMAGE_ANALYSIS_FIRESMOKE_DETECTOR_H__

#include  "opencv2/dnn.hpp"
#include<opencv2/opencv.hpp>
#include <chrono>

namespace ia
{
	using std::chrono::steady_clock;

	class FireSmokeDetector
	{
	public:
		FireSmokeDetector();
		~FireSmokeDetector();

		void detect(cv::Mat &frame);

		int getDetectID() { return this->firesmokeID; };
		std::vector<cv::Rect2d>& getDetectRect() { return this->firesmokes; };

	private:
		int firesmokeID;

		std::vector<cv::Rect2d> firesmokes;

		steady_clock::time_point lastFoundTime;

		cv::dnn::Net net;
	};
}
#endif



fire_smoke_detector.cpp

/****************************************************************************
*
*	 FireSmoke Detector
*
******************************************************************************/
#include "fire_smoke_detector.h"

namespace ia
{
	using namespace std;
	using namespace cv;
	using namespace cv::dnn;

	//float confThreshold_fs = 0.9; // Confidence threshold
	//float nmsThreshold_fs = 0.5;  // Non-maximum suppression threshold
	float confThreshold_fs = 0.25; // Confidence threshold
	float nmsThreshold_fs = 0.2;  // Non-maximum suppression threshold
	int inpWidth_fs = 416;        // Width of network's input image
	int inpHeight_fs = 416;       // Height of network's input image

		// Remove the bounding boxes with low confidence using non-maxima suppression
		//在yolov3中,使用opencv接口来使用yolov3最后输出的维度为[n, 85],其中n是预测的标签框的总数,85分别对应x,y,w,h,置信度,以及各个类别对应的可能性,我们使用的是coco数据集,coco数据集有80个类别
	static void postprocess(Mat& frame, const vector<Mat>& outs, vector<cv::Rect2d>& rects)
	{
		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_fs)
				{
					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
		static vector<int> indices;
		NMSBoxes(boxes, confidences, confThreshold_fs, nmsThreshold_fs, indices);

		rects.clear();
		for (size_t i = 0; i < indices.size(); ++i)
		{
			int idx = indices[i];
			Rect box = boxes[idx];

			cv::Rect2d box2d;
			/*
			box2d.x = (double)box.x / frame.cols;
			box2d.y = (double)box.y / frame.rows;
			box2d.width = (double)box.width / frame.cols;
			box2d.height = (double)box.height / frame.rows;
			*/
			box2d.x = (double)box.x;
			box2d.y = (double)box.y;
			box2d.width = (double)box.width;
			box2d.height = (double)box.height;
			rects.push_back(box2d);

			//Log::info("roadblock c{}:x{},y{},w{},h{}", confidences[idx], box.x, box.y, box.width, box.height);
			/*drawPred(classIds[idx], confidences[idx], box.x, box.y,
				box.x + box.width, box.y + box.height, frame);*/
		}
	}

	// Get the names of the output layers
	static std::vector<cv::String> getOutputsNames(const cv::dnn::Net& net)
	{
		static std::vector<cv::String> names;
		if (names.empty())
		{
			//Get the indices of the output layers, i.e. the layers with unconnected outputs
			std::vector<int> outLayers = net.getUnconnectedOutLayers();

			//get the names of all the layers in the network
			std::vector<cv::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;
	}

	FireSmokeDetector::FireSmokeDetector() :firesmokeID(0)
	{
		//net = cv::dnn::readNetFromDarknet("models/firesmoke.cfg", "models/firesmoke.weights");
		//net = readNet("models/optimized_graph.pb");
		net = cv::dnn::readNetFromDarknet("/root/zhangsong/iva-ds5.0-it1/iva-app/release/iva/models/firesmoke/yolov4-tiny/iteration1/yolov4-tiny.cfg", "/root/zhangsong/iva-ds5.0-it1/iva-app/release/iva/models/firesmoke/yolov4-tiny/iteration1/yolov4-tiny_70000.weights");
		//printf("\nefficientnet_yolo_tiny\n");
	}


	FireSmokeDetector::~FireSmokeDetector()
	{

	}

	void FireSmokeDetector::detect(cv::Mat &frame)
	{
		if (net.empty())
		{
			//Log::error("Could not load net at path: models/firesmoke.weights \n");
			return;
		}
		//}

		Mat blob;
		cv::dnn::blobFromImage(frame, blob, 1 / 255.0, cv::Size(inpWidth_fs, inpHeight_fs), cv::Scalar(0, 0, 0), true, false);
		net.setInput(blob);

		std::vector<Mat> outs;
		net.forward(outs, getOutputsNames(net));

		postprocess(frame, outs, firesmokes);

		for(int i = 0 ;i < firesmokes.size();i++)
		{
			cv::Point pt1, pt2;
			pt1.x = firesmokes[i].x;
			pt1.y = firesmokes[i].y;
			pt2.x = firesmokes[i].x + firesmokes[i].width;
			pt2.y = firesmokes[i].y + firesmokes[i].height;
			rectangle(frame, pt1, pt2, cv::Scalar(255, 255, 255), 2, 8, 0);
		}

		if (firesmokes.size() > 0)
		{
			auto now = std::chrono::steady_clock::now();
			auto passed = std::chrono::duration_cast<std::chrono::seconds>(now - lastFoundTime);
			auto passedSecond = passed.count();
			if (passedSecond > 30)
			{
				firesmokeID++;
				if (firesmokeID > 9999999)
				{
					firesmokeID = 1;
				}
			}

			lastFoundTime = now;
		}
	}
}


Makefile

APP:= test
CXX:= g++
SRCS:= $(wildcard *.cpp)
INCS:= $(wildcard *.h)

PKGS:= opencv

OBJS:= $(SRCS:.cpp=.o)

CFLAGS:= -fPIC

LIBS:= -Wl,-no-undefined \
	   -lm -lpthread

CFLAGS+= `pkg-config --cflags $(PKGS)` -std=c++11
LIBS+= `pkg-config --libs $(PKGS)`

all: $(APP)

%.o: %.cpp $(INCS) Makefile
	@echo $(CFLAGS)
	$(CXX) -c -o $@ $(CFLAGS) $<

$(APP): $(OBJS) Makefile
	@echo $(CFLAGS)
	$(CXX) -o $(APP) $(OBJS) $(LIBS)

clean:
	rm -rf $(OBJS) $(APP)
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页