热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

VS+Yolov3+QT+opencv(GPU版)

环境:系统:win10(显卡:NVIDIAGTX950M)Yolo版本:V3cuda:9.0cudnn:9.0opencv:3.4.9VS:20151、环境准
环境:
系统:win10 (显卡:NVIDIA GTX 950M)
Yolo版本:V3
cuda:9.0
cudnn:9.0
opencv:3.4.9
VS:2015

1、环境准备:

1.1、下载Yolov3(darknet)

下载链接:https://github.com/AlexeyAB/darknet

1.2、下载权重文件(yolov3.weights)

下载链接:https://link.csdn.net/?target=https%3A%2F%2Fpjreddie.com%2Fmedia%2Ffiles%2Fyolov3.weights
下载完成后,将yolov3.weights文件复制到E:\yolo\darknet-master\darknet-master\build\darknet\x64目录下。

1.3、下载CUDA 9.0

下载链接:链接:https://pan.baidu.com/s/1LLMmFVOCSLvaY4GzTuVYcg
提取码:kkvb
安装过程网上搜教程就行了,挺简单的(PS:CUDA版本需根据自己电脑配置选择,我电脑显卡是:NVIDIA GTX 950M的,一开始我装CUDA10.0和11.0都不行,后来改为9.0可以了,也是一波三折)

1.4、下载CUDNN 9.0

下载链接:链接:https://pan.baidu.com/s/1d-yigqIoy9q6Ha5-fdJkSA
提取码:74kw
将里面3个文件夹里的每个文件复制到C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0目录下对应的文件夹中即可。

1.4、opencv3.4.9和VS2015

网上搜索安装即可并将opencv配置到VS2015中

2、编译Yolo

2.1、编译darknet.exe

2.1.1、找到darknet.vcxproj用EditPlus打开CTRL+F搜索CUDA 11.1全部改为9.0然后保存。共2处

 

2.1.2、打开darknet.sln

修改为Release X64模式,然后生成即可。

3、运行yolov3

双击darknet_yolo_v3.cmd识别图片实例;而darknet_web_cam_voc.cmd是打开笔记本摄像头动态检测识别。

4、编译Yolov3动态链接库

打开yolo_cpp_dll.sln在Release X64模式下生成(也要修改yolo_cpp_dll.vcxproj中的cuda版本)
会生成yolo_cpp_dll.dll和yolo_cpp_dll.lib的库文件

5、使用yolo的动态链接库进行开发

使用yolo编译好的yolo_cpp_dll.dll和yolo_cpp_dll.lib的库文件和API:yolo_v2_class.hpp头文件
mainwindow.h
#pragma once
//这段代码一定要加,这是在yolo_v2_class.hpp文件中使用opencv函数
#ifdef _WIN32
#define OPENCV
#define GPU
#endif

#include 
#include "ui_mianwindow.h"
#include "yolo_v2_class.hpp"
#include "opencv\highgui.h"
#include "opencv2\opencv.hpp"
#include "opencv2\core\core.hpp"
#include "opencv2\highgui\highgui.hpp"
#include 
#include 

#pragma comment(lib, "yolo_cpp_dll.lib")//引入yolo链接库
#pragma execution_character_set("utf-8")
using namespace cv;

class mianwindow : public QMainWindow
{
    Q_OBJECT

public:
    mianwindow(QWidget *parent = Q_NULLPTR);

    void draw_boxes(Mat mat_img, std::vector result_vec, std::vectorstring> obj_names);

    std::vectorstring> objects_names_from_file(std::string const filename);
    QImage cvMat2QImage(const Mat& mat);
    Mat QImage2cvMat(QImage image);


private:
    Ui::mianwindowClass ui;
};

mainwindow.cpp

