环境配置
1、配置系统环境,Env文件夹下有libtorch和opencv两个子文件夹,将两个文件夹下的三个bin文件目标添加至系统环境变量
2、在VS中配置项目属性,配置包含目录和库目录,包含目录包括Env文件夹下的三个include文件夹,库目录包含Env文件夹下的两个lib文件夹
3、在链接器-输入中添加以下附加依赖项,其中第一个HeZheng_dll.lib和对应的dll文件放在工程目录下即可,其余为opencv和libtorch库
(Debug):
HeZheng_dll.lib
opencv_world450d.lib
libprotobufd.lib
dnnl.lib
torch.lib
torch_cpu.lib
c10.lib
(Release):
HeZheng_dll.lib
opencv_world450.lib
libprotobuf.lib
dnnl.lib
torch.lib
torch_cpu.lib
c10.lib
头文件解析
HeZheng_dll.h
#pragma once
#ifdef HEZHENG_API
#else
#define HEZHENG_API __declspec(dllimport)
#endif // HEZHENG_API
#include <iostream>
#include <opencv2/highgui/highgui_c.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/objdetect.hpp>
#include <torch/script.h>
#include <torch/torch.h>
using namespace std;
class HEZHENG_API HeZheng
{
public:
/// <summary>
/// 输入摄像头每帧图像,返回一维长度为2的容器,容器内是int类型数据,为点的横纵坐标
/// </summary>
/// <param name="frame"></param>
/// <returns></returns>
vector<int> DetectPoint(cv::Mat &frame);
/// <summary>
/// 输入二维容器点集合和一张黑底空图,将点集画在图上,生成轨迹图
/// </summary>
/// <param name="newPoints"></param>
/// <param name="img"></param>
void DrawOnCanVas(vector<int> &newPoints, cv::Mat &img);
/// <summary>
/// 判定轨迹图类别,返回1-6为类别,0为未判定结果
/// </summary>
/// <param name="img"></param>
/// <returns></returns>
int Prediction(cv::Mat &img);
/// <summary>
/// 点方差稳定算法,判断轨迹图上所有点中后points_num个点的方差,达到阈值返回true
/// </summary>
/// <param name="points_num"></param>
/// <returns></returns>
bool Variance(int points_num);
/// <summary>
/// 结果稳定算法,输入每次(帧)判断结果,连续result_stable_num次结果一致返回true
/// </summary>
/// <param name="result"></param>
/// <param name="result_stable_num"></param>
/// <returns></returns>
bool Result_stable(int result, int result_stable_num);
cv::Mat black = cv::Mat(640, 640, CV_8UC3, cv::Scalar(0, 0, 0)); //设置黑底背景图
torch::jit::script::Module model = torch::jit::load("model_path"); //加载模型路径
torch::DeviceType device_type = at::kCPU;
vector<vector<int>> allPoints; //每次新一轮绘图前需要清空该容器: he.allPoints.clear()
cv::Point* myPoint = new cv::Point();
int Point_Area = 150; //目标点最大面积
cv::Scalar lower{ 0, 0, 211 }; //HSV 低阈值
cv::Scalar upper{ 179, 30, 255 }; //HSV 高阈值
float IOU_1 = 8.0; //披毛犀判定阈值
float IOU_2 = 7.0; //剑齿虎判定阈值
float IOU_3 = 5.0; //和政羊判定阈值
float IOU_4 = 2.0; //巨鬣狗判定阈值
float IOU_5 = 15.0; //铲齿象判定阈值
float IOU_6 = 8.0; //三趾马判定阈值
bool print_result = false; //是否打印模型输出结果
bool print_variance = false; //是否打印方差
float variance_x_max = 1000.0; //横坐标方差最大阈值
float variance_y_max = 4000.0; //纵坐标方差最大阈值
vector<int> result_stable_count = {0,0}; //如调用结果稳定算法,需先初始化类成员变量 vector<int> result_stable_count {0,0};
};
1、DetectPoint是用来获取目标点在图像中的位置信息,输入摄像头每帧的画面,输出一个一维容器(vector),长度为2,数据类型为int型的坐标点数据,需要注意的预先根据摄像头参数和现场环境来调节摄像头的曝光度
cap.set(cv::CAP_PROP_EXPOSURE, 曝光值);
2、DrawOnCanVas是将DetectPoint生成的坐标绘制在一张黑底图上,随着每一帧生成点的叠加会逐渐得到一幅轨迹图。
3、Prediction是将生成的轨迹图进行分类判断,返回int类型数据,0为判断无效,1-6分别代表六种分类任务判断成功
4、Variance方差稳定算法,判断轨迹图上所有点中后points_num个点的方差,达到阈值返回true
5、Result_stable结果稳定算法,输入每次(帧)判断结果,连续result_stable_num次结果一致返回true
6、预定义值的修改,在代码中初始化类对象,可根据项目实际需要修改一些值参数
HeZheng he;
he.Point_Area = 修改后的目标的点最大阈值;
he.lower = { 修改后的HSV颜色低阈值 };
he.upper = { 修改后的HSV颜色高阈值 };
he.IOU_1 = 修改后的披毛犀判定阈值;
he.IOU_2 = 修改后的剑齿虎判定阈值;
he.IOU_3 = 修改后的和政羊判定阈值;
he.IOU_4 = 修改后的巨鬣狗判定阈值;
he.IOU_5 = 修改后的铲齿象判定阈值;
he.IOU_6 = 修改后的三趾马判定阈值;
he.print_result = true; //打印一维长度为6的tensor格式输出
he.print_variance = true; //打印方差
he.variance_x_max = 修改后的横坐标方差最大阈值;
he.variance_y_max = 修改后的纵坐标方差最大阈值;
实例演示
1、首先新建一个空白项目,把以下4个文件放入项目文件夹下
2、按照文章开头说明配置好环境
3、新建源文件test.cpp,添加头文件-现有项 HeZheng_dll.h
4、test.cpp
#include "HeZheng_dll.h"
void main() {
vector<string> Animal_names = { "Rhinoceros","Tiger","Sheep","Dog","Elephant","Horse" };
vector<cv::Scalar> Animal_colors = { {0,0,255},{255,255,0},{0,255,0},{255,0,0},{160,32,240},{210,105,30} };
HeZheng he; //初始化类对象
cv::VideoCapture cap(1); //定义摄像头输入端口
cv::Mat frame; //定义摄像头获取每帧画面
cap.set(cv::CAP_PROP_EXPOSURE, -10.5); //调节摄像头曝光度
while (true)
{
he.allPoints.clear(); //每次识别后需要清空上次识别的点集合
cv::Mat Result = he.black.clone(); //每次识别后需要重新定义黑底图片
while (true)
{
cap.read(frame); //摄像头读帧
vector<int> newPoints = he.DetectPoint(frame); //获取目标点坐标
he.DrawOnCanVas(newPoints, Result); //绘制轨迹图像
int result = he.Prediction(Result); //判断轨迹图像得到结果
if (he.Result_stable(result, 30)) //结果稳定算法,判断是否稳定
{
cv::putText(Result, Animal_names[result - 1],cv::Point(20,50), cv::FONT_HERSHEY_SIMPLEX, 1.5, Animal_colors[result - 1], 2);
cv::imshow("Result", Result);
}
else
{
cv::imshow("Result", Result);
}
if (cv::waitKey(1) == 27)
{
break;
}
}
}
}
5、结果演示
结果演示