Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
dbb23f6
tangent image generation code and unit test
meder411 Jun 1, 2020
cd3ee2b
cleaned up tangent image code a bit
meder411 Jun 5, 2020
f143631
merge with openmvg dev
meder411 Jun 14, 2020
ddf6204
updated the tangent images code, still need to finish feature conversion
meder411 Aug 22, 2020
841bd0a
added copyright stuff to tangent_images_test
meder411 Aug 22, 2020
7fee680
undo edits to dockerfile
meder411 Aug 22, 2020
343e5c3
tangent image generation code and unit test
meder411 Jun 1, 2020
f611d8a
cleaned up tangent image code a bit
meder411 Jun 5, 2020
0cb6b2e
updated the tangent images code, still need to finish feature conversion
meder411 Aug 22, 2020
e64daa7
added copyright stuff to tangent_images_test
meder411 Aug 22, 2020
7e90175
undo edits to dockerfile
meder411 Aug 22, 2020
3982170
fixed merge conflicts in spherical cmakelists
meder411 Aug 22, 2020
31d7f17
generate tangent images with valid-region masks, also compute convers…
meder411 Oct 17, 2020
4cd54c7
fixed tangent-uv-to-equirect conversion
meder411 Oct 17, 2020
1a1f967
removed unimplemented unit test
meder411 Oct 17, 2020
0ec10ab
removed changes to dockerfile from openmvg main repo
meder411 Oct 17, 2020
2d2d31e
undo changes to compute features script
meder411 Oct 17, 2020
b8bd46a
undo changes to compute features script
meder411 Oct 17, 2020
2b99156
fixed unused var and const ref per codacity
meder411 Oct 17, 2020
dd22903
some clarifying comments, fixed some const stuff
meder411 Oct 18, 2020
ba87b6e
some more comments
meder411 Oct 18, 2020
6ed020c
added newline to end of my computeFeatures so as not to impact that f…
meder411 Oct 18, 2020
d4f78b8
got rid of need to track tangent image corners
meder411 Oct 18, 2020
f301158
deleted spurious const returns per code quality review
meder411 Oct 18, 2020
f48db23
tangent image feature detection except for coord update
meder411 Nov 1, 2020
abd1553
fixed the feature coordinate update
meder411 Nov 1, 2020
84f0026
Merge pull request #1 from meder411/tangent-image-feature-detection
meder411 Nov 1, 2020
dd07c4c
changed image_describer to accept ref instead of unique_ptr
meder411 Nov 1, 2020
f6bd913
more unit tests, resampling back to equirect
meder411 Nov 2, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
tangent image generation code and unit test
  • Loading branch information
meder411 committed Jun 1, 2020
commit dbb23f675d84a9538a324ab47c2ba7c55184696a
7 changes: 7 additions & 0 deletions src/openMVG/spherical/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

add_library(openMVG_spherical INTERFACE)
target_compile_features(openMVG_spherical INTERFACE ${CXX11_FEATURES})
target_link_libraries(openMVG_spherical INTERFACE openMVG_image)
install(TARGETS openMVG_spherical DESTINATION lib EXPORT openMVG-targets)

UNIT_TEST(openMVG_spherical spherical "openMVG_spherical")
Binary file added src/openMVG/spherical/earthmap4k.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
216 changes: 216 additions & 0 deletions src/openMVG/spherical/spherical.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
// This file is part of OpenMVG, an Open Multiple View Geometry C++ library.

// Copyright (c) 2014, 2015 Romuald Perrot.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef OPENMVG_SPHERICAL_SPHERICAL_HPP
#define OPENMVG_SPHERICAL_SPHERICAL_HPP

#include <utility>
#include <vector>
#include <cmath>
#include <iostream>
#include "openMVG/image/image_container.hpp"
#include "openMVG/image/sample.hpp"

namespace openMVG {
namespace spherical {

using namespace openMVG::image;

// Spherical coordinates of placement of tangent images for level 0 (20 x 2 row
// major order)
static const std::vector<double> tangentCentersL0 = {
1.8850, -0.9184, 0.6283, -0.9184, -0.6283, -0.9184, -1.8850, -0.9184,
3.1416, -0.9184, 0.6283, -0.1887, 1.8850, -0.1887, 3.1416, -0.1887,
-1.8850, -0.1887, -0.6283, -0.1887, 1.2566, 0.9184, 2.5133, 0.9184,
-2.5133, 0.9184, -1.2566, 0.9184, 0.0000, 0.9184, 1.2566, 0.1887,
2.5133, 0.1887, -2.5133, 0.1887, -1.2566, 0.1887, 0.0000, 0.1887};

// Spherical coordinates of placement of tangent images for level 1 (80 x 2 row
// major order)
static const std::vector<double> tangentCentersL1 = {
1.8850, -0.9184, 0.6283, -0.9184, -0.6283, -0.9184, -1.8850, -0.9184,
3.1416, -0.9184, 0.6283, -0.1887, 1.8850, -0.1887, 3.1416, -0.1887,
-1.8850, -0.1887, -0.6283, -0.1887, 1.2566, 0.9184, 2.5133, 0.9184,
-2.5133, 0.9184, -1.2566, 0.9184, 0.0000, 0.9184, 1.2566, 0.1887,
2.5133, 0.1887, -2.5133, 0.1887, -1.2566, 0.1887, 0.0000, 0.1887,
2.2802, -0.6998, 1.4897, -0.6998, 1.8850, -1.2655, 1.0236, -0.6998,
0.2331, -0.6998, 0.6283, -1.2655, -0.2331, -0.6998, -1.0236, -0.6998,
-0.6283, -1.2655, -1.4897, -0.6998, -2.2802, -0.6998, -1.8850, -1.2655,
3.1416, -1.2655, -2.7464, -0.6998, 2.7464, -0.6998, 0.9473, -0.3506,
0.6283, 0.1583, 0.3093, -0.3506, 2.2040, -0.3506, 1.8850, 0.1583,
1.5660, -0.3506, -2.8226, -0.3506, 3.1416, 0.1583, 2.8226, -0.3506,
-1.5660, -0.3506, -1.8850, 0.1583, -2.2040, -0.3506, -0.3093, -0.3506,
-0.6283, 0.1583, -0.9473, -0.3506, 0.8614, 0.6998, 1.6519, 0.6998,
1.2566, 1.2655, 2.1180, 0.6998, 2.9085, 0.6998, 2.5133, 1.2655,
-2.9085, 0.6998, -2.1180, 0.6998, -2.5133, 1.2655, -1.6519, 0.6998,
-0.8614, 0.6998, -1.2566, 1.2655, 0.0000, 1.2655, -0.3952, 0.6998,
0.3952, 0.6998, 1.2566, -0.1583, 1.5756, 0.3506, 0.9376, 0.3506,
2.5133, -0.1583, 2.8323, 0.3506, 2.1943, 0.3506, -2.5133, -0.1583,
-2.1943, 0.3506, -2.8323, 0.3506, -1.2566, -0.1583, -0.9376, 0.3506,
-1.5756, 0.3506, 0.0000, -0.1583, 0.3190, 0.3506, -0.3190, 0.3506};

// Angular resolution of icosahedron levels
static const double angResL0 = 1.1071487665176392; // radians
static const double angResL1 = 0.5891666412353516; // radians

// Floating point negative modulus operation
template <typename T>
const T fnegmod(const T lval, const T rval) {
return fmod(fmod(lval, rval) + rval, rval);
}

// Rescale value to a new range
template <typename T>
T renormalize(const T value, const T old_min, const T old_max, const T new_min, const T new_max){
return (new_max - new_min) * (value - old_min) / (old_max - old_min) +
new_min;
}

void CreateSamplingMap(const size_t base_level, const size_t resolution_level,
const size_t rect_h, const size_t rect_w,
std::vector<double>& sampling_map) {
// Tangent image dimension is 2^(s-b)
const size_t tangent_dim = 1 << (resolution_level - base_level);

// Allocate space for all the tangent image sample maps
const size_t num_tangent_imgs =
20 * std::pow(4L, static_cast<long>(base_level));
sampling_map.resize(num_tangent_imgs * tangent_dim * tangent_dim * 2);

// Resolution of the icosahedron
double sample_resolution;
switch(base_level)
{
case 0:
sample_resolution = angResL0 / tangent_dim;
break;
case 1:
default:
sample_resolution = angResL1 / tangent_dim;
break;
}

// Tangent image locations
std::vector<double> tangent_centers;
switch(base_level)
{
case 0:
tangent_centers = tangentCentersL0;
break;
case 1:
default:
tangent_centers = tangentCentersL1;
break;
}

// Go through each tangent image
for (size_t i = 0; i < num_tangent_imgs; i++){
// Tangent point for each tangent image in spherical coordinates
const double lon = tangent_centers[2 * i];
const double lat = tangent_centers[2 * i + 1];

// j indexes rows in the tangent image
for (size_t j = 0; j < tangent_dim; j++){
const double y =
(static_cast<double>(j) - static_cast<double>(tangent_dim) / 2.0) *
sample_resolution +
sample_resolution / 2.0;
// k indexes columns in the tangent image
for (size_t k = 0; k < tangent_dim; k++){
const double x =
(static_cast<double>(k) - static_cast<double>(tangent_dim) / 2.0) *
sample_resolution +
sample_resolution / 2.0;

// Compute the gnomonic projection of each (x,y) onto a plane centered at (lon, lat) [output is in spherical coordinates (radians)]
const double rho = std::sqrt(x * x + y * y);
const double nu = std::atan(rho);

// Index in sample map
const size_t map_idx =
i * tangent_dim * tangent_dim * 2 + j * tangent_dim * 2 + k * 2;

// Compute output longitude (modulo 2*PI)
sampling_map[map_idx] =
fnegmod(lon +
std::atan2(x * std::sin(nu),
rho * std::cos(lat) * std::cos(nu) -
y * std::sin(lat) * std::sin(nu)) +
M_PI,
2 * M_PI) -
M_PI;

// Compute output latitude
sampling_map[map_idx + 1] =
std::asin(std::cos(nu) * std::sin(lat) +
y * std::sin(nu) * std::cos(lat) / rho);

// Convert the output to coordinates of an equirectangular image
sampling_map[map_idx] =
renormalize(sampling_map[map_idx], -M_PI, M_PI, 0.0, static_cast<double>(rect_w));
sampling_map[map_idx + 1] =
renormalize(sampling_map[map_idx + 1], -M_PI / 2.0, M_PI / 2.0, 0.0,
static_cast<double>(rect_h - 1));
}
}
}
}

/**
** @brief Convert equirectangular image to tangent images
** @param src input equirectangular image
** @param input spherical level (in terms of icosahedron subdivision)
** @param base level
** @param out output tangent image set
**/
template <typename Image>
void Equirectangular2Tangent(const Image& src, const size_t resolution_level,
const size_t base_level,
std::vector<Image>& out) {
// TODO: should assert a range of allowed base levels (probably {0,1})

// Allocate the output vector
const size_t num_tangent_imgs =
20 * std::pow(4L, static_cast<long>(base_level));
out.resize(num_tangent_imgs);

// Create the sampling maps for the tangent images
std::vector<double> sampling_map;
CreateSamplingMap(base_level, resolution_level, src.Height(), src.Width(),
sampling_map);

// Tangent image dimension is 2^(s-b)
const size_t tangent_dim = 1 << (resolution_level - base_level);

// Create bilinear sampler
const Sampler2d<SamplerLinear> sampler;

// Create each tangent image
for (size_t i = 0; i < num_tangent_imgs; i++){

// Initialize output image
out[i] = Image(tangent_dim, tangent_dim);

// Resample to each tangent image
for (size_t j = 0; j < tangent_dim; j++) {
for (size_t k = 0; k < tangent_dim; k++) {
// Index in sample map
const size_t map_idx =
i * tangent_dim * tangent_dim * 2 + j * tangent_dim * 2 + k * 2;

// Sample from the precomputed map
out[i](j, k) =
sampler(src, sampling_map[map_idx + 1], sampling_map[map_idx]);
}
}
}
}
}
} // namespace openMVG

