【问题标题】:How to convert an OpenCV IplImage to an SDL_Surface?如何将 OpenCV IplImage 转换为 SDL_Surface?
【发布时间】:2010-09-28 11:32:53
【问题描述】:

我正在尝试编写一个程序,它采用 SDL_Surface,将其转换为 IplImage,使用 cvBlobsLib 查找 blob,将 blob 绘制为图像上的点,然后转换输出 IplImageSDL_Surface

我快完成了:仅将 IplImage 转换回 SDL_Surface 尚未完成。这个 IplImage 有 3 个图像通道,每像素 8 位。我想我可以使用两个电话:

SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
SDL_Surface *SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);

我目前正在尝试使用SDL_CreateRGBsurfaceFrom。但是,我不知道 pitch、Rmask、Gmask 和 Bmask 的正确值是多少。 (Amask 为 0,因为没有 alpha 通道。)

谁能帮我解释一下如何做到这一点?

谢谢!

编辑:例如,这是我尝试使用的代码:

SDL_Surface *ipl_to_surface (IplImage *opencvimg)
{
    int pitch = opencvimg->nChannels*opencvimg->width;
    printf("Depth %d, nChannels %d, pitch %d\n", opencvimg->depth,
                    opencvimg->nChannels, pitch);
    SDL_Surface *surface = SDL_CreateRGBSurfaceFrom((void*)opencvimg->imageData,
                    opencvimg->width,
                    opencvimg->height,
                    opencvimg->depth,
                    pitch,
                    0x0000ff, 0x00ff00, 0xff0000, 0
                    );
    return surface;
}

(SDL 文档写道“Pitch 是表面扫描线的大小,以字节为单位,即 widthInPixels*bytesPerPixel。”) 这将输出“Depth 8, nChannels 3, pitch 1920”并显示一个完全红色的图像。 我认为一个解决方案是将我的 8 位图像转换为 24 位(每个通道 1 个字节),但我不知道该怎么做。有什么想法吗?

【问题讨论】:

  • 您的图像是每像素 8 位,具有 3 个通道?您的意思是每像素 24 位吗,因为您指定的 RGB 掩码似乎暗示了这一点?
  • 不,恰恰相反:我指定的 RGB 蒙版是错误的。图像实际上是每像素 8 位,具有 3 个通道。我现在要试试这段代码:paster.dazjorz.com/?p=3705
  • 是的,您最好将其转换为 24 位或 32 位,因为我认为 SDL 不能很好地处理非标准位深度。
  • stackoverflow.com/questions/394488/…也看到问题... :(
  • 好的。所以现在我有一个 32 位的 3 通道图像,我需要将其转换为 SDL_Surface。

标签: c++ opencv sdl iplimage


【解决方案1】:

首先:谢谢!!

第二:它与 3 通道图像完美配合,但我想显示单通道 IplImage

所以我们开始了:

SDL_Surface *single_channel_ipl_to_surface (IplImage *opencvimg)
{
    SDL_Surface *surface = SDL_CreateRGBSurfaceFrom((void*)opencvimg->imageData,
                           opencvimg->width,
                           opencvimg->height,
                           opencvimg->depth*opencvimg->nChannels,
                           opencvimg->widthStep,
                           0xffffff, 0xffffff, 0xffffff,0);
    return surface;
}

【讨论】:

    【解决方案2】:

    好的,我搞定了!

    我想我对 OpenCV 深度为 8 意味着 一个像素每个通道有 8 位,因此在 3 通道图像中,一个像素有 24 位这一事实感到困惑。因此,当将其转换为深度的 SDL 含义时,我们得到 8 * 3 = 24 位。

    图像毕竟是 24 位的,SDL 支持。所以把图片转成SDL就这么简单:

    SDL_Surface *surface = SDL_CreateRGBSurfaceFrom((void*)opencvimg->imageData,
                    opencvimg->width,
                    opencvimg->height,
                    opencvimg->depth*opencvimg->nChannels,
                    opencvimg->widthStep,
                    0xff0000, 0x00ff00, 0x0000ff, 0
                    );
    return surface;
    

    对不起,我希望这可以帮助任何寻找相同答案的人。

    其他感兴趣的链接: http://www.libsdl.org/cgi/docwiki.cgi/Pixel_Access
    完整的子程序位于: http://paster.dazjorz.com/?p=3714

    【讨论】:

    • 如果您使用的是 C++,我真的鼓励您尽快将标准指针 (*) 转换为智能指针。否则,意外的、未处理的异常将产生内存泄漏。看一下智能指针的 boost 系列。还有其他实现。 OpenCV 本身提供了一个,它可能不像 boost 中的所有东西那么花哨,但它确实可以防止内存泄漏和悬空指针。
    猜你喜欢
    • 1970-01-01
    • 2010-09-28
    • 2013-05-17
    • 2011-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多