cvui 是一个非常简单的 UI 库,构建在 OpenCV 画图基本原型接口上。其他 UI 库,如imgui, 需要 OpenGL 才能工作。cvui 则不需要。
cvui 只有一个头文件,不需要真的安装,如果需要使用,直接将头文件 cvui.h
放到项目中,并引用即可。或者在 Python
代码中直接引用 cvui.py。
可以通过以下命令在 Python
环境安装
pip install cvui
├── CHANGELOG.md
├── CMakeLists.txt
├── cvui.h
├── cvui.py
├── docs
├── Doxyfile
├── EnhancedWindow.h
├── EnhancedWindow.py
├── example
│ ├── build
│ │ └── README.md
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── cmake_install.cmake
│ ├── data
│ │ ├── fruits.jpg
│ │ ├── lena-face-gray.jpg
│ │ ├── lena-face.jpg
│ │ ├── lena-face-red.jpg
│ │ ├── lena.jpg
│ │ └── sparkline.csv
│ ├── example
│ ├── example.sln
│ ├── Makefile
│ └── src
│ ├── button-shortcut
│ │ ├── button-shortcode.vcxproj.filters
│ │ ├── button-shortcode.vcxproj.user
│ │ ├── button-shortcut.py
│ │ ├── button-shortcut.vcxproj
│ │ ├── CMakeLists.txt
│ │ └── main.cpp
│ ├── canny
│ │ ├── canny.filters
│ │ ├── canny.py
│ │ ├── canny.vcxproj
│ │ ├── canny.vcxproj.user
│ │ ├── CMakeLists.txt
│ │ └── main.cpp
│ ├── complext-layout
│ │ ├── CMakeLists.txt
│ │ ├── complex-layout.filters
│ │ ├── complex-layout.py
│ │ ├── complex-layout.user
│ │ ├── complex-layout.vcxproj
│ │ ├── complex-layout.vcxproj.user
│ │ └── main.cpp
│ ├── hello-world
│ │ ├── CMakeLists.txt
│ │ ├── hello-world.filters
│ │ ├── hello-world.py
│ │ ├── hello-world.vcxproj
│ │ ├── hello-world.vcxproj.user
│ │ └── main.cpp
│ ├── image-button
│ │ ├── CMakeLists.txt
│ │ ├── image-button.py
│ │ ├── image-button.vcxproj
│ │ ├── image-button.vcxproj.filters
│ │ ├── image-button.vcxproj.user
│ │ └── main.cpp
│ ├── interaction-area
│ │ ├── CMakeLists.txt
│ │ ├── image-button.vcxproj.filters
│ │ ├── interaction-area.py
│ │ ├── interaction-area.vcxproj
│ │ ├── interaction-area.vcxproj.user
│ │ └── main.cpp
│ ├── main-app
│ │ ├── CMakeLists.txt
│ │ ├── main-app.py
│ │ ├── main-app.vcxproj
│ │ ├── main-app.vcxproj.filters
│ │ ├── main-app.vcxproj.user
│ │ └── main.cpp
│ ├── mouse
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ ├── mouse.py
│ │ ├── mouse.vcxproj
│ │ ├── mouse.vcxproj.filters
│ │ └── mouse.vcxproj.user
│ ├── mouse-complex
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ ├── mouse-complex.py
│ │ ├── mouse-complex.vcxproj
│ │ ├── mouse-complex.vcxproj.filters
│ │ └── mouse-complex.vcxproj.user
│ ├── mouse-complex-buttons
│ │ ├── CMakeLists.txt
│ │ ├── lena.jpg
│ │ ├── main.cpp
│ │ ├── mouse-complex-buttons.py
│ │ ├── mouse-complex-buttons.vcxproj
│ │ ├── mouse-complex-buttons.vcxproj.filters
│ │ └── mouse-complex-buttons.vcxproj.user
│ ├── multiple-files
│ │ ├── Class1.cpp
│ │ ├── Class1.h
│ │ ├── Class1.py
│ │ ├── Class2.cpp
│ │ ├── Class2.h
│ │ ├── Class2.py
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ ├── multiple-files.filters
│ │ ├── multiple-files.py
│ │ ├── multiple-files.vcxproj
│ │ └── multiple-files.vcxproj.user
│ ├── multiple-windows
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ ├── multiple-windows.filters
│ │ ├── multiple-windows.py
│ │ ├── multiple-windows.vcxproj
│ │ └── multiple-windows.vcxproj.user
│ ├── multiple-windows-complex
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ ├── multiple-windows-complex.filters
│ │ ├── multiple-windows-complex.py
│ │ ├── multiple-windows-complex.user
│ │ ├── multiple-windows-complex.vcxproj
│ │ └── multiple-windows-complex.vcxproj.user
│ ├── multiple-windows-complex-dynamic
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ ├── multiple-windows-complex-dynamic.filters
│ │ ├── multiple-windows-complex-dynamic.py
│ │ ├── multiple-windows-complex-dynamic.user
│ │ ├── multiple-windows-complex-dynamic.vcxproj
│ │ └── multiple-windows-complex-dynamic.vcxproj.user
│ ├── multiple-windows-complex-mouse
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ ├── multiple-windows-complex-mouse.filters
│ │ ├── multiple-windows-complex-mouse.py
│ │ ├── multiple-windows-complex-mouse.user
│ │ ├── multiple-windows-complex-mouse.vcxproj
│ │ └── multiple-windows-complex-mouse.vcxproj.user
│ ├── nested-rows-columns
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ ├── nested-rows-columns.filters
│ │ ├── nested-rows-columns.py
│ │ ├── nested-rows-columns.user
│ │ ├── nested-rows-columns.vcxproj
│ │ └── nested-rows-columns.vcxproj.user
│ ├── on-image
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ ├── on-image.py
│ │ ├── on-image.vcxproj
│ │ ├── on-image.vcxproj.filters
│ │ └── on-image.vcxproj.user
│ ├── row-column
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ ├── row-column.filters
│ │ ├── row-column.py
│ │ ├── row-column.user
│ │ ├── row-column.vcxproj
│ │ └── row-column.vcxproj.user
│ ├── sparkline
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ ├── sparkline.filters
│ │ ├── sparkline.py
│ │ ├── sparkline.user
│ │ ├── sparkline.vcxproj
│ │ └── sparkline.vcxproj.user
│ ├── trackbar
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ ├── trackbar.py
│ │ ├── trackbar.vcxproj
│ │ ├── trackbar.vcxproj.filters
│ │ └── trackbar.vcxproj.user
│ ├── trackbar-complex
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ ├── trackbar-complex.py
│ │ ├── trackbar-complex.vcxproj
│ │ ├── trackbar-complex.vcxproj.filters
│ │ └── trackbar-complex.vcxproj.user
│ ├── trackbar-sparkline
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ ├── trackbar-sparkline.py
│ │ ├── trackbar-sparkline.vcxproj
│ │ ├── trackbar-sparkline.vcxproj.filters
│ │ └── trackbar-sparkline.vcxproj.user
│ ├── ui-enhanced-canny
│ │ ├── canny.filters
│ │ ├── canny.vcxproj
│ │ ├── canny.vcxproj.user
│ │ ├── CMakeLists.txt
│ │ ├── main.cpp
│ │ ├── ui-enhanced-canny.filters
│ │ ├── ui-enhanced-canny.py
│ │ ├── ui-enhanced-canny.vcxproj
│ │ └── ui-enhanced-canny.vcxproj.user
│ └── ui-enhanced-window-component
│ ├── CMakeLists.txt
│ ├── main.cpp
│ ├── ui-enhanced-window-component.py
│ ├── ui-enhanced-window-component.vcxproj
│ ├── ui-enhanced-window-component.vcxproj.filters
│ └── ui-enhanced-window-component.vcxproj.user
├── LICENSE.md
├── python
│ ├── make_dist.sh
│ ├── make_upload.sh
│ ├── package
│ │ ├── cvui
│ │ │ └── __init__.py
│ │ ├── LICENSE.md
│ │ ├── README.md
│ │ └── setup.py
│ └── README.md
└── README.md
cvui 不需要任何构建步骤,只需要添加 cvui.h
或者 cvui.py
到你的源代码中。cvui 除了 OpenCV 3.x (2.x), 没有任何依赖。
example
里提供了很多案例可以使用。
下载代码
git clone https://github.com/Dovyski/cvui.git cvui && cd cvui
编译
mkdir build.release && cd build.release
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++ -DADD_PYTHON_EXAMPLES=ON
make -j4
下载最新的代码,将 cvui.h
放到项目中,并引用。
#define CVUI_IMPLEMENTATION
#include "cvui.h"
IMPORTANT: 如果在多个文件中引用
cvui.h
, 使用#define CVUI_IMPLEMENTATION
仅在一个实现文件中定义,其他文件只需#include "cvui.h"
,不用#define CVUI_IMPLEMENTATION
; 例如:
// File: main.cpp
#define CVUI_IMPLEMENTATION <-- CVUI_IMPLEMENTATION defined in one (and only one) C++ source file.
#include "cvui.h"
// (...)
/
// File: another.cpp
#include "cvui.h"
// (...)
/
// File: MyClass.hpp
#include "cvui.h"
// (...)
/
使用 cvui
之前,我们需要调用 cvui::init()
初始化 cvui
。以下为实例:
#include
#define CVUI_IMPLEMENTATION
#include "cvui.h"
#define WINDOW_NAME "CVUI Test"
int main() {
// Tell cvui to init and create a window
cvui::init(WINDOW_NAME);
while(true) {
// your app logic here
if (cv::waitKey(20) == 27) {
break;
}
}
return 0;
}
所有的 cvui 组件都被渲染到 cv::Mat 里。以下为实例:
#include
#define CVUI_IMPLEMENTATION
#include "cvui.h"
#define WINDOW_NAME "CVUI Test"
int main() {
cvui::init(WINDOW_NAME);
// Create a frame
cv::Mat frame = cv::Mat(cv::Size(400, 200), CV_8UC3);
while(true) {
// clear the frame
frame = cv::Scalar(49, 52, 49);
// render a message in the frame at position (10, 15)
cvui::text(frame, 10, 15, "Hello world!");
if (cv::waitKey(20) == 27) {
break;
}
}
return 0;
}
渲染完后,可以用 cvui::imshow()
进行显示, cvui::imshow
在 cv::imshow
基础上进行了改进。
#include
#define CVUI_IMPLEMENTATION
#include "cvui.h"
#define WINDOW_NAME "CVUI Test"
int main() {
cvui::init(WINDOW_NAME);
cv::Mat frame = cv::Mat(cv::Size(400, 200), CV_8UC3);
while(true) {
frame = cv::Scalar(49, 52, 49);
cvui::text(frame, x, y, "Hello world!");
// Show window content
cvui::imshow(WINDOW1_NAME, frame);
if (cv::waitKey(20) == 27) {
break;
}
}
return 0;
}
cvui::imshow()
替代 cv::imshow()
时,不仅更新窗口内容,还更新了内部结构,确保所有 UI
交互的工作。
如果想使用 cv::imshow()
,则需要在调用之前再调用 cvui::update()
。
#include
#define CVUI_IMPLEMENTATION
#include "cvui.h"
#define WINDOW_NAME "CVUI Test"
int main() {
cvui::init(WINDOW_NAME);
cv::Mat frame = cv::Mat(cv::Size(400, 200), CV_8UC3);
while(true) {
frame = cv::Scalar(49, 52, 49);
cvui::text(frame, x, y, "Hello world!");
// Update cvui internal stuff
cvui::update();
// Show window content
cv::imshow(WINDOW1_NAME, frame);
if (cv::waitKey(20) == 27) {
break;
}
}
return 0;
}
You can disable such compilation messages by defining CVUI_DISABLE_COMPILATION_NOTICES before including cvui.h. E.g.:
可以定义 CVUI_DISABLE_COMPILATION_NOTICES
屏蔽一些编译信息;
#include
#define CVUI_DISABLE_COMPILATION_NOTICES
#define CVUI_IMPLEMENTATION
#include "cvui.h"
下载最新代码,拷贝 cvui.py
到项目文件夹,然后 import
import cvui
import numpy as np
import cv2
import cvui
WINDOW_NAME = 'CVUI Test'
# Tell cvui to init and create a window
cvui.init(WINDOW_NAME)
while True:
# your app logic here
if cv2.waitKey(20) == 27:
break
所有的 cvui
组件渲染到 np.array
里,等同于 C++ cv::Mat
。
import numpy as np
import cv2
import cvui
WINDOW_NAME = 'CVUI Test'
cvui.init(WINDOW_NAME)
# Create a frame
frame = np.zeros((200, 400, 3), np.uint8)
while True:
# clear the frame
frame[:] = (49, 52, 49)
# render a message in the frame at position (10, 15)
cvui.text(frame, 10, 15, 'Hello world!')
if cv2.waitKey(20) == 27:
break
Some cvui components use an external variable that they need to modify to control their internal state, e.g. checkbox() uses an external boolean to store if it is checked or not.
一些组件需要使用外部变换,从而可以控制内部状态,例如 checkbox()
。
Tip:
counter, trackbar and checkbox
需要.
import numpy as np
import cv2
import cvui
WINDOW_NAME = 'CVUI Test'
cvui.init(WINDOW_NAME)
frame = np.zeros((200, 400, 3), np.uint8)
# use an array/list because this variable will be changed by cvui
checkboxState = [False]
while True:
frame[:] = (49, 52, 49)
# Render the checkbox. Notice that checkboxState is used AS IS,
# e.g. simply "checkboxState" instead of "checkboxState[0]".
# Only internally that cvui will use checkboxState[0].
cvui.checkbox(frame, 10, 15, 'My checkbox', checkboxState)
# Check the state of the checkbox. Here you need to remember to
# use the first position of the array/list because that's the
# one being used by all cvui components that perform changes
# to external variables.
if checkboxState[0] == True:
print('Checkbox is checked')
if cv2.waitKey(20) == 27:
break
import numpy as np
import cv2
import cvui
WINDOW_NAME = 'CVUI Test'
cvui.init(WINDOW_NAME)
frame = np.zeros((200, 400, 3), np.uint8)
while True:
frame[:] = (49, 52, 49)
cvui.text(frame, 10, 15, 'Hello world!')
# Update cvui internal stuff
cvui.update()
# Show window content
cv2.imshow(WINDOW_NAME, frame)
if cv2.waitKey(20) == 27:
break
见 用例
后续更新链接。