Skip to content

Commit

Permalink
Merge pull request #270 from clEsperanto/add-affine-transform
Browse files Browse the repository at this point in the history
add transform and tests
  • Loading branch information
StRigaud committed Mar 29, 2024
2 parents 42f9007 + 4906a05 commit 8cb6539
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 1 deletion.
23 changes: 23 additions & 0 deletions clic/include/tier7.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,29 @@
namespace cle::tier7
{

/**
* @name affine_transform
* @brief Apply an affine transformation matrix to an array and return the result.
* The transformation matrix must be 3x3 or 4x4 stored as a 1D array.
* The matrix should be row-major, i.e. the first 3 elements are the first row of the matrix.
*
* @param device Device to perform the operation on. [const Device::Pointer &]
* @param src Input Array to be transformed. [const Array::Pointer &]
* @param dst Output Array. [Array::Pointer ( = None )]
* @param transform_matrix Affine transformation matrix (3x3 or 4x4). [std::vector<float> &]
* @param interpolate If true, bi/trilinear interpolation will be applied, if hardware allows. [bool ( = False )]
* @param resize Automatically determines the size of the output depending on the rotation angles. [bool ( = False )]
* @return Array::Pointer
*
*/
auto
affine_transform_func(const Device::Pointer & device,
const Array::Pointer & src,
Array::Pointer dst,
std::vector<float> & transform_matrix,
bool interpolate,
bool resize) -> Array::Pointer;

/**
* @name eroded_otsu_labeling
* @brief Segments and labels an image using blurring, Otsu-thresholding, binary erosion and
Expand Down
2 changes: 1 addition & 1 deletion clic/include/transform.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class AffineTransform
*/
AffineTransform(const std::array<float, 16> & array)
{
m_matrix = matrix::Map(array.data());
m_matrix = matrix::Map(array.data()).transpose();
update();
}

Expand Down
43 changes: 43 additions & 0 deletions clic/src/tier7.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,49 @@
namespace cle::tier7
{

auto
affine_transform_func(const Device::Pointer & device,
const Array::Pointer & src,
Array::Pointer dst,
std::vector<float> & transform_matrix,
bool interpolate,
bool resize) -> Array::Pointer
{
if (transform_matrix.size() != 16 && transform_matrix.size() != 9)
{
throw std::runtime_error("Error: Transformation matrix size must be 9 or 16.");
}
std::array<float, 16> transform_matrix_arr;
if (transform_matrix.size() == 9)
{
// Fill the array with the 3x3 matrix and the extra row and column for the 4x4 matrix
transform_matrix_arr = { transform_matrix[0],
transform_matrix[1],
0,
transform_matrix[2],
transform_matrix[3],
transform_matrix[4],
0,
transform_matrix[5],
transform_matrix[6],
transform_matrix[7],
1,
0, // transform_matrix[8],
0,
0,
0,
1 };
}
else
{
// If the matrix is already 4x4, just copy the values
std::copy(transform_matrix.begin(), transform_matrix.end(), transform_matrix_arr.begin());
}
auto transform = AffineTransform(transform_matrix_arr);
return apply_affine_transform(src, dst, transform, interpolate, resize);
}


auto
eroded_otsu_labeling_func(const Device::Pointer & device,
const Array::Pointer & src,
Expand Down
50 changes: 50 additions & 0 deletions tests/tier7/test_affine_transform.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include "cle.hpp"

#include <array>
#include <gtest/gtest.h>

class TestAffineTransform : public ::testing::TestWithParam<std::string>
{};

TEST_P(TestAffineTransform, affineTransform)
{
const std::array<float, 5 * 5 * 1> input = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
const std::array<float, 5 * 5 * 1> valid = {
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
std::array<float, 5 * 5 * 1> output;

std::string param = GetParam();
cle::BackendManager::getInstance().setBackend(param);
auto device = cle::BackendManager::getInstance().getBackend().getDevice("", "all");
device->setWaitToFinish(true);

auto gpu_input = cle::Array::create(5, 5, 1, 2, cle::dType::FLOAT, cle::mType::BUFFER, device);
gpu_input->write(input.data());

std::vector<float> matrix = { 1, 0, -1, 0, 1, -1, 0, 0, 1 };
auto gpu_output = cle::tier7::affine_transform_func(device, gpu_input, nullptr, matrix, false, false);

gpu_output->read(output.data());
for (int i = 0; i < output.size(); i++)
{
EXPECT_EQ(output[i], valid[i]);
}
}

std::vector<std::string>
getParameters()
{
std::vector<std::string> parameters;
#if USE_OPENCL
parameters.push_back("opencl");
#endif
#if USE_CUDA
parameters.push_back("cuda");
#endif
return parameters;
}

INSTANTIATE_TEST_SUITE_P(InstantiationName, TestAffineTransform, ::testing::ValuesIn(getParameters()));

0 comments on commit 8cb6539

Please sign in to comment.