Я пытаюсь научиться манипулировать значениями матрицы OpenCV наиболее оптимизированным способом. Я попытался масштабировать большое изображение, хранящееся в матрице OpenCV, четырьмя различными способами.
1) Использование оператора *
*
2) Использование функции at
и петли for
3) Использование доступа к указателю и for
циклов
4) Использование справочной таблицы
Округленные результаты этого эксперимента были следующими
*
оператор ------- 3 ms
at
функция ------- 12 ms
указатель доступа ---- 9 ms
справочная таблица -------- 1 ms
Теперь совершенно очевидно, почему таблицы поиска являются самыми быстрыми. Но я не всегда смогу их использовать. Для случаев, для которых я не могу использовать справочную таблицу, мне нужно понять, как OpenCV реализует масштабирование с помощью оператора *
, чтобы я мог использовать этот метод в качестве справочного материала в других моих манипуляциях со значениями матрицы.
Буду очень признателен, если кто-нибудь скажет мне, что происходит за операцией *
, которая делает его быстрее, чем метод доступа с указателем?
Пожалуйста, найдите следующий код для справки.
Спасибо
#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>
#include <chrono>
typedef std::chrono::system_clock Timer;
typedef std::chrono::duration<double> Duration;
using std::cout;
using std::endl;
using std::vector;
double profile(Timer::time_point start, Timer::time_point end) {
Duration span = end - start;
return span.count() * 1000;
}
int main() {
cv::Mat image = cv::imread("../data/large.jpg", 0);
float sc = 1;
while (true) {
//=================== first method ====================
Timer::time_point s1 = Timer::now();
cv::Mat mine = image * sc;
Timer::time_point s2 = Timer::now();
//=================== second method ====================
cv::Mat yours(image.size(), image.type());
Timer::time_point s3 = Timer::now();
for (int i = 0; i < image.rows; i++) {
for (int j = 0; j < image.cols; j++) {
yours.at<uchar>(i, j) = image.at<uchar>(i, j) * sc;
}
}
Timer::time_point s4 = Timer::now();
//=================== third method ====================
if (!image.isContinuous()) {
std::cerr << "ERROR: image matrix isn't stored as a 1D array" << endl;
exit(-1);
}
Timer::time_point s5 = Timer::now();
cv::Mat result(image.size(), image.type());
for (int i = 0; i < image.rows; i++) {
for (int j = 0; j < image.cols; j++) {
result.data[i * image.cols + j] = image.data[i * image.cols + j] * sc;
}
}
Timer::time_point s6 = Timer::now();
//=================== fourth method ====================
Timer::time_point s7 = Timer::now();
cv::Mat lookupTable(1, 256, image.type());
for (int i = 0; i < 256; i++)
lookupTable.data[i] = i * sc;
cv::Mat his;
cv::LUT(image, lookupTable, his);
Timer::time_point s8 = Timer::now();
cout << "first = " << profile(s1, s2) << endl;
cout << "second = " << profile(s3, s4) << endl;
cout << "third = " << profile(s5, s6) << endl;
cout << "fourth = " << profile(s7, s8) << endl;
cout << "=============== " << endl;
}
return 0;
}