Skip to content

Commit

Permalink
Merge pull request #22 from OpenPIV/18-overlap-with-independent-x-and…
Browse files Browse the repository at this point in the history
…-y-size

extend grid generation to support pixel offsets #18
  • Loading branch information
timdewhirst authored May 1, 2022
2 parents 1e3301c + ae26c8d commit e1da2b6
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 14 deletions.
36 changes: 25 additions & 11 deletions openpiv/core/detail/grid.impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,50 @@ namespace openpiv::core {
std::vector<core::rect>
generate_cartesian_grid( const core::size& image_size,
const core::size& interrogation_size,
double percentage_overlap )
double percentage_offset )
{
if ( percentage_offset < 0.0 || percentage_offset > 1.0 )
core::exception_builder<std::runtime_error>() << "offsets must be between 0.0 and 1.0";

return generate_cartesian_grid(
image_size,
interrogation_size,
{ (uint32_t)(interrogation_size.width() * percentage_offset),
(uint32_t)(interrogation_size.height() * percentage_offset) } );
}

std::vector<core::rect>
generate_cartesian_grid( const core::size& image_size,
const core::size& interrogation_size,
std::array<uint32_t, 2> offsets )
{
if ( image_size.area() == 0 )
core::exception_builder<std::runtime_error>() << "image size must be non-zero";

if ( interrogation_size.area() == 0 )
core::exception_builder<std::runtime_error>() << "interrogation size must be non-zero";

auto x_overlap = (uint32_t)(interrogation_size.width() * percentage_overlap);
auto y_overlap = (uint32_t)(interrogation_size.height() * percentage_overlap);

if ( percentage_overlap < 0.0 || percentage_overlap > 1.0 || x_overlap == 0 || y_overlap == 0 )
core::exception_builder<std::runtime_error>() << "overlaps must be between 0.0 and 1.0";
if ( offsets[0] == 0 || offsets[1] == 0 )
core::exception_builder<std::runtime_error>() << "offsets must be non-zero";

if ( interrogation_size.width() > image_size.width() ||
interrogation_size.height() > image_size.height() )
core::exception_builder<std::runtime_error>() << "interrogation size is bigger than image";

auto x_count = 1 + (image_size.width() - interrogation_size.width()) / x_overlap;
auto y_count = 1 + (image_size.height() - interrogation_size.height()) / y_overlap;
auto [x_offset, y_offset] = offsets;

auto x_count = 1 + (image_size.width() - interrogation_size.width()) / x_offset;
auto y_count = 1 + (image_size.height() - interrogation_size.height()) / y_offset;

auto x_offset = (image_size.width() - interrogation_size.width() - (x_overlap * (x_count-1)))/2;
auto y_offset = (image_size.height() - interrogation_size.height() - (y_overlap * (y_count-1)))/2;
auto x_start_offset = (image_size.width() - interrogation_size.width() - (x_offset * (x_count-1)))/2;
auto y_start_offset = (image_size.height() - interrogation_size.height() - (y_offset * (y_count-1)))/2;

std::vector<core::rect> result;
for ( size_t y=0; y < y_count; ++y )
{
for ( size_t x=0; x < x_count; ++x )
{
rect r{ {x_offset + x * x_overlap, y_offset + y * y_overlap}, interrogation_size };
rect r{ {x_start_offset + x * x_offset, y_start_offset + y * y_offset}, interrogation_size };
result.emplace_back( std::move(r) );
}
}
Expand Down
21 changes: 19 additions & 2 deletions openpiv/core/grid.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#pragma once

// std
#include <array>
#include <vector>

// openpiv
Expand All @@ -11,7 +12,7 @@
namespace openpiv::core {

/// generate a centred cartesian grid of rectangles with
/// dimensions \a size and a specified \a overlap
/// dimensions \a size and a specified \a offset
///
/// generate_cartesian_grid( images_size, size( 32, 32 ), 0.5 )
///
Expand All @@ -24,7 +25,23 @@ namespace openpiv::core {
std::vector<core::rect>
generate_cartesian_grid( const core::size& image_size,
const core::size& interrogation_size,
double percentage_overlap );
double percentage_offset );

/// generate a centred cartesian grid of rectangles with
/// dimensions \a size and a specified \a offset in x and y
///
/// generate_cartesian_grid( images_size, size( 32, 32 ), { 16, 16 } )
///
/// image_size = (100, 50)
///
/// top-left: [(2, 1), (18, 1), (34, 1), (50, 1), (66, 1),
/// (2, 17), (18, 17), (34, 17), (50, 17), (66, 17)]
/// (66, 1) -> rectangle from (66, 1) -> (98, 33)
/// (2, 17) -> rectangle from (2, 17) -> (34, 49)
std::vector<core::rect>
generate_cartesian_grid( const core::size& image_size,
const core::size& interrogation_size,
std::array< uint32_t, 2 > offsets );

} // end of namespace

Expand Down
66 changes: 65 additions & 1 deletion test/grid_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ TEST_CASE("grid_test - cartesian grid")

for ( const auto& tl :
{ point_t(2, 1), point_t(18, 1), point_t(34, 1), point_t(50, 1), point_t(66, 1),
point_t(2, 17), point_t(18, 17), point_t(34, 17), point_t(50, 17), point_t(66, 17) } )
point_t(2, 17), point_t(18, 17), point_t(34, 17), point_t(50, 17), point_t(66, 17) } )
expected.emplace_back( rect(tl, interrogation) );

