【OpenCV-Python】cvui: 简介

CVUI 简介

cvui 是一个非常简单的 UI 库,构建在 OpenCV 画图基本原型接口上。其他 UI 库,如imgui, 需要 OpenGL 才能工作。cvui 则不需要。

特性

  1. 轻量级,简单易用;
  2. 只需要头文件,除了 OpenCV以外,不需要其他依赖;
  3. 基于基础的 OpenCV 绘图函数,不需要 OpenGL 或者 QT;
  4. 友好的类C接口API;
  5. 组件渲染轻松,不用担心位置;
  6. 简单但功能强大的鼠标 API;
  7. UI 组件数量适中,一共11个;
  8. 在 C++ 或者 Python 中使用,纯实现无绑定;

安装

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 在 C++

#include

下载最新的代码,将 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 <opencv2/opencv.hpp>
#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 <opencv2/opencv.hpp>
#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::imshowcv::imshow 基础上进行了改进。

#include <opencv2/opencv.hpp>
#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 <opencv2/opencv.hpp>
#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 <opencv2/opencv.hpp>

#define CVUI_DISABLE_COMPILATION_NOTICES
#define CVUI_IMPLEMENTATION
#include "cvui.h"

cvui 在 Python

加载引用

下载最新代码,拷贝 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

实例

用例

后续更新链接。

参考

  1. cvui
  2. cvui github

猜你喜欢

转载自blog.csdn.net/zhoujinwang/article/details/129990648
今日推荐