#include "mianwindow.h"
#include "yolo_v2_class.hpp"
#include 
mianwindow::mianwindow(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);

    QImage q_image(QString("E:/TX_workCode/DataInfo/images/dog.jpg"));

    ui.label_img->setPixmap(QPixmap::fromImage(q_image));
    
    std::string names_file = "coco.names";
    std::string cfg_file = "yolov3.cfg";
    std::string weights_file = "yolov3.weights";
    Detector detector(cfg_file, weights_file); //初始化Detector

    std::vectorstring> obj_names;
    obj_names = objects_names_from_file(names_file);
    //测试是否成功读入分类对象文件
    for (int i = 0; i )
    {
        qDebug() <<"第i个:" << QString(QString::fromLocal8Bit(obj_names[i].c_str()));
    }
    
    Mat frame = QImage2cvMat(q_image);
    std::vector result_vec = detector.detect(frame);
    draw_boxes(frame, result_vec, obj_names);

    QImage det_image = cvMat2QImage(frame);
    ui.label_detectorImg->setPixmap(QPixmap::fromImage(det_image));

}
//以下draw_boxes和objects_names_from_file两段代码来自yolo_console_dll.sln
//给Mat类型的图像画出检测出对象框
void mianwindow::draw_boxes(cv::Mat mat_img, std::vector result_vec, std::vectorstring> obj_names)
{
    int const colors[6][3] = { { 1,0,1 },{ 0,0,1 },{ 0,1,1 },{ 0,1,0 },{ 1,1,0 },{ 1,0,0 } };
    for (auto &i : result_vec) {
        cv::Scalar color = obj_id_to_color(i.obj_id);
        cv::rectangle(mat_img, cv::Rect(i.x, i.y, i.w, i.h), color, 2);
        if (obj_names.size() > i.obj_id) {
            std::string obj_name = obj_names[i.obj_id];
            if (i.track_id > 0) obj_name += " - " + std::to_string(i.track_id);
            cv::Size const text_size = getTextSize(obj_name, cv::FONT_HERSHEY_COMPLEX_SMALL, 1.2, 2, 0);
            int const max_width = (text_size.width > i.w + 2) ? text_size.width : (i.w + 2);
            cv::rectangle(mat_img, cv::Point2f(std::max((int)i.x - 1, 0), std::max((int)i.y - 30, 0)),
                cv::Point2f(std::min((int)i.x + max_width, mat_img.cols - 1), std::min((int)i.y, mat_img.rows - 1)),
                color, CV_FILLED, 8, 0);
            putText(mat_img, obj_name, cv::Point2f(i.x, i.y - 10), cv::FONT_HERSHEY_COMPLEX_SMALL, 1.2, cv::Scalar(0, 0, 0), 2);
        }
    }

}
//读names文件中对象类别名称保存在vector容器中
std::vectorstring> mianwindow::objects_names_from_file(std::string const filename) {
    std::ifstream file(filename);
    std::vectorstring> file_lines;
    if (!file.is_open()) return file_lines;
    for (std::string line; getline(file, line);) file_lines.push_back(line);
    std::cout <<"object names loaded \n";
    return file_lines;
}

