学习图形用户界面

1、OpenCV 用户界面介绍

#include <iostream>
#include <string>
#include <sstream>
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"

using namespace std;
using namespace cv;
//CV_GUI_NORMAL标志使用原生界面和更基本的界面
const int CV_GUI_NORMAL = 0x10;

int main()
{
		//imread是读取图像的主函数,此函数打开图像并以矩阵格式存储它
		//imread(”图像路径字符串“,用于指定要加载的图像类型<默认为彩色图像;可选的>)
        Mat lena = imread("lena.jpg");
        Mat photo = imread("photo.jpg");

        if (!lena.data)
        {
                cout << "Lena image missing!" << endl;
                return -1;
        }
        if (!photo.data)
        {
                cout << "Lena image missing!" << endl;
                return -1;
        }
		//namedWindow函数创建窗口
		//namedWindow(”带有窗口名称的常量字符串“,需要的标志<可选的>)
        namedWindow("Lena", WINDOW_NORMAL);
        namedWindow("Photo", WINDOW_AUTOSIZE);
		//当创建多个窗口时,它们是叠加的,moveWindow函数将窗口移动到桌面的任何位置
		//Lena窗口向左移动了10个像素,向上移动了10个像素
        moveWindow("Lena", 10, 10);
        moveWindow("Photo", 700, 10);
		//显示图像
        imshow("Lena", lena);
        imshow("Photo", photo);
        //resizeWindow函数将Lena窗口的大小调整为512像素
        //resizeWindow("window name", width, height)
        resizeWindow("Lena", 512, 512);
		waitKey(0);
		//destroyWindow函数删除窗口,窗口名称是唯一需要的参数
        destroyWindow("Lena");
        destroyWindow("Photo");
		//创建10个窗口
        for (int i=0; i < 10; i++)
        {
                ostringstream ss;
                ss << "Photo" << i;
                namedWindow(ss.str());
                moveWindow(ss.str(), 20*i, 20*i);
                imshow(ss.str(), photo);
        }
        waitKey(0);
        //destroyAllWindows函数可以一次删除所创建的所有窗口
        //在任何情况下,OpenCV都会在应用程序中终止时自动销毁所有的窗口,因此在应用程序结束时不必调用此函数
        destroyAllWindows();
        return 0;
}
知识补充

在这里插入图片描述

结果

在这里插入图片描述在这里插入图片描述

2、将滑块和鼠标事件添加到界面

#include <iostream>
#include <string>
#include <sstream>
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"

using namespace std;
using namespace cv;

// 创建一个变量保存滑块位置
int blurAmount=15;
//为滑块和鼠标事件定义回调函数
static void onChange(int pos, void* userInput);
static void onMouse( int event, int x, int y, int, void* userInput );

int main( int argc, const char** argv )
{
        Mat lena = imread("lena.jpg");
        namedWindow("Lena");
        //createTrackbar函数用于生成滑块
        //为Lena窗口添加了tracebar,然后调用Lena跟踪条对图像进行模糊处理。跟踪条的值存储在将会作为指针传递的blurAmount整数中,并将跟踪条的最大值设置为30,把onChange设置为回调函数,将lena mat图像作为用户数据发送
        createTrackbar("Lena", "Lena", &blurAmount, 30, onChange, &lena);
		//可以向Lena窗口添加鼠标回调,并将onMouse设置为回调函数,从而将lena mat图像作为用户数据进行传递
        setMouseCallback("Lena", onMouse, &lena);
        //为了完成主函数,需要使用与滑块相同的参数来初始化图像,要执行初始化,只需调用onChange回调函数
        onChange(blurAmount, &lena);
        waitKey(0);
        destroyWindow("Lena");
        return 0;
}
//滑块回调函数使用滑块值作为模糊量,将基本的模糊滤镜应用于图像
static void onChange(int pos, void* userInput)
{
		//使用pos来检查滑块值是否为0
		//在这种情况下,我们不使用过滤器,因为它会生产执行错误,也不能用0像素模糊
        if(pos <= 0)
                return;
        //创建一个名为imgBlur的空矩阵来存储模糊结果
        Mat imgBlur;
        // Get the pointer input image
        Mat* img= (Mat*)userInput;
        // Apply a blur filter
        blur(*img, imgBlur, Size(pos, pos));
        // Show the result
        imshow("Lena", imgBlur);
}

//Mouse callback
static void onMouse( int event, int x, int y, int, void* userInput )
{
        if( event != EVENT_LBUTTONDOWN )
                return;

        // Get the pointer input image
        Mat* img= (Mat*)userInput;

        // Draw circle
        circle(*img, Point(x, y), 10, Scalar(0,255,0), 3);
        // Call on change to get blurred image
        onChange(blurAmount, img);

}
知识补充

在这里插入图片描述在这里插入图片描述在这里插入图片描述

结果

在这里插入图片描述

3、Qt图形用户界面

简单操作

#include <iostream>
#include <string>
#include <sstream>
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"

using namespace std;
using namespace cv;

const int CV_GUI_NORMAL= 0x10;

int main( int argc, const char** argv )
{
        //imread是读取图像的主函数,此函数打开图像并以矩阵格式存储它
		//imread(”图像路径字符串“,用于指定要加载的图像类型<默认为彩色图像;可选的>)
        Mat lena= imread("lena.jpg");
        //namedWindow函数创建窗口
		//namedWindow(”带有窗口名称的常量字符串“,需要的标志<可选的>)
        namedWindow("Lena");
        //显示图像
        imshow("Lena", lena);
        //displayOverlay函数在图像区域顶部显示叠加消息
        //displayOverlay(”窗口名称“, “要显示的文本”, 显示叠加文本的时间<以毫秒为单位,如果设置为0,则文本永远不会消失>)
        displayOverlay("Lena", "Overlay 5secs", 0);
        //displayStatusBar函数在状态栏显示叠加消息
        //displayStatusBar(”窗口名称“, “要显示的文本”, 显示叠加文本的时间<以毫秒为单位,如果设置为0,则文本永远不会消失>)
        displayStatusBar("Lena", "Status bar 5secs", 5000);
        // 保存窗口参数
        saveWindowParameters("Lena");
        // 下载窗口参数
        loadWindowParameters("Lena");
       //waitKey函数参数为要等待按键的毫秒数,如果参数为0,则这个函数会一直等待下去,直到用户按下某个键
        waitKey(0);
        ///destroyWindow函数删除窗口,窗口名称是唯一需要的参数
        destroyWindow("Lena");
        return 0;
}
结果

在这里插入图片描述

将按钮添加到用户界面

#include <iostream>
#include <string>
#include <sstream>
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"

using namespace std;
using namespace cv;

Mat img;
//应用三种类型的滤镜:将颜色转化为灰色、模糊和Sobel过滤器
//都是可选的,用户可以使用要创建的按钮选择每一种滤镜
//为了获得每个过滤器的状态,创建了三个全局的布尔变量
bool applyGray=false;
bool applyBlur=false;
bool applySobel=false;
//applyFilters函数检查每个过滤器的状态变量
void applyFilters(){
        Mat result;
        img.copyTo(result);
        if(applyGray)
        {
        	cvtColor(result, result, COLOR_BGR2GRAY);
        }
        if(applyBlur)
        {
         	blur(result, result, Size(5,5));
        }
        if(applySobel)
        {
            //sobel滤波器是使用sobel算子获得的图像导数,通常用于检测图像边缘
        	Sobel(result, result, CV_8U, 1, 1);
        }
        imshow("Lena", result);
}
//每个回调函数都会更改其状态变量以调用另一个名为applyFilters的函数,以便将激活的过滤器添加到输入图像
void grayCallback(int state, void* userData)
{
        applyGray = true;
        applyFilters();
}
void bgrCallback(int state, void* userData)
{
        applyGray = false;
        applyFilters();
}

void blurCallback(int state, void* userData)
{
        applyBlur = (bool)state;
        applyFilters();
}

void sobelCallback(int state, void* userData)
{
        applySobel = !applySobel;
        applyFilters();
}
int main( int argc, const char** argv )
{
        img = imread("lena.jpg");
        namedWindow("Lena");
        //createButton函数创建按钮
        //OpenCV中定义了三种按钮类型:QT_CHECKBOX,QT_RADIOBOX,QT_PUSH_BUTTON
        //每个按钮有五个参数,按顺序如下所示:
        //1、按钮名称;2、回调函数;3、传递给回调函数的用户变量数据的指针;4、按钮类型;5、用于复选框和单选框按钮类型的默认初始状态
        createButton("Blur", blurCallback, NULL, QT_CHECKBOX, 0);                      	createButton("Gay",grayCallback,NULL,QT_RADIOBOX, 0); 
        //图片的默认状态为彩色 
        createButton("RGB",bgrCallback,NULL,QT_RADIOBOX, 1);     createButton("Sobel",sobelCallback,NULL,QT_PUSH_BUTTON, 0);
        waitKey(0);
        destroyWindow("Lena");
        return 0;
}
知识补充

在这里插入图片描述
在这里插入图片描述

结果

在这里插入图片描述

4、OpenGL 支持

OpenCV 包括对OpenGL的支持。OpenGL 是一个作为标准而集成在几乎所有图形卡中的图形库。OpenGL 能够把2D图像绘制成复杂的3D场景。要在OpenGL中允许支持窗口,必须在调用namedWindow创建窗口时设置WINDOW_OPENGL 标志。

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

// OpenGL includes
#ifdef __APPLE__
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif

// OpenCV includes
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
//创建所需的全局变量,用来存储捕获的视频帧并保存帧,然后控制动画角度平面和OpenGL纹理
Mat frame;
GLfloat angle= 0.0;
GLuint texture;
VideoCapture camera;
//loadTexture函数将Mat帧转换为OpenGL纹理图像,可以在每个回调绘图中加载和使用
int loadTexture() 
{
	//在将图像作为纹理加载之前,必须确保在帧矩阵中有数据,即检查数据变量对象是否为空
    if (frame.data==NULL) return -1;
	//如果每帧矩阵中矩阵中有数据,则可以创建OpenGL纹理绑定,并将OpenGL纹理参数设置为线性插值
    glBindTexture( GL_TEXTURE_2D, texture );    
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);  
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	//定义像素存储在矩阵中
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    //glTexImage2D函数生成像素
    //OpenGL默认使用RGB格式,而OpenCV默认使用BGR格式,必须在函数中设置正确的格式
    glTexImage2D2(GL_TEXTURE_2D, 0, GL_RGB, frame.cols, frame.rows,0, GL_BGR, GL_UNSIGNED_BYTE, frame.data);
    return 0;

}
void on_opengl(void* param)
{
	//使用常见的OpenGL函数,然后加载标识OpenGL矩阵以重置之前所有的更改
    glLoadIdentity();
    // 加载帧纹理
    glBindTexture( GL_TEXTURE_2D, texture );
    // 在1,1,1轴上旋转平面
    glRotatef( angle, 1.0f, 1.0f, 1.0f );
    // glBegin绘制四边形平面
    glBegin (GL_QUADS);
    //绘制一个以(0,0)为中心的平面,其大小为2单位
    //glTexCoord2d和glVertex2d函数定义要使用的纹理坐标和顶点位置
    glTexCoord2d(0.0,0.0); glVertex2d(-1.0,-1.0);
    glTexCoord2d(1.0,0.0); glVertex2d(+1.0,-1.0);
    glTexCoord2d(1.0,1.0); glVertex2d(+1.0,+1.0);
    glTexCoord2d(0.0,1.0); glVertex2d(-1.0,+1.0);
    glEnd();

}
int main( int argc, const char** argv )
{
    // 打开网络摄像头(WebCam),检索拍摄的帧
    camera.open(0);
    if(!camera.isOpened())
    {
        camera.open("Recording3.webm");
        if(!camera.isOpened())
            return -1;
    }
    //如果摄相机正确打开,使用WINDOW_OPENGL标志创建支持OpenGL的窗口
    namedWindow("OpenGL Camera", WINDOW_OPENGL);

    // 想在平面中绘制来自摄像头的图像,需要启用OpenGL纹理
    glEnable( GL_TEXTURE_2D );
    glGenTextures(1, &texture);
	//setOpenGlDrawCallback函数设置绘制OpenGL回调
	//setOpenGlDrawCallback("窗口名称", 回调函数)
    setOpenGlDrawCallback("OpenGL Camera", on_opengl);
	//创建一个循环来加载纹理,并更新调用OpenGL绘图回调的窗口内容,最后更新角度的位置
    while(waitKey(30)!='q')
    {
        camera >> frame;
        // Create first texture
        loadTexture();
        updateWindow("OpenGL Camera");
        angle =angle+4;
    }
        destroyWindow("OpenGL Camera");
        return 0;
}
结果

在这里插入图片描述

问题
/usr/bin/ld: /tmp/ccx2qdzO.o: undefined reference to symbol 'glEnable'
/usr/bin/ld: /lib/x86_64-linux-gnu/libGL.so.1: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
解决方法
g++ sample5.cpp -lGL -lGLU -lGLEW -lglut -o main `pkg-config opencv4 --cflags --libs`

5、VTK 例子

#include <opencv2/viz.hpp>
#include <opencv2/calib3d.hpp>
#include <iostream>

using namespace cv;
using namespace std;

/*
 * @function main
 */
int main()
{
    /// Create a window
    viz::Viz3d myWindow("Coordinate Frame");

    /// Add coordinate axes
    myWindow.showWidget("Coordinate Widget", viz::WCoordinateSystem());

    /// Add line to represent (1,1,1) axis
    viz::WLine axis(Point3f(-1.0f,-1.0f,-1.0f), Point3f(1.0f,1.0f,1.0f));
    axis.setRenderingProperty(viz::LINE_WIDTH, 4.0);
    myWindow.showWidget("Line Widget", axis);

    /// Construct a cube widget
    viz::WCube cube_widget(Point3f(0.5,0.5,0.0), Point3f(0.0,0.0,-0.5), true, viz::Color::blue());
    cube_widget.setRenderingProperty(viz::LINE_WIDTH, 4.0);

    /// Display widget (update if already displayed)
    myWindow.showWidget("Cube Widget", cube_widget);

    /// Rodrigues vector
    Mat rot_vec = Mat::zeros(1,3,CV_32F);
    float translation_phase = 0.0, translation = 0.0;
	while(!myWindow.wasStopped())
    {
        /* Rotation using rodrigues */
        /// Rotate around (1,1,1)
        rot_vec.at<float>(0,0) += CV_PI * 0.01f;
        rot_vec.at<float>(0,1) += CV_PI * 0.01f;
        rot_vec.at<float>(0,2) += CV_PI * 0.01f;

        /// Shift on (1,1,1)
        translation_phase += CV_PI * 0.01f;
        translation = sin(translation_phase);

        Mat rot_mat;
        Rodrigues(rot_vec, rot_mat);

        /// Construct pose
        Affine3f pose(rot_mat, Vec3f(translation, translation, translation));

        myWindow.setWidgetPose("Cube Widget", pose);

        myWindow.spinOnce(1, true);
    }

    return 0;
}
结果

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值