opencv实时采集图像作为opengl的纹理贴图

前言

        本文尝试将opencv通过VideoCapture采集的实时图像数据作为opengl的纹理贴图。特地对Texture类进行了扩充。

        使用cv::Mat作为纹理数据输入,来替代使用stbi_load从文件进行加载图像。本来想使用stbi_load_from_memory,但貌似不需要,直接使用Mat.data即可得到uchar*的数据作为glTexImage2D函数的最后一个参数。

创建纹理对象

code

Texture::Texture(cv::Mat &img, unsigned int unit)
{
  mUint = unit;

  // 生成纹理并且激活单元绑定
  glGenTextures(1, &mTexture);
  glActiveTexture(GL_TEXTURE0 + mUint);
  glBindTexture(GL_TEXTURE_2D, mTexture);

  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  // 需要的像素小于图片像素
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  // 需要的像素大于图片像素
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

  if (img.data)
  {
    mWidth = img.cols;
    mHeight = img.rows;

    // 传输纹理数据
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, mWidth, mHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, img.data);
    glGenerateMipmap(GL_TEXTURE_2D);
  }
  else
  {
    std::cout << "Failed to load texture" << std::endl;
  }
}

        实验过程中发现,图像是反的,我们在使用stb_img的时候,会调用进行翻转。

stbi_set_flip_vertically_on_load(true);

        同样,在使用opencv得到图像时,对其也进行下反转即可,我们使用了以下

// 图像反转
cv::Mat dst;
cv::flip(img, dst, -1);

        其余就是绘制box的基本流程,即创建vao、vbo等,这些属于基本操作,不在本文的讨论范畴,直接看效果。

        到此为止,图像颜色还存在点问题,我穿的黄色衣服,怎么变成蓝色了?

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, mWidth, mHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, img.data);

        具体分析后找到问题原因:opencv视频采集到的颜色默认为BGR,所以我们在函数glTexImage2D中第七个参数是存在问题的,其表示原始数据的格式。 需要将其改为GL_BGR,修改后验证图像为真实颜色了。

部分代码

loop

int main()
{

  if (!app->init(800, 600))
  {
    return -1;
  }

  if (!capture.isOpened())
  {
      printf("[%s][%d]could not load video data...\n", __FUNCTION__, __LINE__);
      return -1;
  }

  // 设置窗口回调
  app->setCallbacks(OnResze, OnKey, OnMouse, OnCursor, OnScroll);

  /* 设置opengl视口以及清理颜色 */
  GL_CALL(glViewport(0, 0, 800, 600));
  GL_CALL(glClearColor(0.2f, 0.3f, 0.3f, 1.0f));

  prepareShader();
  prepareVAO();
  prepareCamera();
  prepareState();

  // 3 执行窗体循环
  while (capture.read(m_backgroundImage) && app->update())
  {
    cameraControl->update();
    render();
  }

  shader->end();

  // 4 退出程序前清理
  app->destroy();
  freePointers();
  return 0;
}

textture.cpp

Texture::Texture(cv::Mat &img, unsigned int unit)
{
  mUint = unit;

  // 生成纹理并且激活单元绑定
  glGenTextures(1, &mTexture);
  glActiveTexture(GL_TEXTURE0 + mUint);
  glBindTexture(GL_TEXTURE_2D, mTexture);

  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  // 需要的像素小于图片像素
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  // 需要的像素大于图片像素
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

  if (img.data)
  {
    mWidth = img.cols;
    mHeight = img.rows;

    // 图像反转
    cv::Mat dst;
    cv::flip(img, dst, -1);

    // 传输纹理数据
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, mWidth, mHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, dst.data);
    glGenerateMipmap(GL_TEXTURE_2D);
  }
  else
  {
    std::cout << "Failed to load texture" << std::endl;
  }
}

最终效果

        以上就是使用opencv实时采集的图像作为opengl纹理贴图的数据的全过程,尝试贴图到球体上应该更酷了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我啥都会

如果觉得对您有帮助,打赏一下吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值