//---------QImage与Mat类型相互转换----------------------------------------------------------
QImage mianwindow::cvMat2QImage(const cv::Mat& mat)
{
    // 8-bits unsigned, NO. OF CHANNELS = 1  
    if (mat.type() == CV_8UC1)
    {
        QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
        // Set the color table (used to translate colour indexes to qRgb values)  
        image.setColorCount(256);
        for (int i = 0; i <256; i++)
        {
            image.setColor(i, qRgb(i, i, i));
        }
        // Copy input Mat  
        uchar *pSrc = mat.data;
        for (int row = 0; row )
        {
            uchar *pDest = image.scanLine(row);
            memcpy(pDest, pSrc, mat.cols);
            pSrc += mat.step;
        }
        return image;
    }
    // 8-bits unsigned, NO. OF CHANNELS = 3  
    else if (mat.type() == CV_8UC3)
    {
        // Copy input Mat  
        const uchar *pSrc = (const uchar*)mat.data;
        // Create QImage with same dimensions as input Mat  
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
        return image.rgbSwapped();
    }
    else if (mat.type() == CV_8UC4)
    {
        qDebug() <<"CV_8UC4";
        // Copy input Mat  
        const uchar *pSrc = (const uchar*)mat.data;
        // Create QImage with same dimensions as input Mat  
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
        return image.copy();
    }
    else
    {
        qDebug() <<"ERROR: Mat could not be converted to QImage.";
        return QImage();
    }
}
cv::Mat mianwindow::QImage2cvMat(QImage image)
{
    cv::Mat mat;
    qDebug() << image.format();
    switch (image.format())
    {
    case QImage::Format_ARGB32:
    case QImage::Format_RGB32:
    case QImage::Format_ARGB32_Premultiplied:
        mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine());
        break;
    case QImage::Format_RGB888:
        mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine());
        cv::cvtColor(mat, mat, CV_BGR2RGB);
        break;
    case QImage::Format_Indexed8:
        mat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine());
        break;
    }
    return mat;
}

 6、运行结果

 

 

 
 
 
 
 
 
 
 
 

报错:error MSB3721

解决办法:
问题产生的原因:
sm_XX,compute_XX:表示自己电脑显卡的计算能力,显卡越好值越高,自己显卡对应的值可以查看英伟达官网
 
由于自己电脑显卡有好有坏,对应的sm_XX,compute_XX值也不一样,出现上述错误的原因主要是当前运行的程序里的sm_XX,compute_XX值选取不当。如下图是我自己程序中设置sm_XX,compute_XX的值。(我将sm_30改为了sm_35可以)
 
 
参考链接:
1、https://blog.csdn.net/lixudem/article/details/106993430?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.control
2、https://blog.csdn.net/sinat_41852207/article/details/90906309?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-5.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-5.control
3、https://blog.csdn.net/alansss/article/details/104448347?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161095690516780271532753%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=161095690516780271532753&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v29-3-104448347.first_rank_v2_pc_rank_v29&utm_term=win10%E7%BC%96%E8%AF%91yolov3%E6%97%B6%E6%8A%A5%E9%94%99error%20MSB3721&spm=1018.2226.3001.4187
4、https://blog.csdn.net/jin739738709/article/details/90342696
5、https://blog.csdn.net/stjuliet/article/details/87884976?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161102361916780269894467%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=161102361916780269894467&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v29-3-87884976.first_rank_v2_pc_rank_v29&utm_term=%E4%BD%BF%E7%94%A8yolo%E7%9A%84%E5%8A%A8%E6%80%81%E9%93%BE%E6%8E%A5%E5%BA%93&spm=1018.2226.3001.4187


推荐阅读
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 使用nodejs爬取b站番剧数据,计算最佳追番推荐
    本文介绍了如何使用nodejs爬取b站番剧数据,并通过计算得出最佳追番推荐。通过调用相关接口获取番剧数据和评分数据,以及使用相应的算法进行计算。该方法可以帮助用户找到适合自己的番剧进行观看。 ... [详细]
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • 本文详细介绍了如何创建和使用VUE uni-app开发环境,包括通过HBuilderX可视化界面和通过vue-cli命令执行的方法。文章内容简单清晰,易于学习与理解。通过学习本文,读者可以深入了解VUE uni-app开发环境,并通过实践验证掌握具体的使用情况。编程笔记将为读者推送更多相关知识点的文章,欢迎关注! ... [详细]
  • 使用eclipse创建一个Java项目的步骤
    本文介绍了使用eclipse创建一个Java项目的步骤,包括启动eclipse、选择New Project命令、在对话框中输入项目名称等。同时还介绍了Java Settings对话框中的一些选项,以及如何修改Java程序的输出目录。 ... [详细]
author-avatar
yaoyinghua2012
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有