1.主窗体管理
(1)namedWindow(win, flag=1)=void●destroyWindow(win)=void●destroyAllWindows()=void
1)flag=WINDOW_NORMAL:尺寸可任意缩放且可全屏的窗体
2)flag=WINDOW_AUTOSIZE:尺寸固定为图像大小且不可全屏的窗体
3)flag=WINDOW_KEEPRATIO:尺寸可任意缩放且可全屏但长宽比例固定的窗体
4)flag=WINDOW_OPENGL:支持OpenGL的窗体
(2)moveWindow(win, x, y)=void●resizeWindow(win, w, h)=void●resizeWindow(win, size)=void
(3)getWindowImageRect(win)=rect●setWindowTitle(win, title)=void
1)x和y是窗体左上角在屏幕坐标系中的坐标,w和h是窗体的宽高
2)rect是窗体工作区(即图像)左上角在屏幕坐标系中的坐标和宽高
(4)setWindowProperty(win, key, val)=void●getWindowProperty(win, key)=val
1)key=WND_PROP_FULLSCREEN:取WINDOW_NORMAL或WINDOW_FULLSCREEN
2)key=WND_PROP_AUTOSIZE:取WINDOW_NORMAL或WINDOW_AUTOSIZE
3)key=WND_PROP_ASPECT_RATION:WINDOW_FREERATIO或WINDOW_KEEPRATIO
4)key=WND_PROP_OPENGL:未知
5)key=WND_PROP_VISIBLE:未知
2.事件循环
(1)imshow(win, ima)=void●imshow(win, texture2D)=void:显示图像或二维纹理
(2)waitKey(delay=0)=int●waitKeyEx(delay=0)=int:后者返回完整键码(值与系统相关)
(3)loadWindowParameters()=void:加载备份的主窗体属性及其所有子窗体属性
(4)saveWindowParameters()=void:备份主窗体属性及其所有子窗体属性到内存
(5)startWindowThread()=int:功能未知
(6)startLoop(Fun, argc, argv)=int●stopLop()=void:对QtConcurrent::run的封装
3.工作区管理
(1)displayStatusBar(win, str, delay=0)=void:在状态栏左侧显示指定毫秒(0无限)
(2)displayOverlay(win, str, delay=0)=void:在工作区顶部显示指定毫秒(0无限)当鼠标靠近
(3)fontQt(fontName, pointSize=-1, color=Scalar::all(0), weight=~, style=~, spacing=0)=font
1)weight=QT_FONT_LIGHT、~NORMAL、~DEMIBOLD、~BOLD、~BLACK
2)style=QT_STYLE_NORMAL、~ITALIC、~OBLIQUE
(4)selectROI(ima, showCrosschair=true, formCenter=false)=rect
(5)selectROI(win, ima, showCrosschair=true, fromCenter=false)=rect
(6)selectROIs(win, ima, rects, ~)=void●addText(ima, str, pt, font)=void
1)绘制ima到窗体并等待鼠标操作,鼠标右键按下与释放可绘制矩形
2)showCrosschair为真绘制田字矩形,fromCenter为真绘制起点是矩形中心
3)selectROI按enter/space/esc返回绘制的矩形,按c退出并返回空矩形
4)selectROIs按enter/space进行下一次绘制,按esc退出绘制
4.事件交互
(1)setMouseCallback(win, cbMouse, usrdata=0)=void●getMouseWheelDelta(wheelFlag)=int
1)回调函数形式:void cbMouse(eventType, x, y, eventFlag, usrdata){}
2)eventType取值:event_mousemove/event_mousewheel/event_mousehwheel
3)eventType取值:event_lbuttondown/event_lbuttonup/event_lbuttondblclk
4)eventType取值:event_rbuttondown/event_rbuttonup/event_rbuttondblclk
5)eventType取值:event_mbuttondown/event_mbuttonup/event_mbuttondblclk
6)eventFlag取值:event_flag_lbutton/event_flag_rbutton/event_flag_mbutton
7)eventFlag取值:event_flag_ctrlkey/event_flag_shiftkey/event_flag_altkey
8)wheelFlag取值:仅响应event_mousewheel和event_mousehwheel事件
(2)createTrackbar(bar, win, bindVar, maxVal, cbTracker=0, usrdata=0)=int
(3)setTrackbarMin(bar, win,val)=void●setTrackbarMax(bar, win, val)=void
(4)setTrackbarPos(bar, win, val)=void●getTrackbarPos(bar, win)=int
1)回调函数形式:void cbTracker(val, usrdata) {}
2)最简使用方式:绑定变量是随跟踪条实时更新的,若无复杂操作则不用提供回调函数
3)按需使用方式:在需要时再由getTrackbarPos获取跟踪条的当前值
(5)createButton(bar, cbButton, usrdata=0, btnType=QT_PUSH_BUTTON, state=false)
1)回调函数形式:void cbButton(state, usrdata)
2)btnType取值:qt_push_button/qt_checkbox/qt_radiobox + qt_new_buttonbar
3)单选按分组:同一行的单选按钮归为同一组,即同一行的单选按键互斥
(6)回调函数的lambda问题:用lambda似乎捕获参数只能为空,但可直接访问外部静态变量
5.立体显示
(1)setOpenGlContext(win)=void●updateWindow(win)=void
(2)setOpenGlDrawCallback(win, cbGlDraw, usrdata)=void
1)回调函数形式:void cbGlDraw(usrdata)=void
2)使用注意事项:首先要设置窗体支持OpenGL,否则setOpenGLContext会异常。
3)使用基本流程:参见对应样例代码。这几个函数难以完成立体交互,需用viz模块。
6.使用样例
以下提供OpenCV GUI模块的使用样例,封装在类AboutOpenCVGUI,实现功能如下:
(1)模拟使用selectROI和selectROIs,在图像上选择感知兴趣的区域并按相应的键退出后,终端将显示选择的区域。
(2)模拟使用setWindowTitle、displayStatusBar及displayOverlay,可在窗口相应处观察到相应的文字且在动态变化,按q退出。
(3)模拟使用setMouseCallback、createTracker、createButton,可单击右上角的扫帚打开子窗口查看创建的控制。
以下是详细代码,依赖于C++14、OpenCV4.x和Spdlog。
1 #include <opencv2/opencv.hpp> 2 #include <spdlog/spdlog.h> 3 using namespace std; 4 using namespace cv; 5 6 #ifndef StrPairKey 7 #define StrPairKey(key) make_pair(#key, key) 8 #define StrPairVal(val) make_pair(val, #val) 9 #endif 10 11 class AboutOpenCVGUI 12 { 13 public: 14 struct MouseInfo 15 { 16 int rowsUser;//GivenByUser 17 int colsUser;//GivenByUser 18 MouseInfo(int rows = INT_MAX, int cols = INT_MAX) : rowsUser(rows), colsUser(cols) {} 19 int xMouse;//UpdatedByCbMouse 20 int yMouse;//UpdatedByCbMouse 21 int eventMouse;//UpdatedByCbMouse 22 int flagMouse;//UpdatedByCbMouse 23 const map<int, string> mouseEvents = 24 { 25 StrPairVal(EVENT_MOUSEMOVE), 26 StrPairVal(EVENT_LBUTTONDOWN), 27 StrPairVal(EVENT_RBUTTONDOWN), 28 StrPairVal(EVENT_MBUTTONDOWN), 29 StrPairVal(EVENT_LBUTTONUP), 30 StrPairVal(EVENT_RBUTTONUP), 31 StrPairVal(EVENT_MBUTTONUP), 32 StrPairVal(EVENT_LBUTTONDBLCLK), 33 StrPairVal(EVENT_RBUTTONDBLCLK), 34 StrPairVal(EVENT_MBUTTONDBLCLK), 35 StrPairVal(EVENT_MOUSEWHEEL), 36 StrPairVal(EVENT_MOUSEHWHEEL) 37 }; 38 const map<int, string> mouseFlags = 39 { 40 StrPairVal(EVENT_FLAG_LBUTTON), 41 StrPairVal(EVENT_FLAG_RBUTTON), 42 StrPairVal(EVENT_FLAG_MBUTTON), 43 StrPairVal(EVENT_FLAG_CTRLKEY), 44 StrPairVal(EVENT_FLAG_SHIFTKEY), 45 StrPairVal(EVENT_FLAG_ALTKEY) 46 }; 47 }; 48 49 static void callbackMouse(int event, int x, int y, int flag, void* pMouseInfo) 50 { //common case. could be replaced by lambda based on actual requirement 51 MouseInfo* mouseInfo = (MouseInfo*)pMouseInfo; 52 53 if (x >= mouseInfo->colsUser * 3) x -= mouseInfo->colsUser * 3; 54 else if (x >= mouseInfo->colsUser * 2) x -= mouseInfo->colsUser * 2; 55 else if (x >= mouseInfo->colsUser) x -= mouseInfo->colsUser; 56 57 if (y >= mouseInfo->rowsUser * 3) y -= mouseInfo->rowsUser * 3; 58 else if (y >= mouseInfo->rowsUser * 2) y -= mouseInfo->rowsUser * 2; 59 else if (y >= mouseInfo->rowsUser) y -= mouseInfo->rowsUser; 60 61 mouseInfo->xMouse = x; 62 mouseInfo->yMouse = y; 63 mouseInfo->eventMouse = event; 64 mouseInfo->flagMouse = flag; 65 } 66 67 public: 68 static void testBasicGUI(int argc = 0, char** argv = 0) 69 { 70 Mat_<Vec3b> ima(720, 1280, Vec3b(128, 128, 128)); 71 72 //1.AboutSelectROI 73 string tips1 = "cv::selectROI: press enter/space/esc to return selected rect, press c to return invalid rect."; 74 string tips2 = "cv::selectROIs: press enter/space to select next rect, press esc to return all selected rects."; 75 string tips3 = "current mode: cv::selectROIs"; 76 auto exitFunction = [](Mat ima, string str)->void { putText(ima, "Current Test: " + str, Point(ima.cols >> 2, ima.rows - 100), FONT_HERSHEY_PLAIN, 3, Scalar(255, 0, 0), 3, LINE_8, false); }; 77 putText(ima, tips1, Point(10, 100), FONT_HERSHEY_PLAIN, 1.5, Scalar(255, 255, 255), 2, LINE_8, false); 78 putText(ima, tips2, Point(10, 200), FONT_HERSHEY_PLAIN, 1.5, Scalar(255, 255, 255), 2, LINE_8, false); 79 putText(ima, tips3, Point(10, 300), FONT_HERSHEY_PLAIN, 1.5, Scalar(255, 255, 255), 2, LINE_8, false); 80 exitFunction(ima, "selectROI"); Rect rect = cv::selectROI(__FUNCTION__, ima, true, false); 81 spdlog::info(fmt::format("selectROI results: {} {} {} {}", rect.x, rect.y, rect.width, rect.height)); 82 exitFunction(ima, "selectROIs"); vector<Rect> rects; cv::selectROIs(__FUNCTION__, ima, rects, true, false); 83 for(size_t k = 0; k < rects.size(); ++k) spdlog::info(fmt::format("selectROIs results{}: {} {} {} {}", k, rects[k].x, rects[k].y, rects[k].width, rects[k].height)); 84 85 //2.AboutTipFunctions 86 cv::setWindowProperty(__FUNCTION__, 1, 0);//__FUNCTION__ window has created but fixed size. 87 for (int k = 0; ; ++k) 88 { 89 ima = Vec3b(128, 128, 128); 90 91 tips1 = std::to_string(k) + string(" cv::setWindowTitle: show tips in the title bar until next tip is reached"); 92 tips2 = std::to_string(k) + string(" cv::displayStatusBar: show tips in the status bar until given time or next tip is reached"); 93 tips3 = std::to_string(k) + string(" cv::displayOverlay: show tips at the top of the workarea until given time or next tip is reached when mouse hovers"); 94 putText(ima, tips1, Point(10, 100), FONT_HERSHEY_PLAIN, 1.5, Scalar(255, 255, 255), 2, LINE_8, false); 95 putText(ima, tips2, Point(10, 200), FONT_HERSHEY_PLAIN, 1.5, Scalar(255, 255, 255), 2, LINE_8, false); 96 putText(ima, tips3, Point(10, 300), FONT_HERSHEY_PLAIN, 1.5, Scalar(255, 255, 255), 2, LINE_8, false); 97 exitFunction(ima, "TipsFunction"); 98 99 cv::imshow(__FUNCTION__, ima); 100 cv::setWindowTitle(__FUNCTION__, tips1); 101 cv::displayStatusBar(__FUNCTION__, tips2, 2000); 102 cv::displayOverlay(__FUNCTION__, tips3, 2000); 103 if (cv::waitKey(4000) == 'q') break; 104 } 105 106 //3.AboutControls 107 ima = Vec3b(128, 128, 128); 108 MouseInfo mouseInfo(ima.rows, ima.cols); cv::setMouseCallback(__FUNCTION__, callbackMouse, &mouseInfo); 109 int value = 128; cv::createTrackbar("tracker", __FUNCTION__, &value, 255, 0, 0); 110 auto cbButton = [](int state, void* usrdata)->void 111 { 112 string* str = (string*)usrdata; 113 if (str->find_first_of(':') == string::npos) *str += string(": ") + std::to_string(state); 114 else *str = str->substr(0, str->find_first_of(':')) + string(": ") + std::to_string(state); 115 }; 116 string radioNames[8]; for (int k = 0; k < 8; ++k) cv::createButton(radioNames[k] = string("RadioBox") + std::to_string(k + 1), cbButton, radioNames + k, QT_RADIOBOX | (k == 0 || k == 4 ? QT_NEW_BUTTONBAR : 0)); 117 string checkNames[8]; for (int k = 0; k < 8; ++k) cv::createButton(checkNames[k] = string("CheckBox") + std::to_string(k + 1), cbButton, checkNames + k, QT_CHECKBOX | (k == 0 || k == 4 ? QT_NEW_BUTTONBAR : 0)); 118 string pushNames[8]; for (int k = 0; k < 8; ++k) cv::createButton(pushNames[k] = string("PushButton") + std::to_string(k + 1), cbButton, pushNames + k, QT_PUSH_BUTTON | (k == 0 || k == 4 ? QT_NEW_BUTTONBAR : 0)); 119 string winName = __FUNCTION__; 120 cv::createButton("PushButtonAccept", [](int state, void* usrdata)->void {cv::setWindowTitle(*((string*)usrdata), "PushButtonAccept"); }, &winName, QT_PUSH_BUTTON | QT_NEW_BUTTONBAR); 121 cv::createButton("PushButtonCancel", [](int state, void* usrdata)->void {cv::setWindowTitle(*((string*)usrdata), "PushButtonCancel"); }, &winName, QT_PUSH_BUTTON | QT_NEW_BUTTONBAR); 122 while (1) 123 { 124 ima = Vec3b(value, value, value); 125 for (int k = 0; k < 8; ++k) putText(ima, radioNames[k], Point(100 + k % 4 * 250, 100 + k / 4 * 100), FONT_HERSHEY_PLAIN, 1.5, Scalar(255, 255, 255), 2, LINE_8, false); 126 for (int k = 0; k < 8; ++k) putText(ima, checkNames[k], Point(100 + k % 4 * 250, 300 + k / 4 * 100), FONT_HERSHEY_PLAIN, 1.5, Scalar(255, 255, 255), 2, LINE_8, false); 127 for (int k = 0; k < 8; ++k) putText(ima, pushNames[k], Point(100 + k % 4 * 250, 500 + k / 4 * 100), FONT_HERSHEY_PLAIN, 1.5, Scalar(255, 255, 255), 2, LINE_8, false); 128 129 cv::displayOverlay(__FUNCTION__, string("x: ") + std::to_string(mouseInfo.xMouse) + " y: " + std::to_string(mouseInfo.yMouse), 0); 130 exitFunction(ima, "Controls"); 131 cv::imshow(__FUNCTION__, ima); 132 if (cv::waitKey(40) == 'q') break; 133 } 134 } 135 136 }; 137 138 int main(int argc, char** argv) { AboutOpenCVGUI::testBasicGUI(argc, argv); return 0; }