summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt32
-rw-r--r--httpservice.h2
-rw-r--r--imagealgos.cpp339
-rw-r--r--imagealgos.h10
-rw-r--r--macro.h12
-rw-r--r--main.cpp186
-rw-r--r--profile.cpp2
-rw-r--r--src/calibration.cpp4
-rw-r--r--src/camera/innomakerov9281.cpp280
-rw-r--r--src/camera/innomakerov9281.h36
-rw-r--r--src/camera/ov9281.cpp35
-rw-r--r--src/camera/ov9281.h5
-rw-r--r--src/constants.h3
-rw-r--r--src/dumps.cpp1
-rw-r--r--src/image.cpp44
-rw-r--r--src/image.h8
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);
diff --git a/macro.h b/macro.h
index aeca79d..b270723 100644
--- a/macro.h
+++ b/macro.h
@@ -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)
diff --git a/main.cpp b/main.cpp
index 341693e..481d6f1 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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{};