OpenCV 4.12.0
开源计算机视觉
加载中...
搜索中...
无匹配项
使用神经网络检测色彩检查器

在本教程中,您将学习如何使用神经网络来提高图表检测算法的准确性。

构建

构建 OpenCV 时,运行以下命令来构建所有 contrib 模块

cmake -D OPENCV_EXTRA_MODULES_PATH=<opencv_contrib>/modules/

或者仅构建 mcc 模块

cmake -D OPENCV_EXTRA_MODULES_PATH=<opencv_contrib>/modules/mcc

或者确保您在 CMake 的 GUI 版本中选中 mcc 模块:cmake-gui。

示例的源代码

您可以通过执行以下操作来运行示例代码

<您的 OpenCV 构建目录路径>/bin/example_mcc_chart_detection_with_network -t=<图表类型> -m=<神经网络路径> -pb=<模型 pbtxt 路径> -v=<可选的视频路径,如果未提供,将使用网络摄像头.mp4> --ci=<可选的摄像头 ID,仅在未提供视频时需要> --nc=<图像中可选的最大图表数量> --use_gpu <可选的是否应使用 GPU>
``'
* -t=# 是图表类型,其中 0(标准)、1(DigitalSG)、2(Vinyl)
* --ci=# 是摄像头 ID,其中 0(默认是主摄像头),1(辅助摄像头)等
* --nc=# 默认情况下其值为 1,这意味着只会检测到最佳图表
示例

在 CPU 上简单运行(不使用 GPU) /home/opencv/build/bin/example_mcc_chart_detection_with_network -t=0 -m=/home/model.pb –pb=/home/model.pbtxt -v=mcc24.mp4

在 GPU 上运行 /home/opencv/build/bin/example_mcc_chart_detection_with_network -t=0 -m=/home/model.pb –pb=/home/model.pbtxt -v=mcc24.mp4 –use_gpu

