Skip to content

Instantly share code, notes, and snippets.

@sfalexrog
Last active February 13, 2019 14:19
Show Gist options
  • Save sfalexrog/5d239f66997896bbfac060818188c96b to your computer and use it in GitHub Desktop.
Save sfalexrog/5d239f66997896bbfac060818188c96b to your computer and use it in GitHub Desktop.
Test results for NEON/non-NEON aruco detection
#include <iostream>
#include <opencv2/aruco.hpp>
#include <opencv2/core/mat.hpp>
#include <opencv2/highgui.hpp>
#include <vector>
#include <chrono>
struct dictDescriptor
{
std::string name;
cv::Ptr<cv::aruco::Dictionary> dict;
size_t size;
};
#define BOARD_DESCS \
DICT_DESC(DICT_4X4_50, 50) \
DICT_DESC(DICT_4X4_100, 100) \
/* DICT_DESC(DICT_4X4_1000, 1000) */ \
DICT_DESC(DICT_5X5_50, 50) \
DICT_DESC(DICT_5X5_100, 100) \
/* DICT_DESC(DICT_5X5_1000, 1000) */ \
DICT_DESC(DICT_6X6_50, 50) \
DICT_DESC(DICT_6X6_100, 100) \
DICT_DESC(DICT_6X6_250, 250) \
/* DICT_DESC(DICT_6X6_1000, 1000) */ \
DICT_DESC(DICT_7X7_50, 50) \
DICT_DESC(DICT_7X7_100, 100) \
DICT_DESC(DICT_7X7_250, 250) \
/* DICT_DESC(DICT_7X7_1000, 1000) */
struct TestData
{
std::vector<dictDescriptor> dictionaries;
std::vector<cv::Mat> boardImages;
};
struct TestResult
{
std::chrono::duration<int64_t, std::nano> testDuration;
bool testPassed;
};
std::vector<TestResult> runTests(const TestData& data)
{
std::vector<TestResult> result;
for(size_t i = 0; i < data.boardImages.size(); ++i)
{
const auto& dictDesc = data.dictionaries[i];
const auto& img = data.boardImages[i];
std::vector<std::vector<cv::Point2f>> corners;
std::vector<int> ids;
auto start = std::chrono::steady_clock::now();
cv::aruco::detectMarkers(img, dictDesc.dict, corners, ids);
auto end = std::chrono::steady_clock::now();
auto duration = end - start;
result.emplace_back(TestResult{duration, ids.size() == dictDesc.size});
}
return result;
}
int main() {
int markerLength = 40;
int markerSep = 40;
int margins = 20;
#define xstr(a) str(a)
#define str(a) #a
std::vector<dictDescriptor> dictionaries{
#define DICT_DESC(type, size) dictDescriptor{xstr(type), cv::aruco::getPredefinedDictionary(cv::aruco::type), size},
BOARD_DESCS
#undef DICT_DESC
};
std::vector<cv::Mat> boardImages{
#define DICT_DESC(type, size) cv::imread("board_" xstr(type) ".png"),
BOARD_DESCS
#undef DICT_DESC
};
TestData data{dictionaries, boardImages};
std::cout << "Read all image files" << std::endl;
std::cout << "Running tests" << std::endl;
const size_t NUM_TESTS = 50;
std::vector<std::vector<TestResult>> testLog;
size_t numPassed = 0, numFailed = 0;
for(size_t i = 0; i < NUM_TESTS; ++i)
{
testLog.push_back(runTests(data));
if (i % 10 == 0) std::cout << "." << std::flush;
}
std::cout << std::endl << "Test runs finished, analyzing" << std::endl;
std::vector<int64_t> nanoMeans(boardImages.size(), 0);
for(const auto& result : testLog)
{
for(int i = 0; i < boardImages.size(); ++i)
{
nanoMeans[i] += result[i].testDuration.count();
if (result[i].testPassed)
{
numPassed += 1;
}
else
{
numFailed += 1;
}
}
}
for(int i = 0; i < boardImages.size(); ++i)
{
std::cout << dictionaries[i].name << ": mean time is " << int64_t(nanoMeans[i] / double(NUM_TESTS)) << " ns" << std::endl;
}
std::cout << "Tests passed: " << numPassed;
std::cout << "Tests failed: " << numFailed;
return 0;
}
Board dictionary OpenCV w/o NEON, ns OpenCV w/NEON, ns Change
DICT_4X4_50 113232317 103567988 -8.5%
DICT_4X4_100 310450269 290968575 -6.3%
DICT_5X5_50 120566515 110379509 -8.4%
DICT_5X5_100 344844502 326884664 -5.2%
DICT_6X6_50 135857820 126517161 -6.9%
DICT_6X6_100 404778155 388300000 -4.1%
DICT_6X6_250 789037811 747213918 -5.3%
DICT_7X7_50 106657903 97923349 -8.1%
DICT_7X7_100 271315500 253957344 -6.4%
DICT_7X7_250 799879884 758511765 -5.2%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment