在 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。