Qt 和 OpenCV 的高效集成

2024-01-02

我正在开发一个交互式应用程序,它需要一次读取和操作几个非常大的图像(一次 25 个图像,总大小大约 350 Mb)。 OpenCV 速度相当快,处理算法也相对容易。但事实证明,用 Qt 绘制它们是一个问题。这是我尝试过的两种不太理想的解决方案。

解决方案1(太慢)

每次需要绘制不同的 OpenCV 图像时,将其转换为QImage并画出它。不幸的是,转换需要一段时间 我们无法以交互速度在图像之间切换。

解决方案2(太占用内存)

维护两堆图像,一层用于 OpenCV,另一堆用于 Qt。使用 在合适的时间合适的一个。

我可以直接访问 OpenCV 像素数据。我知道图像的宽度和高度,并且我知道像素是 3 字节的 RGB 值。看起来应该可以快速绘制 OpenCV 图像,而无需将其复制到QImage(据我所知)仅包含数据副本的容器。

我需要从哪里寻找才能从 Qt 中获得这种功能?


我不知道三个月后这对你是否有用。但我有同样类型的应用程序,我必须使用 OpenCV 操作图像流并将其显示在 QT 界面上。经过一番谷歌搜索后,我发现了一个非常巧妙的解决方案。使用opengl的glDrawPixels直接在Qt界面上绘制原始图像数据。最好的部分是,您不必编写任何额外的转换代码。只是用于设置视口和坐标的 opengl 基本代码。查看代码,其中有一个函数,该函数接受 IplImage* 指针并使用该数据来绘制图像。您可能需要稍微调整参数(尤其是宽度和高度变量)才能显示特定尺寸的图像。 是的,我不知道你正在使用什么构建系统。尽管我使用的是 Qt 的 opengl 库,但我使用了 cmake 并且必须为 opengl 设置依赖项。

我已经实现了一个 QIplImage 类,它派生自 QGLWidget 并重写其 PaintGL 方法以将像素数据绘制到帧上。

//File qiplimage.h
class QIplImage : public QGLWidget
{
  Q_OBJECT

 public:
    QIplImage(QWidget *parent = 0,char *name=0);
   ~QIplImage();
   void paintGL();
   void initializeGL();
   void resizeGL(int,int);
   bool drawing;

 public slots:
   void setImage(IplImage);

 private:
  Ui::QIplImage ui;
  IplImage* original;
  GLenum format;
  GLuint texture;
  QColor bgColor;
  char* name;
  bool hidden;
  int startX,startY,endX,endY;
  QList<QPointF*> slopes;
  QWidget* parent;
  int mouseX,mouseY;

};
//End of file qiplimage.h

//file qiplimage.cpp
#include "qiplimage.h"
#include <Globals.h>

QIplImage::QIplImage(QWidget *parent) :
    QGLWidget(parent)
{

}
QIplImage::QIplImage(QWidget *parent,char* name): QGLWidget(parent)
{
     ui.setupUi(this);
    //This is required if you need to transmit IplImage over
    // signals and slots.(That's what I am doing in my application
    qRegisterMetaType<IplImage>("IplImage");
    resize(384,288);
    this->name=name;
    this->parent=parent;
    hidden=false;
    bgColor= QColor::fromRgb(0xe0,0xdf,0xe0);

    original=cvCreateImage(cvSize(this->width(),this->height()),IPL_DEPTH_8U,3);
    cvZero(original);
    switch(original->nChannels) {
        case 1:
            format = GL_LUMINANCE;
            break;
        case 2:
            format = GL_LUMINANCE_ALPHA;
            break;
        case 3:
            format = GL_BGR;
            break;
        default:
            return;
}
    drawing=false;
    setMouseTracking(true);
    mouseX=0;mouseY=0;
    initializeGL();

}
void QIplImage::initializeGL()
{
   qglClearColor(bgColor);  
   //glClearColor(0.5f, 0.5f, 0.5f, 1.0f);              
   glDisable(GL_DEPTH_TEST);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
       glOrtho(0,this->width(),this->height(),0.0f,0.0f,1.0f);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();

   glEnable(GL_TEXTURE_2D);
   glGenTextures(3,&texture);
   glBindTexture(GL_TEXTURE_2D,texture);
   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
   glBindTexture(GL_TEXTURE_2D,texture);                glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,this->width(),this->height(),0,GL_BGR,GL_UNSIGNED_BYTE,NULL);
   glDisable(GL_TEXTURE_2D);


}
void QIplImage::setImage(IplImage image){
original=&image;
//cvShowImage(name,original);

updateGL();
}

