From cae794d6afbe2b6f1d92f64b729459202fb465a9 Mon Sep 17 00:00:00 2001 From: Nikolaus Demmel Date: Tue, 27 Aug 2019 15:19:33 +0000 Subject: [PATCH] Move all eigen serialization to basalt-headers. **Note:** Binary representation of eigen matrices has changed! --- include/basalt/io/dataset_io.h | 33 -- include/basalt/utils/image.h | 688 --------------------------------- test/CMakeLists.txt | 5 - test/src/test_image.cpp | 128 ------ thirdparty/basalt-headers | 2 +- 5 files changed, 1 insertion(+), 855 deletions(-) delete mode 100644 include/basalt/utils/image.h delete mode 100644 test/src/test_image.cpp diff --git a/include/basalt/io/dataset_io.h b/include/basalt/io/dataset_io.h index 9f4843f..839ff29 100644 --- a/include/basalt/io/dataset_io.h +++ b/include/basalt/io/dataset_io.h @@ -155,39 +155,6 @@ class DatasetIoFactory { namespace cereal { -template -static inline - typename std::enable_if<_Rows == Eigen::Dynamic || _Cols == Eigen::Dynamic, - void>::type - save(Archive &ar, const Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, - _MaxRows, _MaxCols> &matrix) { - const std::int32_t rows = static_cast(matrix.rows()); - const std::int32_t cols = static_cast(matrix.cols()); - ar(rows); - ar(cols); - ar(binary_data(matrix.data(), rows * cols * sizeof(_Scalar))); -}; - -template -static inline - typename std::enable_if<_Rows == Eigen::Dynamic || _Cols == Eigen::Dynamic, - void>::type - load(Archive &ar, - Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> - &matrix) { - std::int32_t rows; - std::int32_t cols; - ar(rows); - ar(cols); - - matrix.resize(rows, cols); - - ar(binary_data(matrix.data(), - static_cast(rows * cols * sizeof(_Scalar)))); -}; - template void serialize(Archive &archive, basalt::ManagedImage &m) { archive(m.w); diff --git a/include/basalt/utils/image.h b/include/basalt/utils/image.h deleted file mode 100644 index 2f6c55d..0000000 --- a/include/basalt/utils/image.h +++ /dev/null @@ -1,688 +0,0 @@ -/** -BSD 3-Clause License - -This file is part of the Basalt project. -https://gitlab.com/VladyslavUsenko/basalt.git - -Copyright (c) 2019, Vladyslav Usenko and Nikolaus Demmel. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -// This file is adapted from Pangolin. Original license: - -/* This file is part of the Pangolin Project. - * http://github.com/stevenlovegrove/Pangolin - * - * Copyright (c) 2011 Steven Lovegrove - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#pragma once - -#include - -#include - -// Renamed Pangoling defines to avoid clash -#define BASALT_HOST_DEVICE -#define BASALT_EXTENSION_IMAGE -#ifdef BASALT_ENABLE_BOUNDS_CHECKS -#define BASALT_BOUNDS_ASSERT(...) BASALT_ASSERT(##__VA_ARGS__) -#else -#define BASALT_BOUNDS_ASSERT(...) ((void)0) -#endif - -namespace basalt { - -template -struct CopyObject { - CopyObject(const T& obj) : obj(obj) {} - const T& obj; -}; - -inline void PitchedCopy(char* dst, unsigned int dst_pitch_bytes, - const char* src, unsigned int src_pitch_bytes, - unsigned int width_bytes, unsigned int height) { - if (dst_pitch_bytes == width_bytes && src_pitch_bytes == width_bytes) { - std::memcpy(dst, src, height * width_bytes); - } else { - for (unsigned int row = 0; row < height; ++row) { - std::memcpy(dst, src, width_bytes); - dst += dst_pitch_bytes; - src += src_pitch_bytes; - } - } -} - -template -struct Image { - inline Image() : pitch(0), ptr(0), w(0), h(0) {} - - inline Image(T* ptr, size_t w, size_t h, size_t pitch) - : pitch(pitch), ptr(ptr), w(w), h(h) {} - - BASALT_HOST_DEVICE inline size_t SizeBytes() const { return pitch * h; } - - BASALT_HOST_DEVICE inline size_t Area() const { return w * h; } - - BASALT_HOST_DEVICE inline bool IsValid() const { return ptr != 0; } - - BASALT_HOST_DEVICE inline bool IsContiguous() const { - return w * sizeof(T) == pitch; - } - - ////////////////////////////////////////////////////// - // Iterators - ////////////////////////////////////////////////////// - - BASALT_HOST_DEVICE inline T* begin() { return ptr; } - - BASALT_HOST_DEVICE inline T* end() { return RowPtr(h - 1) + w; } - - BASALT_HOST_DEVICE inline const T* begin() const { return ptr; } - - BASALT_HOST_DEVICE inline const T* end() const { return RowPtr(h - 1) + w; } - - BASALT_HOST_DEVICE inline size_t size() const { return w * h; } - - ////////////////////////////////////////////////////// - // Image transforms - ////////////////////////////////////////////////////// - - template - BASALT_HOST_DEVICE inline void Transform(UnaryOperation unary_op) { - BASALT_ASSERT(IsValid()); - - for (size_t y = 0; y < h; ++y) { - T* el = RowPtr(y); - const T* el_end = el + w; - for (; el != el_end; ++el) { - *el = unary_op(*el); - } - } - } - - BASALT_HOST_DEVICE inline void Fill(const T& val) { - Transform([&](const T&) { return val; }); - } - - BASALT_HOST_DEVICE inline void Replace(const T& oldval, const T& newval) { - Transform([&](const T& val) { return (val == oldval) ? newval : val; }); - } - - inline void Memset(unsigned char v = 0) { - BASALT_ASSERT(IsValid()); - if (IsContiguous()) { - std::memset((char*)ptr, v, pitch * h); - } else { - for (size_t y = 0; y < h; ++y) { - std::memset((char*)RowPtr(y), v, pitch); - } - } - } - - inline void CopyFrom(const Image& img) { - if (IsValid() && img.IsValid()) { - BASALT_ASSERT(w >= img.w && h >= img.h); - PitchedCopy((char*)ptr, pitch, (char*)img.ptr, img.pitch, - std::min(img.w, w) * sizeof(T), std::min(img.h, h)); - } else if (img.IsValid() != IsValid()) { - BASALT_ASSERT(false && "Cannot copy from / to an unasigned image."); - } - } - - ////////////////////////////////////////////////////// - // Reductions - ////////////////////////////////////////////////////// - - template - BASALT_HOST_DEVICE inline T Accumulate(const T init, - BinaryOperation binary_op) { - BASALT_ASSERT(IsValid()); - - T val = init; - for (size_t y = 0; y < h; ++y) { - T* el = RowPtr(y); - const T* el_end = el + w; - for (; el != el_end; ++el) { - val = binary_op(val, *el); - } - } - return val; - } - - std::pair MinMax() const { - BASALT_ASSERT(IsValid()); - - std::pair minmax(std::numeric_limits::max(), - std::numeric_limits::lowest()); - for (size_t r = 0; r < h; ++r) { - const T* ptr = RowPtr(r); - const T* end = ptr + w; - while (ptr != end) { - minmax.first = std::min(*ptr, minmax.first); - minmax.second = std::max(*ptr, minmax.second); - ++ptr; - } - } - return minmax; - } - - template - Tout Sum() const { - return Accumulate((T)0, - [](const T& lhs, const T& rhs) { return lhs + rhs; }); - } - - template - Tout Mean() const { - return Sum() / Area(); - } - - ////////////////////////////////////////////////////// - // Direct Pixel Access - ////////////////////////////////////////////////////// - - BASALT_HOST_DEVICE inline T* RowPtr(size_t y) { - return (T*)((unsigned char*)(ptr) + y * pitch); - } - - BASALT_HOST_DEVICE inline const T* RowPtr(size_t y) const { - return (T*)((unsigned char*)(ptr) + y * pitch); - } - - BASALT_HOST_DEVICE inline T& operator()(size_t x, size_t y) { - BASALT_BOUNDS_ASSERT(InBounds(x, y)); - return RowPtr(y)[x]; - } - - BASALT_HOST_DEVICE inline const T& operator()(size_t x, size_t y) const { - BASALT_BOUNDS_ASSERT(InBounds(x, y)); - return RowPtr(y)[x]; - } - - template - BASALT_HOST_DEVICE inline T& operator()(const TVec& p) { - BASALT_BOUNDS_ASSERT(InBounds(p[0], p[1])); - return RowPtr(p[1])[p[0]]; - } - - template - BASALT_HOST_DEVICE inline const T& operator()(const TVec& p) const { - BASALT_BOUNDS_ASSERT(InBounds(p[0], p[1])); - return RowPtr(p[1])[p[0]]; - } - - BASALT_HOST_DEVICE inline T& operator[](size_t ix) { - BASALT_BOUNDS_ASSERT(InImage(ptr + ix)); - return ptr[ix]; - } - - BASALT_HOST_DEVICE inline const T& operator[](size_t ix) const { - BASALT_BOUNDS_ASSERT(InImage(ptr + ix)); - return ptr[ix]; - } - - ////////////////////////////////////////////////////// - // Interpolated Pixel Access - ////////////////////////////////////////////////////// - - template - inline S interp(const Eigen::Matrix& p) const { - return interp(p[0], p[1]); - } - - template - inline Eigen::Matrix interpGrad( - const Eigen::Matrix& p) const { - return interpGrad(p[0], p[1]); - } - - template - inline float interp(S x, S y) const { - int ix = x; - int iy = y; - - S dx = x - ix; - S dy = y - iy; - - S ddx = 1.0f - dx; - S ddy = 1.0f - dy; - - return ddx * ddy * (*this)(ix, iy) + ddx * dy * (*this)(ix, iy + 1) + - dx * ddy * (*this)(ix + 1, iy) + dx * dy * (*this)(ix + 1, iy + 1); - } - - template - inline Eigen::Matrix interpGrad(S x, S y) const { - int ix = x; - int iy = y; - - S dx = x - ix; - S dy = y - iy; - - S ddx = 1.0f - dx; - S ddy = 1.0f - dy; - - Eigen::Matrix res; - - const T& px0y0 = (*this)(ix, iy); - const T& px1y0 = (*this)(ix + 1, iy); - const T& px0y1 = (*this)(ix, iy + 1); - const T& px1y1 = (*this)(ix + 1, iy + 1); - - res[0] = ddx * ddy * px0y0 + ddx * dy * px0y1 + dx * ddy * px1y0 + - dx * dy * px1y1; - - const T& pxm1y0 = (*this)(ix - 1, iy); - const T& pxm1y1 = (*this)(ix - 1, iy + 1); - - S res_mx = ddx * ddy * pxm1y0 + ddx * dy * pxm1y1 + dx * ddy * px0y0 + - dx * dy * px0y1; - - const T& px2y0 = (*this)(ix + 2, iy); - const T& px2y1 = (*this)(ix + 2, iy + 1); - - S res_px = ddx * ddy * px1y0 + ddx * dy * px1y1 + dx * ddy * px2y0 + - dx * dy * px2y1; - - res[1] = 0.5 * (res_px - res_mx); - - const T& px0ym1 = (*this)(ix, iy - 1); - const T& px1ym1 = (*this)(ix + 1, iy - 1); - - S res_my = ddx * ddy * px0ym1 + ddx * dy * px0y0 + dx * ddy * px1ym1 + - dx * dy * px1y0; - - const T& px0y2 = (*this)(ix, iy + 2); - const T& px1y2 = (*this)(ix + 1, iy + 2); - - S res_py = ddx * ddy * px0y1 + ddx * dy * px0y2 + dx * ddy * px1y1 + - dx * dy * px1y2; - - res[2] = 0.5 * (res_py - res_my); - - return res; - } - - ////////////////////////////////////////////////////// - // Bounds Checking - ////////////////////////////////////////////////////// - - BASALT_HOST_DEVICE - bool InImage(const T* ptest) const { - return ptr <= ptest && ptest < RowPtr(h); - } - - BASALT_HOST_DEVICE inline bool InBounds(int x, int y) const { - return 0 <= x && x < (int)w && 0 <= y && y < (int)h; - } - - BASALT_HOST_DEVICE inline bool InBounds(float x, float y, - float border) const { - return border <= x && x < (w - border) && border <= y && y < (h - border); - } - - template - BASALT_HOST_DEVICE inline bool InBounds( - const TVec& p, const TBorder border = (TBorder)0) const { - return border <= p[0] && p[0] < ((int)w - border) && border <= p[1] && - p[1] < ((int)h - border); - } - - ////////////////////////////////////////////////////// - // Obtain slices / subimages - ////////////////////////////////////////////////////// - - BASALT_HOST_DEVICE inline const Image SubImage(size_t x, size_t y, - size_t width, - size_t height) const { - BASALT_ASSERT((x + width) <= w && (y + height) <= h); - return Image(RowPtr(y) + x, width, height, pitch); - } - - BASALT_HOST_DEVICE inline Image SubImage(size_t x, size_t y, size_t width, - size_t height) { - BASALT_ASSERT((x + width) <= w && (y + height) <= h); - return Image(RowPtr(y) + x, width, height, pitch); - } - - BASALT_HOST_DEVICE inline Image Row(int y) const { - return SubImage(0, y, w, 1); - } - - BASALT_HOST_DEVICE inline Image Col(int x) const { - return SubImage(x, 0, 1, h); - } - - ////////////////////////////////////////////////////// - // Data mangling - ////////////////////////////////////////////////////// - - template - BASALT_HOST_DEVICE inline Image Reinterpret() const { - BASALT_ASSERT_STREAM(sizeof(TRecast) == sizeof(T), - "sizeof(TRecast) must match sizeof(T): " - << sizeof(TRecast) << " != " << sizeof(T)); - return UnsafeReinterpret(); - } - - template - BASALT_HOST_DEVICE inline Image UnsafeReinterpret() const { - return Image((TRecast*)ptr, w, h, pitch); - } - - ////////////////////////////////////////////////////// - // Deprecated methods - ////////////////////////////////////////////////////// - - // PANGOLIN_DEPRECATED inline - Image(size_t w, size_t h, size_t pitch, T* ptr) - : pitch(pitch), ptr(ptr), w(w), h(h) {} - - // Use RAII/move aware pangolin::ManagedImage instead - // PANGOLIN_DEPRECATED inline - void Dealloc() { - if (ptr) { - ::operator delete(ptr); - ptr = nullptr; - } - } - - // Use RAII/move aware pangolin::ManagedImage instead - // PANGOLIN_DEPRECATED inline - void Alloc(size_t w, size_t h, size_t pitch) { - Dealloc(); - this->w = w; - this->h = h; - this->pitch = pitch; - this->ptr = (T*)::operator new(h* pitch); - } - - ////////////////////////////////////////////////////// - // Data members - ////////////////////////////////////////////////////// - - size_t pitch; - T* ptr; - size_t w; - size_t h; - - BASALT_EXTENSION_IMAGE -}; - -template -using DefaultImageAllocator = std::allocator; - -// Image that manages it's own memory, storing a strong pointer to it's memory -template > -class ManagedImage : public Image { - public: - typedef std::shared_ptr> Ptr; - - // Destructor - inline ~ManagedImage() { Deallocate(); } - - // Null image - inline ManagedImage() {} - - // Row image - inline ManagedImage(size_t w) - : Image(Allocator().allocate(w), w, 1, w * sizeof(T)) {} - - inline ManagedImage(size_t w, size_t h) - : Image(Allocator().allocate(w * h), w, h, w * sizeof(T)) {} - - inline ManagedImage(size_t w, size_t h, size_t pitch_bytes) - : Image(Allocator().allocate((h * pitch_bytes) / sizeof(T) + 1), w, h, - pitch_bytes) {} - - // Not copy constructable - inline ManagedImage(const ManagedImage& other) = delete; - - // Move constructor - inline ManagedImage(ManagedImage&& img) { - *this = std::move(img); - } - - // Move asignment - inline void operator=(ManagedImage&& img) { - Deallocate(); - Image::pitch = img.pitch; - Image::ptr = img.ptr; - Image::w = img.w; - Image::h = img.h; - img.ptr = nullptr; - } - - // Explicit copy constructor - template - ManagedImage(const CopyObject& other) { - CopyFrom(other.obj); - } - - // Explicit copy assignment - template - void operator=(const CopyObject& other) { - CopyFrom(other.obj); - } - - inline void Swap(ManagedImage& img) { - std::swap(img.pitch, Image::pitch); - std::swap(img.ptr, Image::ptr); - std::swap(img.w, Image::w); - std::swap(img.h, Image::h); - } - - inline void CopyFrom(const Image& img) { - if (!Image::IsValid() || Image::w != img.w || Image::h != img.h) { - Reinitialise(img.w, img.h); - } - Image::CopyFrom(img); - } - - inline void Reinitialise(size_t w, size_t h) { - if (!Image::ptr || Image::w != w || Image::h != h) { - *this = ManagedImage(w, h); - } - } - - inline void Reinitialise(size_t w, size_t h, size_t pitch) { - if (!Image::ptr || Image::w != w || Image::h != h || - Image::pitch != pitch) { - *this = ManagedImage(w, h, pitch); - } - } - - inline void Deallocate() { - if (Image::ptr) { - Allocator().deallocate(Image::ptr, - (Image::h * Image::pitch) / sizeof(T)); - Image::ptr = nullptr; - } - } - - // Move asignment - template - inline void OwnAndReinterpret(ManagedImage&& img) { - Deallocate(); - Image::pitch = img.pitch; - Image::ptr = (T*)img.ptr; - Image::w = img.w; - Image::h = img.h; - img.ptr = nullptr; - } - - template - inline void ConvertFrom(const ManagedImage& img) { - Reinitialise(img.w, img.h); - - for (size_t j = 0; j < img.h; j++) { - T* this_row = this->RowPtr(j); - const T1* other_row = img.RowPtr(j); - for (size_t i = 0; i < img.w; i++) { - this_row[i] = T(other_row[i]); - } - } - } - - inline void operator-=(const ManagedImage& img) { - for (size_t j = 0; j < img.h; j++) { - T* this_row = this->RowPtr(j); - const T* other_row = img.RowPtr(j); - for (size_t i = 0; i < img.w; i++) { - this_row[i] -= other_row[i]; - } - } - } -}; - -template > -class ManagedImagePyr { - public: - inline ManagedImagePyr() {} - - inline ManagedImagePyr(ManagedImage& other, size_t num_levels) { - setFromImage(other, num_levels); - } - - inline void setFromImage(const ManagedImage& other, size_t num_levels) { - orig_w = other.w; - image.Reinitialise(other.w + other.w / 2, other.h); - image.Fill(0); - lvl_internal(0).CopyFrom(other); - - for (size_t i = 0; i < num_levels; i++) { - const Image l = lvl(i); - Image lp1 = lvl_internal(i + 1); - subsample(l, lp1); - } - } - - static inline int border101(int x, int h) { - return h - 1 - std::abs(h - 1 - x); - } - - static void subsample(const Image& img, Image& img_sub) { - static_assert(std::is_same::value || - std::is_same::value); - - constexpr int kernel[5] = {1, 4, 6, 4, 1}; - - // accumulator - ManagedImage tmp(img_sub.h, img.w); - - // Vertical convolution - { - for (int r = 0; r < int(img_sub.h); r++) { - const T* row_m2 = img.RowPtr(std::abs(2 * r - 2)); - const T* row_m1 = img.RowPtr(std::abs(2 * r - 1)); - const T* row = img.RowPtr(2 * r); - const T* row_p1 = img.RowPtr(border101(2 * r + 1, img.h)); - const T* row_p2 = img.RowPtr(border101(2 * r + 2, img.h)); - - for (int c = 0; c < int(img.w); c++) { - tmp(r, c) = kernel[0] * int(row_m2[c]) + kernel[1] * int(row_m1[c]) + - kernel[2] * int(row[c]) + kernel[3] * int(row_p1[c]) + - kernel[4] * int(row_p2[c]); - } - } - } - - // Horizontal convolution - { - for (int c = 0; c < int(img_sub.w); c++) { - const int* row_m2 = tmp.RowPtr(std::abs(2 * c - 2)); - const int* row_m1 = tmp.RowPtr(std::abs(2 * c - 1)); - const int* row = tmp.RowPtr(2 * c); - const int* row_p1 = tmp.RowPtr(border101(2 * c + 1, tmp.h)); - const int* row_p2 = tmp.RowPtr(border101(2 * c + 2, tmp.h)); - - for (int r = 0; r < int(tmp.w); r++) { - int val_int = kernel[0] * row_m2[r] + kernel[1] * row_m1[r] + - kernel[2] * row[r] + kernel[3] * row_p1[r] + - kernel[4] * row_p2[r]; - T val = ((val_int + (1 << 7)) >> 8); - img_sub(c, r) = val; - } - } - } - } - - inline const Image lvl(size_t lvl) const { - size_t x = (lvl == 0) ? 0 : orig_w; - size_t y = (lvl <= 1) ? 0 : (image.h - (image.h >> (lvl - 1))); - size_t width = (orig_w >> lvl); - size_t height = (image.h >> lvl); - - return image.SubImage(x, y, width, height); - } - - template - inline Eigen::Matrix lvl_offset(size_t lvl) { - size_t x = (lvl == 0) ? 0 : orig_w; - size_t y = (lvl <= 1) ? 0 : (image.h - (image.h >> (lvl - 1))); - - return Eigen::Matrix(x, y); - } - - private: - inline Image lvl_internal(size_t lvl) { - size_t x = (lvl == 0) ? 0 : orig_w; - size_t y = (lvl <= 1) ? 0 : (image.h - (image.h >> (lvl - 1))); - size_t width = (orig_w >> lvl); - size_t height = (image.h >> lvl); - - return image.SubImage(x, y, width, height); - } - - size_t orig_w; - ManagedImage image; -}; - -} // namespace basalt diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e42737a..135b737 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,9 +5,6 @@ cmake_minimum_required(VERSION 3.10) include_directories(../thirdparty/basalt-headers/test/include) -add_executable(test_image src/test_image.cpp) -target_link_libraries(test_image gtest gtest_main basalt) - add_executable(test_spline_opt src/test_spline_opt.cpp) target_link_libraries(test_spline_opt gtest gtest_main basalt) @@ -22,12 +19,10 @@ enable_testing() include(GoogleTest) -#gtest_discover_tests(test_image DISCOVERY_TIMEOUT 60) #gtest_discover_tests(test_spline_opt DISCOVERY_TIMEOUT 60) #gtest_discover_tests(test_vio DISCOVERY_TIMEOUT 60) #gtest_discover_tests(test_nfr DISCOVERY_TIMEOUT 60) -gtest_add_tests(TARGET test_image AUTO) gtest_add_tests(TARGET test_spline_opt AUTO) gtest_add_tests(TARGET test_vio AUTO) gtest_add_tests(TARGET test_nfr AUTO) diff --git a/test/src/test_image.cpp b/test/src/test_image.cpp deleted file mode 100644 index e1f1375..0000000 --- a/test/src/test_image.cpp +++ /dev/null @@ -1,128 +0,0 @@ - -#include - -#include - -#include "gtest/gtest.h" -#include "test_utils.h" - -void setImageData(uint16_t *imageArray, int size) { - double norm = RAND_MAX; - norm /= (double)std::numeric_limits::max(); - - for (int i = 0; i < size; i++) { - imageArray[i] = (unsigned char)(rand() / norm); - } -} - -TEST(Pattern, ImageInterp) { - Eigen::Vector2d offset(231.234242, 123.23424); - - basalt::ManagedImage img(640, 480); - setImageData(img.ptr, img.size()); - - Eigen::Vector3d vg = img.interpGrad(offset); - - Eigen::Matrix J = vg.tail<2>(); - - // std::cerr << "vg\n" << vg << std::endl; - - test_jacobian( - "d_val_d_p", J, - [&](const Eigen::Vector2d &x) { - Eigen::Matrix res; - Eigen::Vector2d p1 = offset + x; - res[0] = img.interpGrad(p1)[0]; - return res; - }, - Eigen::Vector2d::Zero(), 1.0); -} - -TEST(Image, ImageInterpolate) { - Eigen::Vector2i offset(231, 123); - - basalt::ManagedImage img(640, 480); - setImageData(img.ptr, img.size()); - - double eps = 1e-12; - double threshold = 1e-8; - - { - Eigen::Vector2i pi = offset; - Eigen::Vector2d pd = pi.cast() + Eigen::Vector2d(eps, eps); - - uint16_t val1 = img(pi); - double val2 = img.interp(pd); - double val3 = img.interpGrad(pd)[0]; - - EXPECT_LE(std::abs(val2 - val1), threshold); - EXPECT_FLOAT_EQ(val2, val3); - } - - { - Eigen::Vector2i pi = offset; - Eigen::Vector2d pd = pi.cast() + Eigen::Vector2d(eps, eps); - - uint16_t val1 = img(pi); - double val2 = img.interp(pd); - double val3 = img.interpGrad(pd)[0]; - - EXPECT_LE(std::abs(val2 - val1), threshold); - EXPECT_FLOAT_EQ(val2, val3); - } - - { - Eigen::Vector2i pi = offset + Eigen::Vector2i(1, 0); - Eigen::Vector2d pd = pi.cast() + Eigen::Vector2d(-eps, eps); - - uint16_t val1 = img(pi); - double val2 = img.interp(pd); - double val3 = img.interpGrad(pd)[0]; - - EXPECT_LE(std::abs(val2 - val1), threshold); - EXPECT_FLOAT_EQ(val2, val3); - } - - { - Eigen::Vector2i pi = offset + Eigen::Vector2i(0, 1); - Eigen::Vector2d pd = pi.cast() + Eigen::Vector2d(eps, -eps); - - uint16_t val1 = img(pi); - double val2 = img.interp(pd); - double val3 = img.interpGrad(pd)[0]; - - EXPECT_LE(std::abs(val2 - val1), threshold); - EXPECT_FLOAT_EQ(val2, val3); - } - - { - Eigen::Vector2i pi = offset + Eigen::Vector2i(1, 1); - Eigen::Vector2d pd = pi.cast() + Eigen::Vector2d(-eps, -eps); - - uint16_t val1 = img(pi); - double val2 = img.interp(pd); - double val3 = img.interpGrad(pd)[0]; - - EXPECT_LE(std::abs(val2 - val1), threshold); - EXPECT_FLOAT_EQ(val2, val3); - } -} - -TEST(Image, ImageInterpolateGrad) { - Eigen::Vector2i offset(231, 123); - - basalt::ManagedImage img(640, 480); - setImageData(img.ptr, img.size()); - - Eigen::Vector2d pd = offset.cast() + Eigen::Vector2d(0.4, 0.34345); - - Eigen::Vector3d valGrad = img.interpGrad(pd); - Eigen::Matrix J = valGrad.tail<2>(); - - test_jacobian( - "d_res_d_x", J, - [&](const Eigen::Vector2d &x) { - return Eigen::Matrix(img.interp(pd + x)); - }, - Eigen::Vector2d::Zero(), 1); -} diff --git a/thirdparty/basalt-headers b/thirdparty/basalt-headers index c339ea7..792c0e9 160000 --- a/thirdparty/basalt-headers +++ b/thirdparty/basalt-headers @@ -1 +1 @@ -Subproject commit c339ea747a29881271cfcbc559937b81dcf76324 +Subproject commit 792c0e9b5a2ccffac60c80f29905cfde145d4042