简体   繁体   中英

OpenCV vs byte array

I am working on a simple C++ image processing application and deciding whether to use OpenCV for loading the image and accessing individual pixels. My current approach is to simply load the image using fopen , reading the 54 byte header and load the rest of the bytes in a char* array.

To access a specific pixel I use

long q = (long*)(bmpData + x*3 + (bmpSize.height - y - 1) * bmpSize.stride);

To perform a simple color check, for ex. "is blue?"

if (((long*)q | 0xFF000000) == 0xFFFF0000) //for some reason RGB is reversed to BGR
  //do something here

Is OpenCV any faster considering all the function calls, parsing, etc.?

Bitmap file header is actually 54 bytes and you can't skip it. You have to read it to find the width, height, bitcount... calculate padding if necessary... and other information.

Depending on how the file is opened, OpenCV will read the header and reads the pixels directly in to a buffer. The only change is that the rows are flipped so the image is right side up.

cv::Mat mat = cv::imread("filename.bmp", CV_LOAD_IMAGE_COLOR);
uint8_t* data = (uint8_t*)mat.data;

The header checks and the small changes made by OpenCV will not significantly affect performance. The bottle neck is mainly in reading the file from the disk. The change in performance will be difficult to measure, unless you are doing a very specific task, for example you want only 3 bytes in a very large file, and you don't want to read the entire file.

OpenCV is overkill for this task, so you may choose other libraries for example CImg as suggested in comments. If you use smaller libraries they load faster, it might be noticeable when your program starts.


The following code is a test run on Windows.

For a large 16MB bitmap file, the result is almost identical for opencv versus plain c++.

For a small 200kb bitmap file, the result is 0.00013 seconds to read in plain C++, and 0.00040 seconds for opencv. Note the plain c++ is not doing much beside reading the bytes.

 class stopwatch { std::chrono::time_point<std::chrono::system_clock> time_start, time_end; public: stopwatch() { reset();} void reset(){ time_start = std::chrono::system_clock::now(); } void print(const char* title) { time_end = std::chrono::system_clock::now(); std::chrono::duration<double> diff = time_end - time_start; if(title) std::cout << title; std::cout << diff.count() << "\\n"; } }; int main() { const char* filename = "filename.bmp"; //I use `fake` to prevent the compiler from over-optimization //and skipping the whole loop. But it may not be necessary here int fake = 0; //open the file 100 times int count = 100; stopwatch sw; for(int i = 0; i < count; i++) { //plain c++ std::ifstream fin(filename, std::ios::binary); fin.seekg(0, std::ios::end); int filesize = (int)fin.tellg(); fin.seekg(0, std::ios::beg); std::vector<uint8_t> pixels(filesize - 54); BITMAPFILEHEADER hd; BITMAPINFOHEADER bi; fin.read((char*)&hd, sizeof(hd)); fin.read((char*)&bi, sizeof(bi)); fin.read((char*)pixels.data(), pixels.size()); fake += pixels[i]; } sw.print("time fstream: "); sw.reset(); for(int i = 0; i < count; i++) { //opencv: cv::Mat mat = cv::imread(filename, CV_LOAD_IMAGE_COLOR); uint8_t* pixels = (uint8_t*)mat.data; fake += pixels[i]; } sw.print("time opencv: "); printf("show some fake calculation: %d\\n", fake); return 0; } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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