void QIplImage::paintGL (){
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
if(!hidden){
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
            glOrtho(0.0f,this->width(),this->height(),0.0f,0.0f,1.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glEnable(GL_TEXTURE_2D);
            glBindTexture(GL_TEXTURE_2D,texture);
            glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,original->width,original->height,0,GL_BGR_EXT,GL_UNSIGNED_BYTE,original->imageData);
    glBegin(GL_QUADS);
            glTexCoord2i(0,1); glVertex2i(0,this->height());
    glTexCoord2i(0,0); glVertex2i(0,0);
            glTexCoord2i(1,0); glVertex2i(this->width(),0);
            glTexCoord2i(1,1); glVertex2i(this->width(),this->height());
    glEnd();
    glFlush();
    }

}


void QIplImage::resizeGL(int width,int height){

    glViewport(0,0,this->width(),this->height());
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();       
    glOrtho(0.0f,this->width(),this->height(),0.0f,0.0f,1.0f);
    glMatrixMode(GL_MODELVIEW);         
    glLoadIdentity();
 }

希望有帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt 和 OpenCV 的高效集成 的相关文章

  • ASP.NET MVC:这个业务逻辑应该放在哪里?

    我正在开发我的第一个真正的 MVC 应用程序 并尝试遵循一般的 OOP 最佳实践 我正在将控制器中的一些简单业务逻辑重构到我的域模型中 我最近一直在阅读一些内容 很明显我应该将逻辑放在域模型实体类中的某个位置 以避免出现 贫血域模型 反模式
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z
  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • 嵌套接口:将 IDictionary> 转换为 IDictionary>?

    我认为投射一个相当简单IDictionary
  • Clang 3.1 + libc++ 编译错误

    我已经构建并安装了 在前缀下 alt LLVM Clang trunk 2012 年 4 月 23 日 在 Ubuntu 12 04 上成功使用 GCC 4 6 然后使用此 Clang 构建的 libc 当我想使用它时我必须同时提供 lc
  • 堆栈溢出:堆栈空间中重复的临时分配?

    struct MemBlock char mem 1024 MemBlock operator const MemBlock b const return MemBlock global void foo int step 0 if ste
  • 将图像分割成多个网格

    我使用下面的代码将图像分割成网格的 20 个相等的部分 import cv2 im cv2 imread apple jpg im cv2 resize im 1000 500 imgwidth im shape 0 imgheight i
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • Windows 窗体:如果文本太长,请添加新行到标签

    我正在使用 C 有时 从网络服务返回的文本 我在标签中显示 太长 并且会在表单边缘被截断 如果标签不适合表单 是否有一种简单的方法可以在标签中添加换行符 Thanks 如果您将标签设置为autosize 它会随着您输入的任何文本自动增长 为
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 如何将带有 IP 地址的连接字符串放入 web.config 文件中?

    我们当前在 web config 文件中使用以下连接字符串 add name DBConnectionString connectionString Data Source ourServer Initial Catalog ourDB P
  • 在 Qt 中自动调整标签文本大小 - 奇怪的行为

    在 Qt 中 我有一个复合小部件 它由排列在 QBoxLayouts 内的多个 QLabels 组成 当小部件调整大小时 我希望标签文本缩放以填充标签区域 并且我已经在 resizeEvent 中实现了文本大小的调整 这可行 但似乎发生了某
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • C++ 中类级 new 删除运算符的线程安全

    我在我的一门课程中重新实现了新 删除运算符 现在我正在使我的代码成为多线程 并想了解这些运算符是否也需要线程安全 我在某处读到 Visual Studio 中默认的 new delete 运算符是线程安全的 但这对于我的类的自定义 new

随机推荐