Wrote a program in OpenCV, however it doesn't have comfortable canvas, so working with it is a pain in the neck for my purpose, decided to migrate to SDL2. Noticed the RAM usage is 3 times as high. For the dataset of 37 images OpenCV takes up 440mb, while SDL2 1300mb. For 166 images dataset OpenCV takes up 1500mb, and SDL2 5000mb. In the code I am storing image mipmaps and getting them on the runtime to blit on screen.
SDL2 code:
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());
}
}
and to get the texture I'm doing SDL_Texture* tex = sdltexture->get_texture(img, width);
OpenCV code:
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();
}
}
and to get the texture I'm doing cv::Mat tex = cvtexture->get_texture(img, width);
Where get_texture just returns the reference to the texture stored in mipmap
Creating SDL textures on the fly will be too slow I believe. The code is equivalent and the performance is comparable(even though opencv doesn't use gpu). So I am a bit lost as to why the memory usage difference is that drastic. Am I leaking memory somewhere? Does OpenCV use some optimizations to store the matrix while maintaining the same performance?(sounds a little bit too good to be true)
here's minimum reproducible example as requested, not sure if it's helpful tho and it bloats the post:
#include <iostream>
#include <string>
#include <SDL.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 800;
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 USE_SDL = false;
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;
for (int i = 0; i < 100; i++) {
pixels = cv::imread(path, cv::IMREAD_COLOR);
for (int i = 0; i < resolutions.size(); i++) {
// RESIZE
float scale = (float)resolutions[i]/pixels.cols;
cv::resize(pixels, pixels, cv::Size(0, 0),
scale, scale, cv::INTER_AREA);
if (USE_SDL) {
// ADD TO SDL TEXTURES
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);
} else {
// ADD TO OPENCV TEXTURES
cv_mipmaps.push_back(pixels.clone());
}
}
}
// EVERYTHING BELOW CAN BE IGNORED, NOT THE MAIN IDEA.
// RENDER SAMPLE TEXTURE TO SHOW THAT IT WORKS. RENDERS IN A WEIRD PATTERN AND THATS ALRIGHT, not the point
SDL_Texture* sample;
SDL_Rect texr{0, 0, 1600, 1600};
while(running) {
while( SDL_PollEvent( &event ) != 0 )
{
if( event.type == SDL_QUIT )
{
running = false;
}
for (int i = 0; i < 50; i++) {
texr.x = i * 50;
texr.y = i * 50;
texr.w = resolutions[i%7];
texr.h = resolutions[i%7];
if (USE_SDL) {
sample = sdl_mipmaps[i];
SDL_RenderCopy(renderer, sample, NULL, &texr);
} else {
sample = SDL_CreateTexture(renderer,
SDL_PIXELFORMAT_BGR24,
SDL_TEXTUREACCESS_STATIC,
cv_mipmaps[i].cols,
cv_mipmaps[i].rows);
SDL_UpdateTexture(sample, NULL, (void*)cv_mipmaps[i].data, cv_mipmaps[i].step1());
SDL_RenderCopy(renderer, sample, NULL, &texr);
SDL_DestroyTexture(sample);
}
}
SDL_RenderPresent(renderer);
}
}
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();
}
at the start of main there is USE_SDL bool, if set to true you load sdl textures, otherwise you load opencv textures. Path to file is also at the start of main. On my texture of 1170x700 pixels opencv used 669mb and SDL used 1850mb.