简体   繁体   English

将 cv::Mat 转换为 SDL_Texture

[英]Converting cv::Mat to SDL_Texture

I am trying to play a video with SDL.我正在尝试使用 SDL 播放视频。 For that I'm using opencv to load the video, and get the frames.为此,我使用 opencv 加载视频并获取帧。 Then I only need to convert those frames as I need them to a SDL_Texture* and I'm ready to draw them on the screen.然后我只需要在需要时将这些帧转换为SDL_Texture*然后我就可以在屏幕上绘制它们了。

That's my problem, I'm converting it to a SDL_Surface* but then the conversion to SDL_Texture is failing and I'm not sure why.那是我的问题,我正在将其转换为SDL_Surface*但随后转换为SDL_Texture失败,我不知道为什么。 Here is my code:这是我的代码:

void Cutscene::play()
{
  this->onLoop();
  this->onRender();

  while(!frameMat.empty())
  {
    this->onLoop();
    this->onRender();
  }
}

void Cutscene::onLoop()
{
  video >> frameMat;

  convertCV_MatToSDL_Texture();
}

void Cutscene::onRender()
{
  Image::onDraw(GameEngine::getInstance()->getRenderer(), frameTexture);

}

void Cutscene::convertCV_MatToSDL_Texture()
{
  IplImage opencvimg2 = (IplImage)frameMat;
  IplImage* opencvimg = &opencvimg2;

  //Convert to SDL_Surface
  frameSurface = SDL_CreateRGBSurfaceFrom((void*)opencvimg->imageData,
                         opencvimg->width, opencvimg->height,
                         opencvimg->depth*opencvimg->nChannels,
                         opencvimg->widthStep,
                         0xff0000, 0x00ff00, 0x0000ff, 0);

  if(frameSurface == NULL)
  {
    SDL_Log("Couldn't convert Mat to Surface.");
    return;
  }

  //Convert to SDL_Texture
  frameTexture = SDL_CreateTextureFromSurface(
                    GameEngine::getInstance()->getRenderer(), frameSurface);
  if(frameTexture == NULL)
  {
    SDL_Log("Couldn't convert Mat(converted to surface) to Texture."); //<- ERROR!!
    return;
  }

  //cvReleaseImage(&opencvimg);
  //MEMORY LEAK?? opencvimg opencvimg2
}

I've used this function SDL_CreateTextureFromSurface in other parts of my project and it works there.我在项目的其他部分使用了这个函数SDL_CreateTextureFromSurface并且它在那里工作。 So the question is: Do you know what is the problem with the conversion I do in my code?所以问题是:你知道我在代码中所做的转换有什么问题吗? If not, is there a better way to do what I'm trying to do?如果没有,有没有更好的方法来做我想做的事情?

I got it to work!我让它工作! I think the only problem was that i had to use &frameMat and not frameMat.我认为唯一的问题是我必须使用 &frameMat 而不是 frameMat。 Here is my code if someone might be interested:如果有人可能感兴趣,这是我的代码:

SDL_Texture* Cutscene::convertCV_MatToSDL_Texture(const cv::Mat &matImg)
{
    IplImage opencvimg2 = (IplImage)matImg;
    IplImage* opencvimg = &opencvimg2;

     //Convert to SDL_Surface
    frameSurface = SDL_CreateRGBSurfaceFrom(
                         (void*)opencvimg->imageData,
                         opencvimg->width, opencvimg->height,
                         opencvimg->depth*opencvimg->nChannels,
                         opencvimg->widthStep,
                         0xff0000, 0x00ff00, 0x0000ff, 0);

    if(frameSurface == NULL)
    {
        SDL_Log("Couldn't convert Mat to Surface.");
        return NULL;
    }

    //Convert to SDL_Texture
    frameTexture = SDL_CreateTextureFromSurface(
                    GameEngine::getInstance()->getRenderer(), frameSurface);
    if(frameTexture == NULL)
    {
        SDL_Log("Couldn't convert Mat(converted to surface) to Texture.");
        return NULL;
    }
    else
    {
        SDL_Log("SUCCESS conversion");
        return frameTexture;
    }

    cvReleaseImage(&opencvimg);

} }

Here is another way without IplImage :这是没有IplImage另一种方式:

cv::Mat m ...;
// I'm using SDL_TEXTUREACCESS_STREAMING because it's for a video player, you should
// pick whatever suits you most: https://wiki.libsdl.org/SDL_TextureAccess
// remember to pick the right SDL_PIXELFORMAT_* !
SDL_Texture* tex = SDL_CreateTexture(
        ren, SDL_PIXELFORMAT_BGR24, SDL_TEXTUREACCESS_STREAMING, m.cols,
        m.rows);
SDL_UpdateTexture(tex, NULL, (void*)m.data, m.step1());

// do stuff with texture
SDL_RenderClear(...);
SDL_RenderCopy(...);
SDL_RenderPresent(...);
// cleanup (only after you're done displaying. you can repeatedly call UpdateTexture without destroying it)
SDL_DestroyTexture(tex)

I prefer this to the create surface methods because you don't need to free the surface and it is more flexible (you can update the texture easily for example, instead of create/destroy).我更喜欢这个创建表面方法,因为您不需要释放表面并且它更灵活(例如,您可以轻松更新纹理,而不是创建/销毁)。 I will also note that I could not combine these approaches: ie create the texture with SDL_CreateRGBSurfaceFrom and then later update it.我还要注意,我不能结合这些方法:即使用SDL_CreateRGBSurfaceFrom创建纹理,然后再更新它。 That resulted in gray stripes and the image being messed up.这导致灰色条纹和图像混乱。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM