为什么我的 SDL2 纹理占用了这么多空间?

问题描述 投票:0回答:0

在 OpenCV 中编写了一个程序,但是它没有舒适的画布,所以使用它对我来说是一种痛苦,决定迁移到 SDL2。注意到 RAM 使用率是原来的 3 倍。对于 37 张图像的数据集,OpenCV 占用 440mb,而 SDL2 占用 1300mb。对于 166 张图像数据集,OpenCV 占用 1500mb,而 SDL2 占用 5000mb。在代码中,我存储图像 mipmaps 并让它们在运行时在屏幕上 blit。

SDL2代码:

void SDLTexture::set_texture(Image* image, cv::Mat& pixels) {
    for (int i = 0; i < resolutions.size(); i++) {
        float scale = (float)resolutions[i]/pixels.cols;
        cv::resize(pixels, pixels, cv::Size(0, 0),
                    scale, scale, cv::INTER_AREA);

        mipmaps[i][image->get_name()] = SDL_CreateTexture(renderer,
                                           SDL_PIXELFORMAT_BGR24,
                                           SDL_TEXTUREACCESS_STATIC,
                                           pixels.cols,
                                           pixels.rows);

        SDL_UpdateTexture(mipmaps[i][image->get_name()], NULL, (void*)pixels.data, pixels.step1());
    }
}

并获得我正在做的质地

SDL_Texture* tex = sdltexture->get_texture(img, width);

OpenCV代码:

void CVTexture::set_texture(Image* image, cv::Mat& pixels) {
    for (int i = 0; i < resolutions.size(); i++) {
        float scale = (float)resolutions[i]/pixels.cols;
        cv::resize(pixels, pixels, cv::Size(0, 0),
                    scale, scale, cv::INTER_AREA);
        mipmaps[i][image->get_name()] = pixels.clone();
    }
}

并获得我正在做的质地

cv::Mat tex = cvtexture->get_texture(img, width);
其中 get_texture 只是返回对存储在 mipmap 中的纹理的引用

我认为即时创建 SDL 纹理会太慢。 代码是等效的,性能也相当(即使 opencv 不使用 gpu)。所以我有点迷茫为什么内存使用差异如此之大。我在某处泄漏内存吗? OpenCV 是否在保持相同性能的同时使用一些优化来存储矩阵?(听起来有点好得令人难以置信)

这里是按要求提供的最小可重现示例,但不确定它是否有帮助并且它会使帖子膨胀:

#include <iostream>
#include <string>

#include <SDL.h>

#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>

const int SCREEN_WIDTH = 100;
const int SCREEN_HEIGHT = 100;

void init(SDL_Window** window_ptr, SDL_Surface** surface_ptr, SDL_Renderer** renderer_ptr);
void close(SDL_Window** window);

int main( int argc, char* args[] ) {
    bool SDL = true;
    std::string path = "1.png";

    SDL_Window* window = NULL;
    SDL_Surface* screenSurface = NULL;
    SDL_Renderer* renderer = NULL;
    SDL_Event event;

    init(&window, &screenSurface, &renderer);

    bool running = true;

    std::vector<int> resolutions = {1600, 800, 400, 200, 100, 50, 25};
    std::vector<SDL_Texture*> sdl_mipmaps;
    std::vector<cv::Mat> cv_mipmaps;
    cv::Mat pixels;

    if (!SDL) {
        for (int i = 0; i < 100; i++) {
            pixels = cv::imread(path, cv::IMREAD_COLOR);

            for (int i = 0; i < resolutions.size(); i++) {
                float scale = (float)resolutions[i]/pixels.cols;
                cv::resize(pixels, pixels, cv::Size(0, 0),
                            scale, scale, cv::INTER_AREA);
                cv_mipmaps.push_back(pixels.clone());
            }
        }
    } else {
        for (int i = 0; i < 100; i++) {
            pixels = cv::imread(path, cv::IMREAD_COLOR);

            for (int i = 0; i < resolutions.size(); i++) {
                float scale = (float)resolutions[i]/pixels.cols;
                cv::resize(pixels, pixels, cv::Size(0, 0),
                            scale, scale, cv::INTER_AREA);
                SDL_Texture* sdltex = SDL_CreateTexture(renderer,
                                           SDL_PIXELFORMAT_BGR24,
                                           SDL_TEXTUREACCESS_STATIC,
                                           pixels.cols,
                                           pixels.rows);

                SDL_UpdateTexture(sdltex, NULL, (void*)pixels.data, pixels.step1());
                sdl_mipmaps.push_back(sdltex);
            }
        }
    }

    while(running) {
        while( SDL_PollEvent( &event ) != 0 )
        {
            if( event.type == SDL_QUIT )
            {
                running = false;
            }
        }
    }
    close(&window);

    return 0;
}


/* Handles initializing SDL window. */
void init(SDL_Window** window_ptr, SDL_Surface** surface_ptr, SDL_Renderer** renderer_ptr) {
    SDL_Init( SDL_INIT_VIDEO );

    *window_ptr = SDL_CreateWindow( "imageVimage", SDL_WINDOWPOS_UNDEFINED,
                               SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH,
                                SCREEN_HEIGHT, SDL_WINDOW_SHOWN );

    *renderer_ptr = SDL_CreateRenderer( *window_ptr, -1, SDL_RENDERER_ACCELERATED );

    SDL_SetRenderDrawColor( *renderer_ptr, 0xFF, 0xFF, 0xFF, 0xFF );

    *surface_ptr = SDL_GetWindowSurface( *window_ptr );
}

/* Handles closing the window and deallocating the memory. */
void close(SDL_Window** window) {
    SDL_DestroyWindow( *window );
    *window = NULL;
    SDL_Quit();
}

在 main 的开头有一个 SDL bool,如果设置为 true 则加载 sdl 纹理,否则加载 opencv 纹理。文件路径也在 main 的开头。在我的 1170x700 像素纹理上,opencv 使用了 669mb,SDL 使用了 1850mb。

c++ opencv sdl sdl-2
© www.soinside.com 2019 - 2024. All rights reserved.