#endif
36 changes: 36 additions & 0 deletions src/openMVG/spherical/spherical_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "openMVG/image/image_io.hpp"
#include "openMVG/spherical/spherical.hpp"

#include "testing/testing.h"

#include <sstream>
#include <vector>
#include <string>

using namespace openMVG;
using namespace openMVG::image;
using namespace openMVG::spherical;

TEST(Spherical,CreateTangentImages)
{
Image<RGBColor> image;
const std::string png_filename = std::string(THIS_SOURCE_DIR) + "/earthmap4k.jpg";
std::cout << png_filename << std::endl;
EXPECT_TRUE(ReadImage(png_filename.c_str(), &image));

const std::string test_filename = "earthmap4k.jpg";
EXPECT_TRUE(WriteImage(test_filename.c_str(), image));

std::vector<Image<RGBColor>> tangent_images;
Equirectangular2Tangent(image, 9L, 0L, tangent_images);

for (size_t i = 0; i < tangent_images.size(); i++) {
const std::string out_filename = ("test_tangent images_" + std::to_string(i) + ".png");
EXPECT_TRUE( WriteImage( out_filename.c_str(), tangent_images[i]) );
}
}


/* ************************************************************************* */
int main() { TestResult tr; return TestRegistry::runAllTests(tr);}
/* ************************************************************************* */