start developing unit tests for frames.

This commit is contained in:
Jordan 2024-03-22 09:07:04 -07:00
parent d85c25b21e
commit 7d225729ec
8 changed files with 260 additions and 73 deletions

View File

@ -102,6 +102,11 @@ add_executable(
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_image.cxx
)
add_executable(
test_frame
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_image.cxx
)
target_link_libraries(
test_image
cunit
@ -116,6 +121,20 @@ target_link_libraries(
OpenMVG::openMVG_exif
)
target_link_libraries(
test_frame
cunit
cwalk
${LIBDART_OPENMVG}
png
OpenMVG::openMVG_image
OpenMVG::openMVG_numeric
OpenMVG::openMVG_features
OpenMVG::openMVG_sfm
OpenMVG::openMVG_features
OpenMVG::openMVG_exif
)
target_include_directories(
test_image
PRIVATE
@ -124,6 +143,14 @@ target_include_directories(
${CEREAL_INCLUDE_DIR}
)
target_include_directories(
test_frame
PRIVATE
${LIBDART_OPENMVG_INCLUDE_DIRS}
${OpenMVG_INCLUDE_DIRS}/src
${CEREAL_INCLUDE_DIR}
)
set_target_properties(test_image
PROPERTIES
LINKER_LANGUAGE CXX
@ -134,4 +161,9 @@ add_test (
COMMAND test_image
)
add_test (
NAME test_frame
COMMAND test_frame
)
target_compile_definitions(${LIBDART_OPENMVG} PUBLIC DART_SHARED_LIB)

@ -1 +1 @@
Subproject commit 7fd19fc22419a35481d39d2946f77e1dc00df37c
Subproject commit aff37dd005f85b3589aa50caca13b74ca7bd57e4

View File

@ -90,6 +90,70 @@ openMVG::image::Image<u_char> DartOpenMvg::imageFromFrame(const CFrame *frame)
return openMVG::image::Image<uint8_t>(eigenMatrix);
}
DartOpenMvg::Frames::Frames(openMVG::sfm::Bundle_Adjustment_Ceres::BA_Ceres_options &options)
{
mAdjustment = openMVG::sfm::Bundle_Adjustment_Ceres(options);
}
void DartOpenMvg::Frames::computeMatches()
{
#ifdef OPENMVG_USE_OPENMP
OPENMVG_LOG_INFO << "Using the OPENMP thread interface";
const bool b_multithreaded_pair_search = (eMatcherType_ == CASCADE_HASHING_L2);
// -> set to true for CASCADE_HASHING_L2, since OpenMP instructions are not used in this matcher
#endif
// Match the pairs as a sequence
// Within openMvg::matching_image_collection::Matcher
// they matcha gainst *ALL* images. However, since we know the order of the
// image sequences (video frames), we'll stick to the sequence order.
for (size_t i = 0; i < this->size() - 1; ++i)
{
const Frame &frame1 = this->at(i);
const Frame &frame2 = this->at(i + 1);
auto *regions1 = frame1.mRegions.get();
auto *regions2 = frame2.mRegions.get();
// Initialize the matching interface
const std::unique_ptr<openMVG::matching::RegionsMatcher> matcher =
openMVG::matching::RegionMatcherFactory(openMVG::matching::EMatcherType::HNSW_L2, *regions1);
if (!matcher)
continue;
#ifdef OPENMVG_USE_OPENMP
#pragma omp parallel for schedule(dynamic) if (b_multithreaded_pair_search)
#endif
openMVG::matching::IndMatches vec_putative_matches;
matcher->MatchDistanceRatio(0.5, *regions2, vec_putative_matches);
if (vec_putative_matches.empty())
{
return;
}
mFeatureMap[std::make_pair(i, i + 1)] = vec_putative_matches;
}
};
void DartOpenMvg::Frames::buildTracks()
{
openMVG::tracks::TracksBuilder trackBuilder;
openMVG::matching::PairWiseMatches matches;
trackBuilder.Build(mFeatureMap);
trackBuilder.Filter();
trackBuilder.ExportToSTL(mTracks);
}
void DartOpenMvg::Frames::adjust()
{
const openMVG::sfm::Optimize_Options ba_refine_options(openMVG::cameras::Intrinsic_Parameter_Type::ADJUST_ALL,
openMVG::sfm::Extrinsic_Parameter_Type::ADJUST_ALL, // Adjust camera motion
openMVG::sfm::Structure_Parameter_Type::ADJUST_ALL, // Adjust scene structure
openMVG::sfm::Control_Point_Parameter(),
false);
mAdjustment.Adjust(mSfmData, ba_refine_options);
}
void DartOpenMvg::Frame::calculateFeatures()
{
using namespace openMVG::image;
@ -99,30 +163,15 @@ void DartOpenMvg::Frame::calculateFeatures()
mRegions = desc.Describe(image);
}
openMVG::image::Image<u_char> DartOpenMvg::Frame::getMvgImage() {
void DartOpenMvg::Frames::resection() {
// openMVG::tracks::TracksUtilsMap::GetFeatIndexPerViewAndTrackId(
// mTracks;
// )
}
openMVG::image::Image<u_char> DartOpenMvg::Frame::getMvgImage()
{
return imageFromFrame(this->cFrame);
}
void DartOpenMvg::Frames::computeMatches()
{
using namespace openMVG::matching;
using namespace openMVG::matching_image_collection;
using namespace openMVG::sfm;
using namespace openMVG::image;
Matcher *matcher = nullptr;
Regions_Provider provider = Regions_Provider();
matcher = new Matcher_Regions(0.8f, CASCADE_HASHING_L2);
openMVG::Pair_Set pairs = openMVG::Pair_Set();
Image im1 = this->at(0).getMvgImage();
Image im2 = this->at(1).getMvgImage();
auto pair = openMVG::Pair(0, 1);
pairs.insert(pair);
PairWiseMatches map_punitive_matches;
// matcher->Match(provider, pairs, map_punitive_matches, NULL);
#endif // __cplusplus

View File

@ -8,6 +8,8 @@
#include <openMVG/matching_image_collection/Matcher_Regions.hpp>
#include <openMVG/matching_image_collection/Pair_Builder.hpp>
#include <openMVG/sfm/pipelines/sfm_regions_provider.hpp>
#include <openMVG/sfm/pipelines/sfm_engine.hpp>
#include <openMVG/sfm/sfm_data_BA_ceres.hpp>
#include <openMVG/features/feature.hpp>
#include <openMVG/features/sift/octaver.hpp>
#include <openMVG/features/sift/SIFT_Anatomy_Image_Describer.hpp>
@ -17,6 +19,19 @@
#include <openMVG/image/image_container.hpp>
#include <openMVG/image/image_io.hpp>
#include <openMVG/numeric/numeric.h>
#include <openMVG/tracks/tracks.hpp>
#include <string>
#include <vector>
#include <memory>
#include <openMVG/matching/indMatch.hpp>
#include <openMVG/matching_image_collection/Matcher_Regions.hpp>
#include <openMVG/matching_image_collection/Matcher.hpp>
#include <openMVG/matching/regions_matcher.hpp>
#include <openMVG/sfm/pipelines/sfm_regions_provider.hpp>
#include <openMVG/system/progressinterface.hpp>
#include <openMVG/system/logger.hpp>
#include <iostream>
#include <map>
#include <utility>
@ -44,24 +59,19 @@ namespace DartOpenMvg
{
openMVG::image::Image<uint8_t> imageFromFrame(const Frame *);
class InMemoryMatcherRegions : public openMVG::matching_image_collection::Matcher {
void Match(
const Pair_Set &,
PariWiseMatchesContainer &,
) const override;
};
class Frame
{
protected:
const CFrame *cFrame;
std::stringstream mStream;
int mW;
int mH;
int mDepth;
std::unique_ptr<openMVG::features::Regions> mRegions;
public:
// TODO make this private
const CFrame *cFrame;
// TODO make this private
std::unique_ptr<openMVG::features::Regions> mRegions;
Frame(const _Frame *f) : mW(f->w), mH(f->h), mDepth(f->depth)
{
cFrame = f;
@ -70,20 +80,28 @@ namespace DartOpenMvg
read_buffer(f->stream, &buffer_data, &len);
mStream = std::stringstream(std::string((char *)buffer_data));
}
openMVG::image::Image<u_char> DartOpenMvg::Frame::getMvgImage();
openMVG::image::Image<u_char> getMvgImage();
void calculateFeatures();
};
typedef std::pair<Frame, Frame> FrameMatchKey;
typedef std::map<FrameMatchKey, openMVG::matching::IndMatches> FrameFeatureMatch;
typedef std::pair<const Frame &, const Frame &> FrameMatchKey;
typedef std::map<std::pair<size_t, size_t>, openMVG::matching::IndMatches> FrameFeatureMatch;
class Frames : std::vector<Frame>
class Frames : protected std::vector<Frame>
{
protected:
FrameFeatureMatch mFeatureMap;
openMVG::matching::PairWiseMatches mFeatureMap;
openMVG::tracks::STLMAPTracks mTracks;
openMVG::sfm::SfM_Data mSfmData;
openMVG::sfm::Bundle_Adjustment_Ceres mAdjustment;
public:
Frames(openMVG::sfm::Bundle_Adjustment_Ceres::BA_Ceres_options &);
void computeMatches();
void buildTracks();
void adjust ();
void resection ();
void resectionAll ();
};
}
#endif
@ -94,4 +112,6 @@ Frame *new_frame_from_handle(FILE *, int, int, int);
_FFI_PLUGIN
Frame *new_frame_from_data(const uint8_t *, const size_t, int, int, int);
void frame_cleanup(Frame **);
#endif // __FRAME_H

85
src/tests/test_frame.cxx Normal file
View File

@ -0,0 +1,85 @@
#include <archives/binary.hpp>
#include <CUnit/Basic.h>
#include "../image.h"
#include "../streamingview.hpp"
#include "../util.h"
#include <cwalk.h>
#ifdef __cplusplus
#include <iostream>
#endif // __cplusplus
#define STRLEN 2048
FILE *imageHandle = NULL;
char frame1Path[STRLEN];
#define HERE __FILE__
int setUp(void)
{
char framesDir[STRLEN];
size_t length;
cwk_path_get_dirname(HERE, &length); // archimedes_mobile_lib/src/tests
cwk_path_join(HERE, "../../../assets/test/frames", framesDir, STRLEN);
cwk_path_join(framesDir, "0001.png", frame1Path, STRLEN);
printf("Opening file %s\n", frame1Path);
return 0;
}
Frame *get_frame() {
imageHandle = fopen(frame1Path, "rw+");
Frame *f = new_frame_from_handle(
imageHandle,
768,
768,
64);
return f;
}
void destroy_frame() {
frame_
}
int tearDown(void)
{
if (imageHandle)
{
fclose(imageHandle);
}
return 0;
}
void test_calculate_fetures
int main()
{
CU_pSuite pSuite = NULL;
/* initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry())
return CU_get_error();
/* add a suite to the registry */
pSuite = CU_add_suite("ImageSuite", setUp, tearDown);
if (NULL == pSuite)
{
CU_cleanup_registry();
return CU_get_error();
}
/* add the tests to the suite */
if ((NULL == CU_add_test(pSuite, "frame can be created", test_create_frame)) ||
(NULL == CU_add_test(pSuite, "frame can be created from data", test_frame_from_data)) ||
(NULL == CU_add_test(pSuite, "data can be retrieved from frame", test_archimedes_get_data)) ||
(NULL == CU_add_test(pSuite, "Streaming view can read & write data", test_archimedes_streamed_view)))
{
CU_cleanup_registry();
return CU_get_error();
}
/* Run all tests using the CUnit Basic interface */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
CU_cleanup_registry();
return CU_get_error();
}

View File

@ -2,6 +2,7 @@
#include <CUnit/Basic.h>
#include "../image.h"
#include "../streamingview.hpp"
#include "../util.h"
#include <cwalk.h>
#ifdef __cplusplus
#include <iostream>
@ -12,41 +13,6 @@
FILE *imageHandle = NULL;
char frame1Path[STRLEN];
/*
* Read the contents of a file into an array
* path: path to the file
* contents: array we'll write to that contains the contents of the file.
*/
size_t read_file(const char *path, uint8_t **contents)
{
FILE *file = fopen(path, "rb");
if (file == NULL)
{
printf("Error: Unable to open file.\n");
return 0;
}
// Determine the file size
fseek(file, 0, SEEK_END);
size_t file_size = ftell(file);
rewind(file);
// Allocate memory for the contents array
*contents = (uint8_t *)malloc(file_size);
if (*contents == NULL)
{
printf("Error: Unable to allocate memory.\n");
fclose(file);
return 0;
}
// Read the file contents into the array
fread(*contents, 1, file_size, file);
fclose(file);
return file_size;
}
#define HERE __FILE__
int setUp(void)

6
src/util.h Normal file
View File

@ -0,0 +1,6 @@
/*
* Read the contents of a file into an array
* path: path to the file
* contents: array we'll write to that contains the contents of the file.
*/
size_t read_file(const char *path, uint8_t **contents);

29
util.cpp Normal file
View File

@ -0,0 +1,29 @@
size_t read_file(const char *path, uint8_t **contents)
{
FILE *file = fopen(path, "rb");
if (file == NULL)
{
printf("Error: Unable to open file.\n");
return 0;
}
// Determine the file size
fseek(file, 0, SEEK_END);
size_t file_size = ftell(file);
rewind(file);
// Allocate memory for the contents array
*contents = (uint8_t *)malloc(file_size);
if (*contents == NULL)
{
printf("Error: Unable to allocate memory.\n");
fclose(file);
return 0;
}
// Read the file contents into the array
fread(*contents, 1, file_size, file);
fclose(file);
return file_size;
}