在 GPU 上运行并检测最佳 5 个图表(检测数量可以少于 5 个,但不能超过 5 个) /home/opencv/build/bin/example_mcc_chart_detection_with_network -t=0 -m=/home/model.pb –pb=/home/model.pbtxt -v=mcc24.mp4 –use_gpu –nc=5 ```

1#include <opencv2/core.hpp>
2
3#include <opencv2/highgui.hpp>
4#include <opencv2/mcc.hpp>
5#include <opencv2/dnn.hpp>
6#include <iostream>
7
8using namespace std;
9using namespace cv;
10using namespace mcc;
11
12const char *about = "使用神经网络的基本图表检测";
13const char *keys = {
14 "{ help h usage ? | | 显示此消息 }"
15 "{t | 0 | chartType:0-标准,1-DigitalSG,2-Vinyl,默认值:0}"
16 "{m | | 模型的文件路径,如果您没有模型,可以在文档中找到链接}"
17 找到链接}"
18 "{pb | | pbtxt 文件的文件路径,与模型文件一起提供}"
19 文件}"
20 "{v | | 来自视频文件的输入,如果省略,则输入来自摄像头 }"
21 "{ci | 0 | 如果输入不是来自视频(-v),则摄像头 ID }"
22 "{nc | 1 | 图像中图表的最大数量 }"
23 "{use_gpu | | 如果您想使用 GPU,请添加此标志}"};
24
25int main(int argc, char *argv[])
26{
27 // ----------------------------------------------------------
28 // 向下滚动一点(~50 行)以找到实际相关的代码
29 // ----------------------------------------------------------
30
31 CommandLineParser parser(argc, argv, keys);
32 parser.about(about);
33
34 if (parser.has("help"))
35 {
36 parser.printMessage();
37 return -1;
38 }
39
40 int t = parser.get<int>("t");
41
42 CV_Assert(0 <= t && t <= 2);
43 TYPECHART chartType = TYPECHART(t);
44
45 string model_path = parser.get<string>("m");
46 string pbtxt_path = parser.get<string>("pb");
47
48 int camId = parser.get<int>("ci");
49 int nc = parser.get<int>("nc");
50
51 String video;
52
53 if (parser.has("v"))
54 video = parser.get<String>("v");
55
56 bool use_gpu = parser.has("use_gpu");
57
58 if (!parser.check())
59 {
60 parser.printErrors();
61 return 0;
62 }
63
64 VideoCapture inputVideo;
65 int waitTime;
66 if (!video.empty())
67 {
68 inputVideo.open(video);
69 waitTime = 10;
70 }
71 else
72 {
73 inputVideo.open(camId);
74 waitTime = 10;
75 }
76
77 //--------------------------------------------------------------------------
78 //-------------------------实际相关的代码-----------------------------
79 //--------------------------------------------------------------------------
80
81 //加载网络
82
83 cv::dnn::Net net = cv::dnn::readNetFromTensorflow(model_path, pbtxt_path);
84
85 if (use_gpu)
86 {
87 net.setPreferableBackend(dnn::DNN_BACKEND_CUDA);
88 net.setPreferableTarget(dnn::DNN_TARGET_CUDA);
89 }
90
91 Ptr<CCheckerDetector> detector = CCheckerDetector::create();
92 if (!detector->setNet(net))
93 {
94 cout << "加载模型失败:中止" << endl;
95 return 0;
96 }
97
98 while (inputVideo.grab())
99 {
100 Mat image, imageCopy;
101 inputVideo.retrieve(image);
102
103 imageCopy = image.clone();
104
105 // 要检测的标记类型
106 if (!detector->process(image, chartType, nc, true))
107 {
108 printf("未检测到 ChartColor \n");
109 }
110 else
111 {
112
113 // 获取检查器
114 std::vector<Ptr<mcc::CChecker>> checkers = detector->getListColorChecker();
115 for (Ptr<mcc::CChecker> checker : checkers)
116 {
117 // 当前检查器
118
119 Ptr<CCheckerDraw> cdraw = CCheckerDraw::create(checker);
120 cdraw->draw(image);
121 }
122 }
123
124 imshow("图像结果 | q 或 esc 退出", image);
125 imshow("原始", imageCopy);
126 char key = (char)waitKey(waitTime);
127 if (key == 27)
128 break;
129 }
130
131 return 0;
132}
如果数组没有元素,则返回 true。
int64_t int64
n 维密集数组类
定义 mat.hpp:830
CV_NODISCARD_STD Mat clone() const
创建数组及其底层数据的完整副本。
用于从视频文件、图像序列或摄像头捕获视频的类。
Definition videoio.hpp:772
virtual bool open(const String &filename, int apiPreference=CAP_ANY)
打开视频文件或捕获设备或 IP 视频流以进行视频捕获。
virtual bool retrieve(OutputArray image, int flag=0)
解码并返回捕获的视频帧。
virtual bool grab()
从视频文件或捕获设备捕获下一帧。
此类允许创建和操作全面的神经网络。
定义 dnn.hpp:475
void setPreferableBackend(int backendId)
要求网络使用其支持的特定计算后端。
void setPreferableTarget(int targetId)
要求网络在特定目标设备上进行计算。
std::string String
定义 cvstd.hpp:151
std::shared_ptr< _Tp > Ptr
Definition cvstd_wrapper.hpp:23
#define CV_Assert(expr)
在运行时检查条件,如果失败则抛出异常。
定义 base.hpp:423
Net readNetFromTensorflow(CV_WRAP_FILE_PATH const String &model, CV_WRAP_FILE_PATH const String &config=String())
读取以 TensorFlow 框架格式存储的网络模型。
void imshow(const String &winname, InputArray mat)
在指定窗口中显示图像。
int waitKey(int delay=0)
等待按键按下。
int main(int argc, char *argv[])
定义 highgui_qt.cpp:3
定义 core.hpp:107
STL 命名空间。

说明

  1. 设置头文件和命名空间

    #include <opencv2/mcc.hpp>
    using namespace std;
    using namespace cv;
    using namespace mcc;

    如果需要,您可以像上面的代码一样设置命名空间。

  2. 创建检测器对象

    Ptr<CCheckerDetector> detector = CCheckerDetector::create();

    这只是为了创建对象。

  3. 加载模型

    cv::dnn::Net net = cv::dnn::readNetFromTensorflow(model_path, pbtxt_path);

    加载模型,此处提供的模型是在 tensorflow 中训练的,因此我们将其加载到 tensorflow 中,但是如果您有在其他框架中训练的其他模型,也可以使用它。

  4. (可选)将 dnn 后端设置为 CUDA

    net.setPreferableBackend(dnn::DNN_BACKEND_CUDA);
    net.setPreferableTarget(dnn::DNN_TARGET_CUDA);

    模型在 CUDA 上运行得更快,因此如果可能,请使用 CUDA。

  5. 运行检测器

    detector->process(image, chartType, max_number_charts_in_image, true);

    如果检测器成功检测到至少一个图表,则返回 true,否则返回 false。在上面给出的代码中,如果没有检测到任何图表,我们会打印一条失败消息。否则,如果成功,则颜色图表列表存储在检测器本身中,我们将在下一步中看到如何提取它。第四个参数用于决定是否使用网络。

  6. 获取颜色检查器列表

    std::vector<cv::Ptr<mcc::CChecker>> checkers;
    detector->getListColorChecker(checkers);

    所有检测到的颜色检查器现在都存储在“checkers”向量中。

  7. 将颜色检查器绘制回图像

    for(Ptr<mcc::CChecker> checker : checkers)
    {
    // 当前检查器
    Ptr<CCheckerDraw> cdraw = CCheckerDraw::create(checker);
    cdraw->draw(image);
    }

    逐个循环遍历所有检查器,然后绘制它们。