参考:https://github.com/spmallick/learnopencv
cvui:一个构建在OpenCV绘图基元之上的GUI库
通常计算机视觉项目的开发涉及调整技术的参数以实现期望的结果。例如,这些参数可以是边缘检测算法的阈值或图像的亮度。如果您不使用任何图形用户界面(GUI)来调整这些参数,则需要停止您的应用程序,调整您的代码,再次运行应用程序,评估并重复,直到它为好。这是乏味和耗时的。
有很多很棒的GUI库,例如Qt和imgui,可以和OpenCV一起使用,以便在运行时调整参数。在Mac上使用OpenCV的Qt,看看这个帖子。但是,可能有些情况下,您没有(或不想)这些库的依赖关系,例如,你还没有用Qt支持编译OpenCV,或者你不能使用OpenGL。在这种情况下,所有你需要的是创建一个GUI来调整你的算法的快速和无忧无虑的方式。
这就是cvui的目的。它是建立在OpenCV绘图基元之上的C ++,仅标题和跨平台(Windows,Linux和OSX)UI库。除OpenCV之外,它没有任何依赖性(您可能已经在使用它)。
遵循规则
一行代码应该在屏幕上产生一个UI组件。
结果,lib具有友好的C类API,没有类/对象和多个组件,例如, 跟踪栏,按钮,文字等等:
一些在cvui中可用的UI组件。
如何在你的应用程序中使用cvui
为了使用cvui,你只需在你的项目中包含cvui.h,给它一个图像(即cv :: Mat)来渲染组件,你就完成了!
基本的“hello world”应用程序
让我们看看cvui的功能,通过创建一个简单的hello-world应用程序与一些UI交互。 该应用程序包含一个按钮和一个可视指示器,显示该按钮被点击的次数。 这里是代码:
注:cvui.h 下载参考https://github.com/Dovyski/cvui
将cvui.h文件复制到工程文件中即可
#include <opencv2/opencv.hpp>
#include "cvui.h"
#define WINDOW_NAME "CVUI Hello World!"
int main(void)
{
cv::Mat frame = cv::Mat(200, 500, CV_8UC3);
int count = 0;
// Init a OpenCV window and tell cvui to use it.
cv::namedWindow(WINDOW_NAME);
cvui::init(WINDOW_NAME);
while (true) {
// Fill the frame with a nice color
frame = cv::Scalar(49, 52, 49);
// Show a button at position (110, 80)
if (cvui::button(frame, 110, 80, "Hello, world!")) {
// The button was clicked, so let's increment our counter.
count++;
}
// Show how many times the button has been clicked.
// Text at position (250, 90), sized 0.4, in red.
cvui::printf(frame, 250, 90, 0.4, 0xff0000, "Button click count: %d", count);
// Update cvui internal stuff
cvui::update();
// Show everything on the screen
cv::imshow(WINDOW_NAME, frame);
// Check if ESC key was pressed
if (cv::waitKey(20) == 27) {
break;
}
}
return 0;
}
确保cvui与您的项目正常工作
1、在渲染任何组件之前调用初始化函数cvui :: init()。
2、所有组件都被渲染后调用cvui :: update()一次。
关于上面代码中使用的组件,cvui :: button()函数每次点击按钮都会返回true,所以你可以方便的在if语句中使用它。 cvui :: printf()函数与标准C printf()函数的工作方式类似,所以您可以使用符号%d和%s轻松地在屏幕上呈现文本和数字。 您还可以使用十六进制值作为0xRRGGBB来选择文本的颜色,例如 0xFF0000(红色),0x00FF00(绿色)和0x0000FF(蓝色)。
更高级的应用程序
现在让我们来构建一些更复杂的东西,但是和以前一样容易。 应用程序将Canny Edge算法应用于图像,允许用户启用/禁用该技术并调整其阈值。
步骤1:基础
我们首先创建一个没有UI元素的应用程序。 Canny Edge算法的使用由布尔变量(use_canny)定义,而算法阈值由两个整数(low_threshold和high_threshold)定义。 使用这种方法,我们必须重新编译代码,每次我们要启用/禁用该技术或调整其阈值。
该应用程序的代码如下:
#include <opencv2/opencv.hpp>
#define WINDOW_NAME "CVUI Canny Edge"
int main(int argc, const char *argv[])
{
cv::Mat lena = cv::imread("lena.jpg");
cv::Mat frame = lena.clone();
int low_threshold = 50, high_threshold = 150;
bool use_canny = false;
cv::namedWindow(WINDOW_NAME);
while (true) {
// Should we apply Canny edge?
if (use_canny) {
// Yes, we should apply it.
cv::cvtColor(lena, frame, CV_BGR2GRAY);
cv::Canny(frame, frame, low_threshold, high_threshold, 3);
} else {
// No, so just copy the original image to the displaying frame.
lena.copyTo(frame);
}
// Show everything on the screen
cv::imshow(WINDOW_NAME, frame);
// Check if ESC was pressed
if (cv::waitKey(30) == 27) {
break;
}
}
return 0;
}
结果是显示原始图像(use_canny为false)或显示检测到的边缘(use_canny为true)的应用程序:
步骤2:动态启用/禁用边缘检测
我们通过使用cvui并添加一个复选框来控制use_canny的值来改进工作流程。 使用该方法,用户可以在应用程序仍在运行时启用/禁用Canny Edge。 我们添加所需的cvui代码并使用cvui :: checkbox函数:
#include <opencv2/opencv.hpp>
#include "cvui.h"
#define WINDOW_NAME "CVUI Canny Edge"
int main(void)
{
cv::Mat lena = cv::imread("lena.jpg");
cv::Mat frame = lena.clone();
int low_threshold = 50, high_threshold = 150;
bool use_canny = false;
// Init a OpenCV window and tell cvui to use it.
cv::namedWindow(WINDOW_NAME);
cvui::init(WINDOW_NAME);
while (true) {
// Should we apply Canny edge?
if (use_canny) {
// Yes, we should apply it.
cv::cvtColor(lena, frame, CV_BGR2GRAY);
cv::Canny(frame, frame, low_threshold, high_threshold, 3);
} else {
// No, so just copy the original image to the displaying frame.
lena.copyTo(frame);
}
// Checkbox to enable/disable the use of Canny edge
cvui::checkbox(frame, 15, 80, "Use Canny Edge", &use_canny);
// Update cvui internal stuff
cvui::update();
// Show everything on the screen
cv::imshow(WINDOW_NAME, frame);
// Check if ESC was pressed
if (cv::waitKey(30) == 27) {
break;
}
}
return 0;
}
单独这个小的修改已经是测试应用程序而不重新编译所有内容的时间保护程序了:
根据正在使用的图像可能难以看到呈现的复选框及其标签。 有白色背景的图象。 我们可以通过使用cvui :: window()来创建一个窗口来防止这个问题。
cvui在调用组件函数时呈现每个组件,因此我们必须在cvui :: checkbox()之前调用cvui :: window(),否则窗口将显示在复选框前面:
#include <opencv2/opencv.hpp>
#include "cvui.h"
#define WINDOW_NAME "CVUI Canny Edge"
int main(void)
{
cv::Mat lena = cv::imread("lena.jpg");
cv::Mat frame = lena.clone();
int low_threshold = 50, high_threshold = 150;
bool use_canny = false;
// Init a OpenCV window and tell cvui to use it.
cv::namedWindow(WINDOW_NAME);
cvui::init(WINDOW_NAME);
while (true) {
// Should we apply Canny edge?
if (use_canny) {
// Yes, we should apply it.
cv::cvtColor(lena, frame, CV_BGR2GRAY);
cv::Canny(frame, frame, low_threshold, high_threshold, 3);
} else {
// No, so just copy the original image to the displaying frame.
lena.copyTo(frame);
}
// Render the settings window to house the UI
cvui::window(frame, 10, 50, 180, 180, "Settings");
// Checkbox to enable/disable the use of Canny edge
cvui::checkbox(frame, 15, 80, "Use Canny Edge", &use_canny);
// Update cvui internal stuff
cvui::update();
// Show everything on the screen
cv::imshow(WINDOW_NAME, frame);
// Check if ESC was pressed
if (cv::waitKey(30) == 27) {
break;
}
}
return 0;
}
第3步:调整阈值
现在是时候允许用户在运行时选择low_threashold和high_threashold的值了。 由于这些参数可以在一个时间间隔内变化,我们可以使用cvui :: trackbar()来创建一个trackbar:
#include <opencv2/opencv.hpp>
#include "cvui.h"
#define WINDOW_NAME "CVUI Canny Edge"
int main(void)
{
cv::Mat lena = cv::imread("lena.jpg");
cv::Mat frame = lena.clone();
int low_threshold = 50, high_threshold = 150;
bool use_canny = false;
// Init a OpenCV window and tell cvui to use it.
cv::namedWindow(WINDOW_NAME);
cvui::init(WINDOW_NAME);
while (true) {
// Should we apply Canny edge?
if (use_canny) {
// Yes, we should apply it.
cv::cvtColor(lena, frame, CV_BGR2GRAY);
cv::Canny(frame, frame, low_threshold, high_threshold, 3);
} else {
// No, so just copy the original image to the displaying frame.
lena.copyTo(frame);
}
// Render the settings window to house the UI
cvui::window(frame, 10, 50, 180, 180, "Settings");
// Checkbox to enable/disable the use of Canny edge
cvui::checkbox(frame, 15, 80, "Use Canny Edge", &use_canny);
// Two trackbars to control the low and high threshold values
// for the Canny edge algorithm.
cvui::trackbar(frame, 15, 110, 165, &low_threshold, 5, 150);
cvui::trackbar(frame, 15, 180, 165, &high_threshold, 80, 300);
// Update cvui internal stuff
cvui::update();
// Show everything on the screen
cv::imshow(WINDOW_NAME, frame);
// Check if ESC was pressed
if (cv::waitKey(30) == 27) {
break;
}
}
return 0;
}
cvui :: trackbar()函数接受指定trackbar允许的最小值和最大值的参数。 在上例中,low_threshold分别为[5,150],high_threshold分别为[80,130]。
其结果是一个完全交互式的应用程序,允许用户快速轻松地探索Canny Edge参数的调整,以及启用/禁用它的使用:
下面是这个应用程序的完整代码,没有评论。 它显示你不需要许多代码行来为你的应用程序生成一个最小的(和有用的)UI:
#include <opencv2/opencv.hpp>
#include "cvui.h"
#define WINDOW_NAME "CVUI Canny Edge"
int main(void)
{
cv::Mat lena = cv::imread("lena.jpg");
cv::Mat frame = lena.clone();
int low_threshold = 50, high_threshold = 150;
bool use_canny = false;
cv::namedWindow(WINDOW_NAME);
cvui::init(WINDOW_NAME);
while (true) {
if (use_canny) {
cv::cvtColor(lena, frame, CV_BGR2GRAY);
cv::Canny(frame, frame, low_threshold, high_threshold, 3);
} else {
lena.copyTo(frame);
}
cvui::window(frame, 10, 50, 180, 180, "Settings");
cvui::checkbox(frame, 15, 80, "Use Canny Edge", &use_canny);
cvui::trackbar(frame, 15, 110, 165, &low_threshold, 5, 150);
cvui::trackbar(frame, 15, 180, 165, &high_threshold, 80, 300);
cvui::update();
cv::imshow(WINDOW_NAME, frame);
if (cv::waitKey(30) == 27) {
break;
}
}
return 0;
}
结论
cvui lib是根据需要创建的。 这并不是为了开发复杂的图形应用程序而成为一个全面的解决方案。 这很简单,有很多方面的限制。 然而,它是实用的,易于使用,可以节省你几个小时的挫折和繁琐的工作。
如果你喜欢cvui,不要忘记在Github上查看它的存储库,它的文档和所有示例应用程序(可以用cmake构建)。