diff options
| author | Nikita Kostovsky <nikita@kostovsky.me> | 2025-01-23 12:08:26 +0100 |
|---|---|---|
| committer | Nikita Kostovsky <nikita@kostovsky.me> | 2025-01-23 12:08:26 +0100 |
| commit | 3fa8f19daf8b36b0703002d78a84e5bb7919849b (patch) | |
| tree | a82c63aac3b415cb5eddba58ba610213e85f9ae1 | |
| parent | 38acf876313c9bf28e41acd8bc29d6115c1e9285 (diff) | |
add support of inno-maker ov9281
| -rw-r--r-- | CMakeLists.txt | 32 | ||||
| -rw-r--r-- | httpservice.h | 2 | ||||
| -rw-r--r-- | imagealgos.cpp | 339 | ||||
| -rw-r--r-- | imagealgos.h | 10 | ||||
| -rw-r--r-- | macro.h | 12 | ||||
| -rw-r--r-- | main.cpp | 186 | ||||
| -rw-r--r-- | profile.cpp | 2 | ||||
| -rw-r--r-- | src/calibration.cpp | 4 | ||||
| -rw-r--r-- | src/camera/innomakerov9281.cpp | 280 | ||||
| -rw-r--r-- | src/camera/innomakerov9281.h | 36 | ||||
| -rw-r--r-- | src/camera/ov9281.cpp | 35 | ||||
| -rw-r--r-- | src/camera/ov9281.h | 5 | ||||
| -rw-r--r-- | src/constants.h | 3 | ||||
| -rw-r--r-- | src/dumps.cpp | 1 | ||||
| -rw-r--r-- | src/image.cpp | 44 | ||||
| -rw-r--r-- | src/image.h | 8 |
16 files changed, 704 insertions, 295 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ffc2f1..32fdfaa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.16) - +project(orpheus LANGUAGES CXX) set(CMAKE_CXX_STANDARD 23) cmake_minimum_required(VERSION 3.18) @@ -26,6 +26,33 @@ set(ENV{PKG_CONFIG_SYSROOT_DIR} ${CMAKE_SYSROOT}) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${TARGET_SYSROOT}/usr/include") set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") +find_package(OpenMP) +if (OPENMP_FOUND) + message("found openmp") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") +endif() + +# NOTE: on your rpi you'll need to install +# libcamera-dev, libcamera-ipa (TODO: check if ipa is needed) +# libqt6gui6 +# libqt6httpserver6 +# libqt6serialport6 (if you want to control your 3d printer from rpi) +# libtbb-dev (or just comment out source code related to execution policies) +# libpistache-dev - TODO: remove this dep, orpheus uses qt http server +# don't forget to rsync local copy of rpi fs with real rpi fs +# NOTE: to be able to run orpheus remotely from QtCreator, run this on your RPI: +# $ sudo chown -R user:adm /usr/local/bin/ +# NOTE: to use rotary encoder you'll need WiringPi which is not in rpi repos, so +# $ git clone https://github.com/WiringPi/WiringPi.git +# check README.md for installation instructions. You may get this while installing +# .deb package, but it's ok: +# N: Download is performed unsandboxed as root as file +# '/home/user/git/third_party/WiringPi/wiringpi_3.12_arm64.deb' couldn't be +# accessed by user '_apt'. - pkgAcquire::Run (13: Permission denied) + + # NOTE: I've added ld symlink on host to be able to run moc # arch: # sudo ln -s /usr/aarch64-linux-gnu/lib/ld-linux-aarch64.so.1 /lib/ld-linux-aarch64.so.1 @@ -57,8 +84,6 @@ message(STATUS ${LIBCAMERA_BASE_LIBRARY}) pkg_check_modules(CAMERA REQUIRED libcamera) set(LIBCAMERA_LIBRARIES "${LIBCAMERA_LIBRARY}" "${LIBCAMERA_BASE_LIBRARY}") -project(orpheus LANGUAGES CXX) - set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-std:c++latest") @@ -101,6 +126,7 @@ qt_add_executable(apporpheus src/camera/ov9281.h src/camera/ov9281.cpp src/image.h src/image.cpp src/laser.h src/laser.cpp + src/camera/innomakerov9281.h src/camera/innomakerov9281.cpp ) target_link_libraries(app${PROJECT_NAME} PRIVATE diff --git a/httpservice.h b/httpservice.h index 80b8e4a..a6c3f76 100644 --- a/httpservice.h +++ b/httpservice.h @@ -10,7 +10,7 @@ using namespace Pistache; -extern uint8_t pgm_image[64 + img_width * img_height * sizeof(uint16_t)]; +extern uint8_t pgm_image[64 + img_width * img_height * sizeof(uint8_t)]; extern size_t pgm_image_size; extern std::mutex pgm_image_mtx; diff --git a/imagealgos.cpp b/imagealgos.cpp index 6bd4d1e..5936855 100644 --- a/imagealgos.cpp +++ b/imagealgos.cpp @@ -14,7 +14,7 @@ #include "macro.h" -uint8_t pgm_image[64 + img_width * img_height * sizeof(uint16_t)]; +uint8_t pgm_image[64 + img_width * img_height * sizeof(uint8_t)]; size_t pgm_image_size = 0; std::mutex pgm_image_mtx; @@ -25,7 +25,8 @@ T median3(const T &a, const T &b, const T &c) return max(min(a, b), min(max(a, b), c)); } -size_t pgm_save(Image *img, FILE *outfile, bool really_save) { +size_t pgm_save(std::shared_ptr<Image> img, FILE *outfile, bool really_save) +{ std::lock_guard<std::mutex> lg(pgm_image_mtx); size_t n = 0; @@ -38,9 +39,10 @@ size_t pgm_save(Image *img, FILE *outfile, bool really_save) { // for (size_t i = 0; i < img->width * img->height; ++i) for (size_t i = 0; i < img_width * img_height; ++i) { - uint16_t *pixels = (uint16_t*)img->data; + uint8_t *pixels = (uint8_t *) img->data; // const auto p = pixels[i]; - uint8_t value = (pixels[i] & 0xFF00) >> 8; + // uint8_t value = (pixels[i] & 0xFF00) >> 8; + uint8_t value = pixels[i]; // n += fwrite(&value, 1, 1, outfile); memcpy((void*)(pgm_image + n), &value, sizeof(value)); @@ -53,215 +55,214 @@ size_t pgm_save(Image *img, FILE *outfile, bool really_save) { if (really_save) { - fwrite(pgm_image, 1, pgm_image_size, outfile); - fflush(outfile); + if (outfile) { + fwrite(pgm_image, 1, pgm_image_size, outfile); + fflush(outfile); + + } else { + std::cerr << __func__ << ": output filename is nullptr, cannot save" + << std::endl; + } } return n; } -void unpack_10bit(uint8_t const *src, Image const &image, uint16_t *dest) -{ - unsigned int w_align = image.width & ~3; - for (unsigned int y = 0; y < image.height; y++, src += image.stride) - { - uint8_t const *ptr = src; - unsigned int x; - for (x = 0; x < w_align; x += 4, ptr += 5) - { - *dest++ = (ptr[0] << 2) | ((ptr[4] >> 0) & 3); - *dest++ = (ptr[1] << 2) | ((ptr[4] >> 2) & 3); - *dest++ = (ptr[2] << 2) | ((ptr[4] >> 4) & 3); - *dest++ = (ptr[3] << 2) | ((ptr[4] >> 6) & 3); - } - for (; x < image.width; x++) - *dest++ = (ptr[x & 3] << 2) | ((ptr[4] >> ((x & 3) << 1)) & 3); - } -} +// void unpack_10bit(uint8_t const *src, Image const &image, uint16_t *dest) +// { +// unsigned int w_align = image.width & ~3; +// for (unsigned int y = 0; y < image.height; y++, src += image.stride) +// { +// uint8_t const *ptr = src; +// unsigned int x; +// for (x = 0; x < w_align; x += 4, ptr += 5) +// { +// *dest++ = (ptr[0] << 2) | ((ptr[4] >> 0) & 3); +// *dest++ = (ptr[1] << 2) | ((ptr[4] >> 2) & 3); +// *dest++ = (ptr[2] << 2) | ((ptr[4] >> 4) & 3); +// *dest++ = (ptr[3] << 2) | ((ptr[4] >> 6) & 3); +// } +// for (; x < image.width; x++) +// *dest++ = (ptr[x & 3] << 2) | ((ptr[4] >> ((x & 3) << 1)) & 3); +// } +// } -void unpack_16bit(uint8_t const *src, Image const &image, uint16_t *dest) -{ - start_timer(unpack_16bit); - /* Assume the pixels in memory are already in native byte order */ - unsigned int w = image.width; +// void unpack_16bit(uint8_t const *src, Image const &image, uint16_t *dest) +// { +// start_timer(unpack_16bit); +// /* Assume the pixels in memory are already in native byte order */ +// unsigned int w = image.width; - for (unsigned int y = 0; y < image.height; y++) - { - memcpy(dest, src, 2 * w); - dest += w; - src += image.stride; - } - stop_timer(unpack_16bit); -} +// for (unsigned int y = 0; y < image.height; y++) +// { +// memcpy(dest, src, 2 * w); +// dest += w; +// src += image.stride; +// } +// stop_timer(unpack_16bit); +// } template<class T, size_t N> constexpr size_t mysize(T (&)[N]) { return N; } -void smooth_column(uint16_t (&column)[]) { - for (size_t i = 1; i < img_height - 1; ++i) { - column[i] = median3(column[i - 1], column[i], column[i + 1]); - } -} +// void smooth_column(uint8_t (&column)[]) +// { +// for (size_t i = 1; i < img_height - 1; ++i) { +// column[i] = median3(column[i - 1], column[i], column[i + 1]); +// } +// } -float process_column(uint16_t (&column)[]) -{ - start_timer(process_column); - - float result = std::numeric_limits<float>::quiet_NaN(); +// float process_column(uint8_t (&column)[]) +// { +// std::cout << "aaaaaaaaaaa\n"; +// start_timer(process_column); - constexpr uint32_t signalThreshold = 900; // = SKO * sqrt(patternSize) - static constexpr uint32_t patternOffset = patternSize - ((patternSize % 2 == 1) ? 1 : 0); - const uint32_t correlationSize = img_height - patternSize + - ((patternSize % 2 == 1) ? 1 : 0); - uint32_t correlation[img_height]; - uint32_t integralSum[img_height]; - uint32_t maxSum = signalThreshold * 50; - uint32_t x1 = 0; - int32_t y1 = 0; - int32_t y2 = 0; +// float result = std::numeric_limits<float>::quiet_NaN(); - memset(correlation, 0, img_height * sizeof(correlation[0])); - integralSum[0] = 0; +// constexpr uint32_t signalThreshold = 900; // = SKO * sqrt(patternSize) +// static constexpr uint32_t patternOffset = patternSize - ((patternSize % 2 == 1) ? 1 : 0); +// const uint32_t correlationSize = img_height - patternSize + ((patternSize % 2 == 1) ? 1 : 0); +// uint32_t correlation[img_height]; +// uint32_t integralSum[img_height]; +// uint32_t maxSum = signalThreshold * 50; +// uint32_t x1 = 0; +// int32_t y1 = 0; +// int32_t y2 = 0; - for(uint32_t i = 1; i < img_height; ++i) { - // if (column[i + 0] < 100) { column[i + 0] = 0; } integralSum[i + 0] = column[i + 0] / 256 + integralSum[i + 0 - 1]; - // if (column[i + 1] < 100) { column[i + 1] = 0; } integralSum[i + 1] = column[i + 1] / 256 + integralSum[i + 1 - 1]; - // if (column[i + 2] < 100) { column[i + 2] = 0; } integralSum[i + 2] = column[i + 2] / 256 + integralSum[i + 2 - 1]; - // if (column[i + 3] < 100) { column[i + 3] = 0; } integralSum[i + 3] = column[i + 3] / 256 + integralSum[i + 3 - 1]; - // if (column[i + 4] < 100) { column[i + 4] = 0; } integralSum[i + 4] = column[i + 4] / 256 + integralSum[i + 4 - 1]; - // if (column[i + 5] < 100) { column[i + 5] = 0; } integralSum[i + 5] = column[i + 5] / 256 + integralSum[i + 5 - 1]; - // if (column[i + 6] < 100) { column[i + 6] = 0; } integralSum[i + 6] = column[i + 6] / 256 + integralSum[i + 6 - 1]; - // if (column[i + 7] < 100) { column[i + 7] = 0; } integralSum[i + 7] = column[i + 7] / 256 + integralSum[i + 7 - 1]; - // if (column[i + 8] < 100) { column[i + 8] = 0; } integralSum[i + 8] = column[i + 8] / 256 + integralSum[i + 8 - 1]; - // if (column[i + 9] < 100) { column[i + 9] = 0; } integralSum[i + 9] = column[i + 9] / 256 + integralSum[i + 9 - 1]; - // if (column[i + 10] < 100) { column[i + 10] = 0; } integralSum[i + 10] = column[i + 10] / 256 + integralSum[i + 10 - 1]; - // if (column[i + 11] < 100) { column[i + 11] = 0; } integralSum[i + 11] = column[i + 11] / 256 + integralSum[i + 11 - 1]; - // if (column[i + 12] < 100) { column[i + 12] = 0; } integralSum[i + 12] = column[i + 12] / 256 + integralSum[i + 12 - 1]; - // if (column[i + 13] < 100) { column[i + 13] = 0; } integralSum[i + 13] = column[i + 13] / 256 + integralSum[i + 13 - 1]; - // if (column[i + 14] < 100) { column[i + 14] = 0; } integralSum[i + 14] = column[i + 14] / 256 + integralSum[i + 14 - 1]; - // if (column[i + 15] < 100) { column[i + 15] = 0; } integralSum[i + 15] = column[i + 15] / 256 + integralSum[i + 15 - 1]; - - if (column[i] < 100) { column[i] = 0; } - integralSum[i] = column[i] / 256 + integralSum[i - 1]; - } +// memset(correlation, 0, img_height * sizeof(correlation[0])); +// integralSum[0] = 0; - // maxSum = 0 ; - // size_t maxIdx { 0 }; +// for (uint32_t i = 1; i < img_height; ++i) { +// // if (column[i + 0] < 100) { column[i + 0] = 0; } integralSum[i + 0] = column[i + 0] / 256 + integralSum[i + 0 - 1]; +// // if (column[i + 1] < 100) { column[i + 1] = 0; } integralSum[i + 1] = column[i + 1] / 256 + integralSum[i + 1 - 1]; +// // if (column[i + 2] < 100) { column[i + 2] = 0; } integralSum[i + 2] = column[i + 2] / 256 + integralSum[i + 2 - 1]; +// // if (column[i + 3] < 100) { column[i + 3] = 0; } integralSum[i + 3] = column[i + 3] / 256 + integralSum[i + 3 - 1]; +// // if (column[i + 4] < 100) { column[i + 4] = 0; } integralSum[i + 4] = column[i + 4] / 256 + integralSum[i + 4 - 1]; +// // if (column[i + 5] < 100) { column[i + 5] = 0; } integralSum[i + 5] = column[i + 5] / 256 + integralSum[i + 5 - 1]; +// // if (column[i + 6] < 100) { column[i + 6] = 0; } integralSum[i + 6] = column[i + 6] / 256 + integralSum[i + 6 - 1]; +// // if (column[i + 7] < 100) { column[i + 7] = 0; } integralSum[i + 7] = column[i + 7] / 256 + integralSum[i + 7 - 1]; +// // if (column[i + 8] < 100) { column[i + 8] = 0; } integralSum[i + 8] = column[i + 8] / 256 + integralSum[i + 8 - 1]; +// // if (column[i + 9] < 100) { column[i + 9] = 0; } integralSum[i + 9] = column[i + 9] / 256 + integralSum[i + 9 - 1]; +// // if (column[i + 10] < 100) { column[i + 10] = 0; } integralSum[i + 10] = column[i + 10] / 256 + integralSum[i + 10 - 1]; +// // if (column[i + 11] < 100) { column[i + 11] = 0; } integralSum[i + 11] = column[i + 11] / 256 + integralSum[i + 11 - 1]; +// // if (column[i + 12] < 100) { column[i + 12] = 0; } integralSum[i + 12] = column[i + 12] / 256 + integralSum[i + 12 - 1]; +// // if (column[i + 13] < 100) { column[i + 13] = 0; } integralSum[i + 13] = column[i + 13] / 256 + integralSum[i + 13 - 1]; +// // if (column[i + 14] < 100) { column[i + 14] = 0; } integralSum[i + 14] = column[i + 14] / 256 + integralSum[i + 14 - 1]; +// // if (column[i + 15] < 100) { column[i + 15] = 0; } integralSum[i + 15] = column[i + 15] / 256 + integralSum[i + 15 - 1]; - // for (size_t i = 0; i < img_height - patternSize; ++i) { - // const auto sum = integralSum[i + patternSize] - integralSum[i]; - // if (sum > maxSum) { - // maxSum = sum; - // maxIdx = i; - // } - // } +// if (column[i] < 100) { +// column[i] = 0; +// } +// integralSum[i] = column[i] + integralSum[i - 1]; +// } - // Algo genetic(column + maxIdx); - // // std::cout << "maxIdx " << maxIdx << std::endl; +// // maxSum = 0 ; +// // size_t maxIdx { 0 }; - // // return maxIdx + genetic.run().a; - // return 500; - // return img_height - maxIdx - genetic.run().a; +// // for (size_t i = 0; i < img_height - patternSize; ++i) { +// // const auto sum = integralSum[i + patternSize] - integralSum[i]; +// // if (sum > maxSum) { +// // maxSum = sum; +// // maxIdx = i; +// // } +// // } +// // Algo genetic(column + maxIdx); +// // // std::cout << "maxIdx " << maxIdx << std::endl; - for(uint32_t i = 0; i < correlationSize; ++i) - correlation[i + patternSize / 2] = - column[i + patternSize / 2] / 256 * - (integralSum[i + patternOffset] - integralSum[i]); +// // // return maxIdx + genetic.run().a; +// // return 500; +// // return img_height - maxIdx - genetic.run().a; - for(uint32_t i = 3; i < img_height - 2; ++i) - { - const auto sum = correlation[i - 1] + - correlation[i] + - correlation[i + 1]; +// for (uint32_t i = 0; i < correlationSize; ++i) +// correlation[i + patternSize / 2] = column[i + patternSize / 2] / 256 +// * (integralSum[i + patternOffset] - integralSum[i]); - if(sum > maxSum) - { - const int32_t rioux0 = int32_t(correlation[i - 2 - 1] + correlation[i - 1 - 1]) - - int32_t(correlation[i + 1 - 1] + correlation[i + 2 - 1]); +// for (uint32_t i = 3; i < img_height - 2; ++i) { +// const auto sum = correlation[i - 1] + correlation[i] + correlation[i + 1]; - if(rioux0 < 0) - { - const int32_t rioux1 = int32_t(correlation[i - 2] + correlation[i - 1]) - - int32_t(correlation[i + 1] + correlation[i + 2]); +// if (sum > maxSum) { +// const int32_t rioux0 = int32_t(correlation[i - 2 - 1] + correlation[i - 1 - 1]) +// - int32_t(correlation[i + 1 - 1] + correlation[i + 2 - 1]); - if(rioux1 >= 0) - { - x1 = i - 1; - y1 = rioux0; - y2 = rioux1; - maxSum = sum; - } - } - } - } +// if (rioux0 < 0) { +// const int32_t rioux1 = int32_t(correlation[i - 2] + correlation[i - 1]) +// - int32_t(correlation[i + 1] + correlation[i + 2]); - result = (y2 != y1) ? - (float(x1) - (float(y1) / (y2 - y1))) : - std::numeric_limits<float>::quiet_NaN(); +// if (rioux1 >= 0) { +// x1 = i - 1; +// y1 = rioux0; +// y2 = rioux1; +// maxSum = sum; +// } +// } +// } +// } +// result = (y2 != y1) ? (float(x1) - (float(y1) / (y2 - y1))) +// : std::numeric_limits<float>::quiet_NaN(); - static bool result_done = false; - if (!result_done) { - std::cout << "result " << result << std::endl; - result_done = true; - } - // std::cout << "result is '" << result << "'\n"; +// static bool result_done = false; +// if (!result_done) { +// std::cout << "result " << result << std::endl; +// result_done = true; +// } +// // std::cout << "result is '" << result << "'\n"; - // stop_timer(process_column); +// // stop_timer(process_column); - return result; +// return result; -// center of mass -#if 0 - auto max_el = std::max_element(std::begin(accumulated_sum), - std::end(accumulated_sum) - window_size); +// // center of mass +// #if 0 +// auto max_el = std::max_element(std::begin(accumulated_sum), +// std::end(accumulated_sum) - window_size); - size_t max_sum_idx = max_el - std::begin(accumulated_sum) + window_size; +// size_t max_sum_idx = max_el - std::begin(accumulated_sum) + window_size; - double sum_w = 0; - double prod_wx = 0; - double wmc = 0; +// double sum_w = 0; +// double prod_wx = 0; +// double wmc = 0; - for(int i = max_sum_idx - window_size; i < max_sum_idx; ++i) - { - prod_wx += column[i] * i; - sum_w += column[i]; - } +// for(int i = max_sum_idx - window_size; i < max_sum_idx; ++i) +// { +// prod_wx += column[i] * i; +// sum_w += column[i]; +// } - wmc = float(prod_wx) / float(sum_w); +// wmc = float(prod_wx) / float(sum_w); - result = img_height - wmc; +// result = img_height - wmc; - return result; -#endif -} +// return result; +// #endif +// } -Pixels process_columns(Image &image) -{ - Pixels result; - result.counters = image.counters; +// Pixels process_columns(Image &image) +// { +// Pixels result; +// result.counters = image.counters; - // std::cout << "here\n"; - start_timer(process_columns); +// // std::cout << "here\n"; +// start_timer(process_columns); - for (size_t i = 0; i < image.width; i++) - { - // smooth_column(image.rotated_cw[i]); - result.pixels[i] = process_column(image.rotated_cw[i]); - // Algo genetic(image.rotated_cw[i]); +// for (size_t i = 0; i < image.width; i++) +// { +// // smooth_column(image.rotated_cw[i]); +// result.pixels[i] = process_column(image.rotated_cw[i]); +// // Algo genetic(image.rotated_cw[i]); - // image.pixels[i] = genetic.run().a; +// // image.pixels[i] = genetic.run().a; - // if (i == 0) { - // std::cout << "pixel: " << image.pixels[i] << std::endl; - // } - } +// // if (i == 0) { +// // std::cout << "pixel: " << image.pixels[i] << std::endl; +// // } +// } - stop_timer(process_columns); +// stop_timer(process_columns); - return result; -} +// return result; +// } QList<QLineF> pixelsToLines(const Pixels &rawProfile) { diff --git a/imagealgos.h b/imagealgos.h index 4094f87..e443e10 100644 --- a/imagealgos.h +++ b/imagealgos.h @@ -6,12 +6,14 @@ #include "image.h" #include "pixels.h" -size_t pgm_save(Image *img, FILE *outfile, bool really_save = false); +size_t pgm_save(std::shared_ptr<Image> img, + FILE *outfile = nullptr, + bool really_save = false); -void unpack_10bit(uint8_t const *src, Image const &image, uint16_t *dest); -void unpack_16bit(uint8_t const *src, Image const &image, uint16_t *dest); +// void unpack_10bit(uint8_t const *src, Image const &image, uint16_t *dest); +// void unpack_16bit(uint8_t const *src, Image const &image, uint16_t *dest); -Pixels process_columns(Image & image); +// Pixels process_columns(Image & image); QList<QLineF> pixelsToLines(const Pixels& rawProfile); QList<QLineF> pointsToLines(const QList<QPointF>& points); @@ -4,16 +4,12 @@ #include <iostream> #define start_timer(name) \ - std::chrono::steady_clock::time_point begin_ ## name = \ - std::chrono::steady_clock::now(); \ - \ + std::chrono::steady_clock::time_point begin_##name = std::chrono::steady_clock::now(); #define stop_timer(name) \ - std::chrono::steady_clock::time_point end_ ## name = \ - std::chrono::steady_clock::now(); \ + std::chrono::steady_clock::time_point end_##name = std::chrono::steady_clock::now(); \ // std::cout << #name << " (us): " \ - // << std::chrono::duration_cast<std::chrono::microseconds>( \ - // end_ ## name - begin_ ## name) \ - // << std::endl; + // << std::chrono::duration_cast<std::chrono::microseconds>(end_##name - begin_##name) \ + // << std::endl; #define INIT_FIELD(name) m_##name(name) @@ -9,6 +9,7 @@ #include "LibCamera.h" #include "calibration.h" +#include "camera/innomakerov9281.h" #include "camera/ov9281.h" #include "dumps.h" #include "fuck_intel.h" @@ -52,7 +53,7 @@ extern volatile int32_t positionSteps; requested_params_t requested_params; namespace { -Image img; +std::shared_ptr<Image> img; Pixels pixels; std::vector<Pixels> calibrationPixels; QMutex calibrationPixelsMutex; @@ -87,42 +88,73 @@ auto printPixels = [](const auto& pixels) { std::cout << std::endl; }; +void onNewImage( + std::shared_ptr<Image> image) +{ + if (!image) { + qDebug() << __func__ << "no image"; + return; + } + + ::img = image; +} + void onNewPixels( std::shared_ptr<Pixels> pixels) { + if (!pixels) { + qDebug() << __func__ << "got null pixels"; + } + if (!*pixels) { - qDebug() << "got empty pixels"; + // qDebug() << __func__ << "got empty pixels"; } ::pixels = *pixels; - - if (!::pixels) { - qDebug() << "empty pixels after copy"; - } } bool initLaser(); -int main( - int argc, char* argv[]) +int main(int argc, char* argv[]) { QCoreApplication app(argc, argv); + { + std::cout << std::boolalpha; + InnoMakerOV9281 innoMakerCam; + qDebug() << "init:" << innoMakerCam.init(); + qDebug() << "set exposure:" << innoMakerCam.setExposureTimeMs(3000); + qDebug() << "set gain:" << innoMakerCam.setGain(3000); + + Image buf; + + for (size_t i = 0; i < 1000; ++i) { + if (!innoMakerCam.getImage(buf)) { + break; + } + + buf.rotate(); + auto pixels = buf.pixels(); + } + } + qDebug() << "ok"; + exit(EXIT_SUCCESS); + // if (false) qDebug() << "size of raw profile" << sizeof(Pixels); - if (true) { + if (false) { // open binary calibration table - if (false) { + if (true) { if (!openCalibrationTable("/home/user/dumps/binz.calibration_table", ::calibrationTableZ)) { exit(EXIT_FAILURE); } - interpolate(::calibrationTableZ); + // interpolate(::calibrationTableZ); if (!openCalibrationTable("/home/user/dumps/binx.calibration_table", ::calibrationTableX)) { exit(EXIT_FAILURE); } - interpolate(::calibrationTableX); + // interpolate(::calibrationTableX); } if (false) { @@ -200,84 +232,82 @@ int main( // .save("/home/user/dumps/imageX_interpolated.png"); } - if (true) { - auto rawProfiles = openDump("/home/user/dumps/binz"); - // auto rawProfiles = openDump("/home/user/dumps/z"); - qDebug() << "raw z-profiles count is" << rawProfiles.size(); - // qDebug() << "height" << calibrationColumnHeight; + // load binary calibration dumps and calibrate + if (false) { + if (true) { + auto rawProfiles = openDump("/home/user/dumps/binz"); + // auto rawProfiles = openDump("/home/user/dumps/z"); + qDebug() << "raw z-profiles count is" << rawProfiles.size(); + // qDebug() << "height" << calibrationColumnHeight; - auto filteredRawProfiles = filter(std::move(rawProfiles)); - qDebug() << "filtered z-profiles count is" - << filteredRawProfiles.count(); + auto filteredRawProfiles = filter(std::move(rawProfiles)); + qDebug() << "filtered z-profiles count is" + << filteredRawProfiles.count(); - ::calibrationTableZ = calibrateZ(std::move(filteredRawProfiles), - requested_params.stepsPerMm); - // if (!dump( - // ::calibrationTableZ, - // "/home/user/dumps/binz.calibration_table" - // )) - // { - // qApp->exit(EXIT_FAILURE); - // } + ::calibrationTableZ = calibrateZ(std::move(filteredRawProfiles), + requested_params.stepsPerMm); - // bool ok = calibrationTableToImage(::calibrationTableZ) - // .save("/home/user/dumps/z/imageZ.png"); + // bool ok = calibrationTableToImage(::calibrationTableZ) + // .save("/home/user/dumps/z/imageZ.png"); - // if (!ok) - // { - // qDebug() << "cannot save imageZ.png"; - // exit(EXIT_FAILURE); - // } + // if (!ok) + // { + // qDebug() << "cannot save imageZ.png"; + // exit(EXIT_FAILURE); + // } - interpolate(::calibrationTableZ); + interpolate(::calibrationTableZ); - // calibrationTableToImage(::calibrationTableZ) - // .save("/home/user/dumps/z/imageZ_interpolated.png"); - // exit(EXIT_SUCCESS); - } + if (!dump(::calibrationTableZ, + "/home/user/dumps/binz.calibration_table")) { + qApp->exit(EXIT_FAILURE); + } + // calibrationTableToImage(::calibrationTableZ) + // .save("/home/user/dumps/z/imageZ_interpolated.png"); + // exit(EXIT_SUCCESS); + } - qDebug() << "--------------------------------------------------------"; + qDebug() + << "--------------------------------------------------------"; - if (true) { - auto rawProfiles = openDump("/home/user/dumps/binx"); - qDebug() << "raw x-profiles count is" << rawProfiles.size(); - // qDebug() << "height" << calibrationColumnHeight; + if (true) { + auto rawProfiles = openDump("/home/user/dumps/binx"); + qDebug() << "raw x-profiles count is" << rawProfiles.size(); + // qDebug() << "height" << calibrationColumnHeight; - auto filteredRawProfiles = filter(std::move(rawProfiles)); - qDebug() << "filtered x-profiles count is" - << filteredRawProfiles.count(); + auto filteredRawProfiles = filter(std::move(rawProfiles)); + qDebug() << "filtered x-profiles count is" + << filteredRawProfiles.count(); - ::calibrationTableX = calibrateX(std::move(filteredRawProfiles)); + ::calibrationTableX = calibrateX(std::move(filteredRawProfiles)); - // if (!dump( - // ::calibrationTableZ, - // "/home/user/dumps/binx.calibration_table" - // )) - // { - // qApp->exit(EXIT_FAILURE); - // } + // bool ok = calibrationTableToImage(::calibrationTableX) + // .save("/home/user/dumps/z/imageX.png"); - // bool ok = calibrationTableToImage(::calibrationTableX) - // .save("/home/user/dumps/z/imageX.png"); + // if (!ok) + // { + // qDebug() << "cannot save imageX.png"; + // exit(EXIT_FAILURE); + // } - // if (!ok) - // { - // qDebug() << "cannot save imageX.png"; - // exit(EXIT_FAILURE); - // } + interpolate(::calibrationTableX); - interpolate(::calibrationTableX); + if (!dump(::calibrationTableZ, + "/home/user/dumps/binx.calibration_table")) { + qApp->exit(EXIT_FAILURE); + } - // calibrationTableToImage(::calibrationTableX) - // .save("/home/user/dumps/z/imageX_interpolated.png"); + // calibrationTableToImage(::calibrationTableX) + // .save("/home/user/dumps/z/imageX_interpolated.png"); + } } } // exit(EXIT_SUCCESS); - if (!initLaser()) { - return EXIT_FAILURE; - } + // if (!initLaser()) { + // return EXIT_FAILURE; + // } // PrinterClient printerClient; @@ -310,6 +340,7 @@ int main( camera->printControls(); camera->newPixels.connect(&onNewPixels); + camera->newImage.connect(&onNewImage); if (!camera->startStream()) { cm->stop(); @@ -319,15 +350,19 @@ int main( QHttpServer qHttpServer; qHttpServer.route("/v1/sensor/image", [&]() { - std::cout << "http: image" << std::endl; + std::cout << "http: image" << std::endl << std::flush; + pgm_save(::img); std::lock_guard<std::mutex> lg(pgm_image_mtx); - // qDebug() << "image"; + qDebug() << "mutex locked"; + qDebug() << "image saved to array"; return QByteArray((const char*) pgm_image, pgm_image_size); }); qHttpServer.route("/v1/sensor/image2", [&]() { std::cout << "http: image2" << std::endl; + pgm_save(::img); + std::lock_guard<std::mutex> lg(pgm_image_mtx); - // qDebug() << "image"; + qDebug() << "image2"; return QByteArray((const char*) pgm_image, pgm_image_size); }); // qHttpServer.route("/v1/sensor/exposureTimeUs", [&]() { @@ -348,8 +383,9 @@ int main( QJsonObject json; json["pixels"] = pixels; json["encoderPosition"] = qint64{encoder.position()}; - json["measurementCounter"] = qint64{img.counters.measurementCounter}; - json["timestampUs"] = qint64(img.counters.timestampUs); + // FIXME: get prom pixels struct + json["measurementCounter"] = qint64{img->counters.measurementCounter}; + json["timestampUs"] = qint64(img->counters.timestampUs); const auto lines = pixelsToLines(::pixels); diff --git a/profile.cpp b/profile.cpp index 0c4967c..2c7b9a9 100644 --- a/profile.cpp +++ b/profile.cpp @@ -23,7 +23,7 @@ Profile::Profile( if (!done) { for (size_t i = 9471; i < 9472; i++) { - std::cout << "row #" << i << ": "; + std::cout << __func__ << ": row #" << i << ": "; for (size_t j = 0; j < 1280; ++j) { const auto& x = calibrationTableX->at(j).at(i); diff --git a/src/calibration.cpp b/src/calibration.cpp index 7fcdbcc..33423b3 100644 --- a/src/calibration.cpp +++ b/src/calibration.cpp @@ -82,9 +82,9 @@ void interpolate( [](auto& column) { interpolate(column); }); for (size_t i = 9471; i < 9472; i++) { - std::cout << "row #" << i << ": "; + std::cout << __func__ << ": row #" << i << ": "; - for (size_t j = 0; j < 1280; ++j) { + for (size_t j = 640 - 5; j < 640 + 5; ++j) { const auto& p = table->at(j).at(i); std::cout << p << ' '; } diff --git a/src/camera/innomakerov9281.cpp b/src/camera/innomakerov9281.cpp new file mode 100644 index 0000000..6d7aa4a --- /dev/null +++ b/src/camera/innomakerov9281.cpp @@ -0,0 +1,280 @@ +#include "innomakerov9281.h" + +#include <errno.h> +#include <fcntl.h> +#include <linux/videodev2.h> +#include <stdio.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <unistd.h> + +#include "constants.h" +// #include "rotaryencoder.h" + +#define LOGD(...) \ + do { \ + printf(__VA_ARGS__); \ + printf("\n"); \ + } while (0) + +#define DBG(fmt, args...) LOGD("%s:%d, " fmt, __FUNCTION__, __LINE__, ##args); + +extern uint64_t sum_elapsed_ns; +extern uint64_t corr_elapsed_ns; +extern uint64_t max_elapsed_ns; +extern uint64_t value_elapsed_ns; + +constexpr char videoDevice[] = "/dev/video0"; + +InnoMakerOV9281::InnoMakerOV9281() {} + +InnoMakerOV9281::~InnoMakerOV9281() +{ + int ret{-1}; + + for (int i = 0; i < BUFFER_COUNT; ++i) { + ret = munmap(video_buffer_ptr[i], img_size); + + if (ret < 0) { + DBG("Munmap failed!!."); + } + } + + // std::cout << __func__ << std::endl; + if (m_cam_fd >= 0) { + int ret = close(m_cam_fd); + + if (ret == -1) { + // std::cout << __func__ + // << ": cannot close camera: " << strerror(errno) + // << std::endl; + } + }; + + // std::cout << __func__ << ": success" << std::endl; +} + +bool InnoMakerOV9281::init() +{ + if (!openCam()) + return false; + + if (!selectCam()) + return false; + + if (!initCam()) + return false; + + return true; +} + +bool InnoMakerOV9281::setExposureTimeMs(int value) +{ + return setCamParam(V4L2_CID_EXPOSURE, value); +} + +bool InnoMakerOV9281::setGain(int value) +{ + return setCamParam(V4L2_CID_GAIN, value); +} + +bool InnoMakerOV9281::setCamParam(unsigned int v4l2controlId, int value) +{ + v4l2_control ctl{v4l2controlId, value}; + + int ret = ioctl(m_cam_fd, VIDIOC_S_CTRL, &ctl); + + if (ret < 0) { + fprintf(stderr, + "cannot set cam param: id - %d, error - '%s'\n", + v4l2controlId, + strerror(errno)); + + return false; + } + + return true; +} + +bool InnoMakerOV9281::openCam() +{ + m_cam_fd = open(videoDevice, O_RDWR); + + if (m_cam_fd < 0) { + fprintf(stderr, "cannot open cam '%s', error: '%s'\n", videoDevice, strerror(errno)); + return false; + } + + return true; +} + +bool InnoMakerOV9281::selectCam(int camIdx) +{ + int input = camIdx; + int ret = ioctl(m_cam_fd, VIDIOC_S_INPUT, &input); + + if (ret < 0) { + fprintf(stderr, "cannot select cam: idx - %d, error - '%s'\n", camIdx, strerror(errno)); + + return false; + } + + return true; +} + +bool InnoMakerOV9281::initCam() +{ + v4l2_format format; + memset(&format, 0, sizeof(v4l2_format)); + format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + format.fmt.pix.pixelformat = V4L2_PIX_FMT_GREY; + format.fmt.pix.width = img_width; + format.fmt.pix.height = img_height; + + int ret = ioctl(m_cam_fd, VIDIOC_TRY_FMT, &format); + + if (ret < 0) { + fprintf(stderr, "cannot try cam format: error - '%s'\n", strerror(errno)); + + return false; + } + + // TODO: remove this? + format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + ret = ioctl(m_cam_fd, VIDIOC_S_FMT, &format); + + if (ret < 0) { + fprintf(stderr, "cannot set cam format: error - '%s'\n", strerror(errno)); + + return false; + } + + struct v4l2_requestbuffers request; + request.count = BUFFER_COUNT; + request.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + request.memory = V4L2_MEMORY_MMAP; + ret = ioctl(m_cam_fd, VIDIOC_REQBUFS, &request); + + if (ret < 0) { + fprintf(stderr, "cannot set cam request buffers: ioctl error - '%s'\n", strerror(errno)); + + return false; + } + + if (request.count < BUFFER_COUNT) { + fprintf(stderr, "cannot set cam request buffers\n"); + + return false; + } + + struct v4l2_buffer buffer; + memset(&buffer, 0, sizeof(buffer)); + buffer.type = request.type; + buffer.memory = V4L2_MEMORY_MMAP; + + for (uint32_t i = 0; i < request.count; i++) { + buffer.index = i; + ret = ioctl(m_cam_fd, VIDIOC_QUERYBUF, &buffer); + + if (ret < 0) { + DBG("ioctl(VIDIOC_QUERYBUF) failed %d(%s)", errno, strerror(errno)); + return false; + } + + DBG("buffer.length: %d", buffer.length); + DBG("buffer.m.offset: %d", buffer.m.offset); + video_buffer_ptr[i] = (uint8_t *) + mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, m_cam_fd, buffer.m.offset); + if (video_buffer_ptr[i] == MAP_FAILED) { + DBG("mmap() failed %d(%s)", errno, strerror(errno)); + return false; + } + + buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buffer.memory = V4L2_MEMORY_MMAP; + buffer.index = i; + ret = ioctl(m_cam_fd, VIDIOC_QBUF, &buffer); + if (ret != 0) { + DBG("ioctl(VIDIOC_QBUF) failed %d(%s)", errno, strerror(errno)); + return false; + } + } + + int buffer_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + ret = ioctl(m_cam_fd, VIDIOC_STREAMON, &buffer_type); + if (ret != 0) { + DBG("ioctl(VIDIOC_STREAMON) failed %d(%s)", errno, strerror(errno)); + return false; + } + + DBG("cam init done."); + + return true; +} + +bool InnoMakerOV9281::getImage(Image &image) +{ + static struct timeval curr, prev; + static uint16_t counter = 0; + gettimeofday(&curr, NULL); + ++counter; + + double elapsedTime = (curr.tv_sec - prev.tv_sec) * 1000.0; // sec to ms + elapsedTime += (curr.tv_usec - prev.tv_usec) / 1000.0; // us to ms + + if (elapsedTime > 1000.) { + // fprintf(stderr, "fps: %d, sec: %d\n", counter, curr.tv_sec); + fprintf(stderr, + "sum: %d,\tcorr: %d,\tval: %d\n", + sum_elapsed_ns / 1000 / counter, + corr_elapsed_ns / 1000 / counter, + // max_elapsed_ns / 1000 / counter, + value_elapsed_ns / 1000 / counter); + sum_elapsed_ns = 0; + corr_elapsed_ns = 0; + max_elapsed_ns = 0; + value_elapsed_ns = 0; + + counter = 0; + prev = curr; + } + + int ret; + struct v4l2_buffer buffer; + + memset(&buffer, 0, sizeof(buffer)); + buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buffer.memory = V4L2_MEMORY_MMAP; + buffer.index = BUFFER_COUNT; + + ret = ioctl(m_cam_fd, VIDIOC_DQBUF, &buffer); + + if (ret != 0) { + DBG("ioctl(VIDIOC_DQBUF) failed %d(%s)", errno, strerror(errno)); + return false; + } + + if (buffer.index < 0 || buffer.index >= BUFFER_COUNT) { + DBG("invalid buffer index: %d", buffer.index); + return false; + } + + image.height = img_height; + image.width = img_width; + // TODO: fill + // image.counters.encoderPosition = RotaryEncoder::instance()->position(); + image.counters.measurementCounter = buffer.sequence; + image.counters.timestampUs = buffer.timestamp.tv_sec * 1000 * 1000 + buffer.timestamp.tv_usec; + memcpy(image.data, video_buffer_ptr[buffer.index], img_size); + + ret = ioctl(m_cam_fd, VIDIOC_QBUF, &buffer); + + if (ret != 0) { + DBG("ioctl(VIDIOC_QBUF) failed %d(%s)", errno, strerror(errno)); + return false; + } + + return true; +} diff --git a/src/camera/innomakerov9281.h b/src/camera/innomakerov9281.h new file mode 100644 index 0000000..bcafc12 --- /dev/null +++ b/src/camera/innomakerov9281.h @@ -0,0 +1,36 @@ +#pragma once + +#include <cstdint> + +#include "constants.h" +#include "image.h" + +class InnoMakerOV9281 +{ +public: + using buffer_t = std::array<uint8_t, img_size>; + +public: + InnoMakerOV9281(); + ~InnoMakerOV9281(); + +public: + bool init(); + + bool setExposureTimeMs(int value); + bool setGain(int value); + + bool getImage(Image &image); + +private: + bool setCamParam(unsigned int v4l2controlId, int value); + bool openCam(); + bool selectCam(int camIdx = 0); + bool initCam(); + +private: + int m_cam_fd{-1}; + static constexpr uint8_t BUFFER_COUNT{3}; + uint8_t *video_buffer_ptr[BUFFER_COUNT]; + // buffer_t m_buf; +}; diff --git a/src/camera/ov9281.cpp b/src/camera/ov9281.cpp index 4d393a0..012eab6 100644 --- a/src/camera/ov9281.cpp +++ b/src/camera/ov9281.cpp @@ -18,9 +18,15 @@ #include "rotaryencoder.h" #include "typedefs.h" +#include <QElapsedTimer> + +QElapsedTimer timer; +size_t fpsCounter{0}; + OV9281::OV9281(const std::shared_ptr<libcamera::Camera> &camera) : INIT_FIELD(camera) { + timer.start(); std::cout << __func__ << ":\tid: " << m_camera->id(); } @@ -54,7 +60,7 @@ bool OV9281::init() return false; } - m_config->orientation = libcamera::Orientation::Rotate90; + // m_config->orientation = libcamera::Orientation::Rotate90; libcamera::StreamConfiguration &streamConfig = m_config->at(0); @@ -135,6 +141,14 @@ bool OV9281::applyConfig() */ void OV9281::onRequestCompleted(libcamera::Request *completed_request) { + fpsCounter++; + + if (timer.elapsed() > 1000) { + std::cout << "fps: " << fpsCounter << std::endl; + timer.restart(); + fpsCounter = 0; + } + using namespace libcamera; if (completed_request->status() == Request::RequestCancelled) @@ -146,6 +160,7 @@ void OV9281::onRequestCompleted(libcamera::Request *completed_request) const auto &buffers = completed_request->buffers(); +#if 1 for (auto [stream, buffer] : buffers) { const auto &streamConfig = stream->configuration(); @@ -170,13 +185,12 @@ void OV9281::onRequestCompleted(libcamera::Request *completed_request) img->height = imageSize.height; memcpy(img->data, data, size); - img->dataSize = size; - img->stride = stride; + // img->dataSize = size; + // img->stride = stride; img->pixelFormat = pixelFormat; img->counters.measurementCounter = metadata.sequence; img->counters.timestampUs = metadata.timestamp / 1000; img->counters.encoderPosition = RotaryEncoder::instance()->position(); - img->rotate(); auto pixels = img->pixels(); @@ -185,12 +199,13 @@ void OV9281::onRequestCompleted(libcamera::Request *completed_request) if (!pixels) { std::cerr << "emit empty pixels" << std::endl; } + newImage.emit(img); newPixels.emit(pixels); #define emit #endif } } - +#endif const libcamera::ControlList &metadata = completed_request->metadata(); const ControlInfoMap &control_map = m_camera->controls(); // const ControlIdMap & ctrlIdMap = control_map.idmap(); @@ -207,11 +222,11 @@ void OV9281::onRequestCompleted(libcamera::Request *completed_request) static auto lastControls = completed_request->controls(); completed_request->reuse(Request::ReuseBuffers); - completed_request->controls().set(libcamera::controls::AeEnable, false); - completed_request->controls() - .set(libcamera::controls::draft ::NoiseReductionMode, - libcamera::controls::draft ::NoiseReductionModeEnum :: - NoiseReductionModeHighQuality); + // completed_request->controls().set(libcamera::controls::AeEnable, false); + // completed_request->controls() + // .set(libcamera::controls::draft ::NoiseReductionMode, + // libcamera::controls::draft ::NoiseReductionModeEnum :: + // NoiseReductionModeHighQuality); completed_request->controls().set(libcamera::controls::ExposureTime, m_exposureTime); diff --git a/src/camera/ov9281.h b/src/camera/ov9281.h index f70db2f..e989d96 100644 --- a/src/camera/ov9281.h +++ b/src/camera/ov9281.h @@ -37,6 +37,7 @@ public: // TODO: image->pixels in separate thread // TODO: respect sender/receiver threads libcamera::Signal<std::shared_ptr<Pixels>> newPixels; + libcamera::Signal<std::shared_ptr<Image>> newImage; private: explicit OV9281(const std::shared_ptr<libcamera::Camera> &camera); @@ -51,7 +52,7 @@ private: // constants private: - static inline constexpr auto pixelFormat{libcamera::formats::R16}; + static inline constexpr auto pixelFormat{libcamera::formats::R8}; static inline constexpr unsigned int bufferCount{2}; static inline constexpr size_t desiredFPS{144}; @@ -64,5 +65,5 @@ private: std::unique_ptr<libcamera::FrameBufferAllocator> m_allocator{nullptr}; // TODO: set exposureTime from outside - int32_t m_exposureTime{1000}; + int32_t m_exposureTime{100}; }; diff --git a/src/constants.h b/src/constants.h index 1c451ab..b7fd7bc 100644 --- a/src/constants.h +++ b/src/constants.h @@ -3,10 +3,13 @@ #include <cstddef> #include <cstdint> +// TODO: get rid of qstring #include <QString> constexpr size_t img_width = 1280; constexpr size_t img_height = 800; +constexpr size_t img_size = img_width * img_height; + constexpr uint32_t patternSize = 16; constexpr float hardcodedZRangeMm{175.f}; diff --git a/src/dumps.cpp b/src/dumps.cpp index 43a839c..0a85c1b 100644 --- a/src/dumps.cpp +++ b/src/dumps.cpp @@ -53,6 +53,7 @@ QList<Pixels> openDump( qDebug() << "create results array" << filenames.size(); auto resultOptionals = QScopedPointer( new QList<std::optional<Pixels>>(filenames.size())); + qDebug() << "created results array"; QElapsedTimer t; t.start(); diff --git a/src/image.cpp b/src/image.cpp index 7d1c824..ce814da 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -1,11 +1,20 @@ #include "image.h" +#include <QElapsedTimer> + #include "macro.h" #include "pixels.h" -float process_column(const uint16_t (&column)[]) +uint64_t sum_elapsed_ns = 0; +uint64_t corr_elapsed_ns = 0; +uint64_t max_elapsed_ns = 0; +uint64_t value_elapsed_ns = 0; + +float process_column(const uint8_t (&column)[]) { start_timer(process_column); + QElapsedTimer t; + t.start(); float result = std::numeric_limits<float>::quiet_NaN(); @@ -24,23 +33,20 @@ float process_column(const uint16_t (&column)[]) memset(correlation, 0, img_height * sizeof(correlation[0])); integralSum[0] = 0; - for (uint32_t i = 1; i < img_height; ++i) - { - // if (column[i] < 100) - // { - // column[i] = 0; - // } - - integralSum[i] = column[i] / 256 + integralSum[i - 1]; + for (uint32_t i = 1; i < img_height; ++i) { + integralSum[i] = column[i] + integralSum[i - 1]; } + sum_elapsed_ns += t.nsecsElapsed(); + t.restart(); for (uint32_t i = 0; i < correlationSize; ++i) - correlation[i + patternSize / 2] = column[i + patternSize / 2] / 256 * - (integralSum[i + patternOffset] - - integralSum[i]); + correlation[i + patternSize / 2] = column[i + patternSize / 2] + * (integralSum[i + patternOffset] - integralSum[i]); - for (uint32_t i = 3; i < img_height - 2; ++i) - { + corr_elapsed_ns += t.nsecsElapsed(); + t.restart(); + + for (uint32_t i = 3; i < img_height - 2; ++i) { const auto sum = correlation[i - 1] + correlation[i] + correlation[i + 1]; @@ -69,6 +75,9 @@ float process_column(const uint16_t (&column)[]) } } + value_elapsed_ns += t.nsecsElapsed(); + t.restart(); + result = (y2 != y1) ? (float(x1) - (float(y1) / (y2 - y1))) : std::numeric_limits<float>::quiet_NaN(); @@ -81,6 +90,8 @@ void Image::rotate() using namespace std; +#pragma omp parallel +#pragma omp for for (size_t i = 0; i < img_height; ++i) { for (size_t j = 0; j < img_width; ++j) @@ -99,8 +110,9 @@ std::shared_ptr<Pixels> Image::pixels() const start_timer(process_columns); - for (size_t i = 0; i < width; i++) - { +#pragma omp chunk +#pragma omp parallel for + for (size_t i = 0; i < img_width; i++) { result->pixels[i] = process_column(rotated_cw[i]); } diff --git a/src/image.h b/src/image.h index 2fff020..1ec1b93 100644 --- a/src/image.h +++ b/src/image.h @@ -9,10 +9,10 @@ struct Image { int width{0}; int height{0}; - uint16_t data[img_height][img_width] = {{0}}; - uint16_t rotated_cw[img_width][img_height] = {{0}}; - size_t dataSize{0}; - unsigned int stride{0}; + uint8_t data[img_height][img_width] = {{0}}; + uint8_t rotated_cw[img_width][img_height] = {{0}}; + // size_t dataSize{0}; + // unsigned int stride{0}; libcamera::PixelFormat pixelFormat{0}; Counters counters{}; |