INFO( "generated: " << sort_grid(generated) );
Expand Down Expand Up @@ -152,4 +152,68 @@ TEST_CASE("grid_test - cartesian grid")
CHECK( generated.size() == expected.size() );
CHECK( (sort_grid( generated ) == sort_grid( expected )) );
}

SECTION("exact 3x3, 50% pixel offset")
{
auto generated = generate_cartesian_grid( {64, 64}, interrogation, {16, 16} );

for ( const auto& tl :
{ point_t(0, 0), point_t(16, 0), point_t(32, 0),
point_t(0, 16), point_t(16, 16), point_t(32, 16),
point_t(0, 32), point_t(16, 32), point_t(32, 32) } )
expected.emplace_back( rect(tl, interrogation) );

INFO( "generated: " << sort_grid(generated) );
INFO( "expected: " << sort_grid(expected) );

CHECK( generated.size() == expected.size() );
CHECK( (sort_grid( generated ) == sort_grid( expected )) );
}

SECTION("exact 3x5, 50/25% pixel offset")
{
auto generated = generate_cartesian_grid( {64, 64}, interrogation, {16, 8} );

for ( const auto& tl :
{ point_t(0, 0), point_t(16, 0), point_t(32, 0),
point_t(0, 8), point_t(16, 8), point_t(32, 8),
point_t(0, 16), point_t(16, 16), point_t(32, 16),
point_t(0, 24), point_t(16, 24), point_t(32, 24),
point_t(0, 32), point_t(16, 32), point_t(32, 32) } )
expected.emplace_back( rect(tl, interrogation) );

INFO( "generated: " << sort_grid(generated) );
INFO( "expected: " << sort_grid(expected) );

CHECK( generated.size() == expected.size() );
CHECK( (sort_grid( generated ) == sort_grid( expected )) );
}

SECTION("exact 3x7, 50/50% pixel offset, non-square interrogation")
{
auto interrogation = size(32, 16);
auto generated = generate_cartesian_grid(
{64, 64}, // image size
interrogation, // interrogation size
{16, 8} // offset
);

for ( const auto& tl :
{ point_t(0, 0), point_t(16, 0), point_t(32, 0),
point_t(0, 8), point_t(16, 8), point_t(32, 8),
point_t(0, 16), point_t(16, 16), point_t(32, 16),
point_t(0, 24), point_t(16, 24), point_t(32, 24),
point_t(0, 32), point_t(16, 32), point_t(32, 32),
point_t(0, 40), point_t(16, 40), point_t(32, 40),
point_t(0, 48), point_t(16, 48), point_t(32, 48)
} )
expected.emplace_back( rect(tl, interrogation) );

INFO( "generated: " << sort_grid(generated) );
INFO( "expected: " << sort_grid(expected) );

CHECK( generated.size() == expected.size() );
CHECK( (sort_grid( generated ) == sort_grid( expected )) );
}

}

0 comments on commit e1da2b6

Please sign in to comment.