QT+opencv+dnn调用预训练好的模型

8 篇文章 0 订阅
3 篇文章 0 订阅

由于项目需要,需要在QT中进行图片分类,准备用opencv自带的dnn模块,调用训练好的模型。
win7/64+QT5.11.1+opencv3.4.1

1.QTCreator配置opencv

先测试是否可用,QTCreator的pro文件先添加opencv库。(默认系统环境变量已添加opencv的bin目录)

CONFIG(debug,debug|release) {
    TARGET = $$join(TARGET,,,_d)
}


Debug {
        contains(QMAKE_COMPILER_DEFINES, _WIN64) {
                LIBS += -LH:/opencv/opencv/newbuild/install/x64/vc15/lib				-lopencv_img_hash341d
                LIBS += -LH:/opencv/opencv/newbuild/install/x64/vc15/lib				-lopencv_world341d
                DESTDIR = ./Bin/x64
        }
        else {
        }
}
else {
        contains(QMAKE_COMPILER_DEFINES, _WIN64) {
                LIBS += -LH:/opencv/opencv/newbuild/install/x64/vc15/lib				-lopencv_img_hash341
                LIBS += -LH:/opencv/opencv/newbuild/install/x64/vc15/lib				-lopencv_world341
                DESTDIR = ./Bin/x64
        }
        else {
        }
}

INCLUDEPATH += \
            H:/opencv/opencv/newbuild/install/include\
            H:/opencv/opencv/newbuild/install/include/opencv\
            H:/opencv/opencv/newbuild/install/include/opencv2\

测试opencv是否可用

2.百度上找一张直升飞机的图片,修改main函数,打开图片,测试opencv库是否配置成功

#include "opencvmat.h"

#include <iostream>

#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

using namespace std;
using namespace cv;

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Mat src = cv::imread("F:/DahuaSDKC++/opencvtest/airplane.jpg");
    cv::namedWindow("input", CV_WINDOW_AUTOSIZE);
    cv::imshow("input", src);
    cv::waitKey(0);
    //opencvMat w;
    //w.show();

    return a.exec();
}

这里之前用的相对路径,读取有的图片成功,有的有问题,出过一个opencv错误:断言失败的问题,后来查了之后改成绝对路径就好了。
参考:https://blog.csdn.net/lijinshanba/article/details/78888159

3.准备模型

oepncv没问题就可以准备模型文件了,参考很多案例,下了一堆模型,出现问题好像都是因为.pb和.pbtxt文件不匹配之类的,蛋疼。
后来找到一个案例:https://blog.csdn.net/qq_35054151/article/details/82916424
1.首先我们需要下载训练好的googlenet权重模型bvlc_googlenet .caffemodel(二进制文件),模型下载地址为
http://dl.caffe.berkeleyvision.org/
2.然后导入模型描述文件,地址为H:\opencv\opencv\sources\samples\data\dnn(这里具体路径看自己opencv的路径)
把打勾的两个文件拷过去
在这里插入图片描述

4.测试程序

修改main函数如下:我这里都是用的绝对路径

#include "opencvmat.h"
#include <QApplication>

#include <iostream>
#include <string>
#include <vector>

#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

using namespace std;
using namespace cv;
using namespace dnn;

String model_file = "F:/DahuaSDKC++/opencvtest/bvlc_googlenet.caffemodel";
String model_txtfile = "F:/DahuaSDKC++/opencvtest/bvlc_googlenet.prototxt";
String labels_file = "F:/DahuaSDKC++/opencvtest/synset_words.txt";

vector<String>readLabels();

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    Mat src = cv::imread("F:/DahuaSDKC++/opencvtest/airplane.jpg");
    namedWindow("input", CV_WINDOW_AUTOSIZE);
    cv::imshow("input", src);
    
    //读取模型的类别(文本)
    vector<String> labels = readLabels();


    //读取google_net的模型和描述文件
    Net net = readNetFromCaffe(model_txtfile, model_file);
    if (net.empty()) {
        printf("read caffee model data failure\n");
        return -1;
    }

    //将图像转为google_net网络输入的对象,由描述文件可知,图像尺寸统一为224*224
    Mat inputBlob = blobFromImage(src, 1.0, Size(224, 224), Scalar(104, 117, 123));
    //进行前向传播,由描述文件可知,第一层用了10个卷积层,提取图像10种不同的特征
    Mat prob;

    for (int i = 0; i < 10; i++) {
        net.setInput(inputBlob, "data");
        prob = net.forward("prob");//最后一层的输出为“prob”
    }

    //输出
    //得到的概率值为1行1000列的
    Mat promat = prob.reshape(1, 1);
    Point classLoc;
    double classProb;
    minMaxLoc(promat, NULL, &classProb, NULL, &classLoc);
    printf("current image classification: %s,probablity %f\n", labels.at(classLoc.x).c_str(), classProb);

    putText(src, labels.at(classLoc.x), Point(20, 20), FONT_HERSHEY_COMPLEX, 1.0, Scalar(0, 0, 255), 2);

    imshow("output", src);

    waitKey(0);
    //opencvMat w;
    //w.show();

    return a.exec();
}

//读取模型的类别(文本)

vector<String>readLabels() {
    vector<String>classNames;
    ifstream fp(labels_file);//打开文件
    if (!fp.is_open()) {//文件没打开
        printf("could not open the file ");
        exit(-1);
    }

    string name;

    while (!fp.eof()) {//文件没读到结尾
        getline(fp, name);//得到每一行,放到name中
        if (name.length()) {//非空行
            classNames.push_back(name.substr(name.find(' ') + 1));//
        }
    }

    fp.close();
    return classNames;
}

5结果展示

在这里插入图片描述

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值