Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
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
3 changes: 3 additions & 0 deletions clic/include/core/clesperanto.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ class Clesperanto
auto
DetectMaximaBox(const Image & source, const Image & destination) -> void;

auto
DetectMinima(const Image & source, const Image & destination) -> void;

auto
DifferenceOfGaussian(const Image & source,
const Image & destination,
Expand Down
31 changes: 31 additions & 0 deletions clic/include/tier1/cleDetectMinimaKernel.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

#ifndef __TIER1_CLEDETECTMINIMAKERNEL_HPP
#define __TIER1_CLEDETECTMINIMAKERNEL_HPP

#include "cleOperation.hpp"

namespace cle
{

class DetectMinimaKernel : public Operation
{
public:
explicit DetectMinimaKernel(const ProcessorPointer & device);
auto
SetInput(const Image & object) -> void;
auto
SetOutput(const Image & object) -> void;
};

inline auto
DetectMinimaKernel_Call(const std::shared_ptr<cle::Processor> & device, const Image & src, const Image & dst) -> void
{
DetectMinimaKernel kernel(device);
kernel.SetInput(src);
kernel.SetOutput(dst);
kernel.Execute();
}

} // namespace cle

#endif // __TIER1_CLEDETECTMINIMAKERNEL_HPP
6 changes: 6 additions & 0 deletions clic/src/core/clesperanto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ Clesperanto::SubtractImages(const Image & source1, const Image & source2, const
this->AddImagesWeighted(source1, source2, destination, 1, -1);
}

auto
Clesperanto::DetectMinima(const Image & source, const Image & destination) -> void
{
DetectMinimaKernel_Call(this->GetDevice(), source, destination);
}

auto
Clesperanto::DilateSphere(const Image & source, const Image & destination) -> void
{
Expand Down
28 changes: 28 additions & 0 deletions clic/src/tier1/cleDetectMinimaKernel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

#include "cleDetectMinimaKernel.hpp"

namespace cle

{
DetectMinimaKernel::DetectMinimaKernel(const ProcessorPointer & device)
: Operation(device, 2)

{
std::string cl_header = {
#include "cle_detect_minima.h"
};
this->SetSource("detect_minima", cl_header);
}
Comment on lines +10 to +13
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Library was updated, this need to be changed as followed:

  • move the include outside the function, at the top of the file
  • replace cl_header by oclKernel::detect_minima

see: absolute kernel for example


auto
DetectMinimaKernel::SetInput(const Image & object) -> void
{
this->AddParameter("src", object);
}

auto
DetectMinimaKernel::SetOutput(const Image & object) -> void
{
this->AddParameter("dst", object);
}
} // namespace cle
8 changes: 8 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ target_link_libraries(detect_maxima_test PRIVATE CLIc::CLIc)
set_target_properties(detect_maxima_test PROPERTIES FOLDER "Tests")
# target_compile_features(detect_maxima_test PRIVATE cxx_std_17)

add_executable(detect_minima_test detect_minima_test.cpp)
add_dependencies(detect_minima_test CLIc)
target_link_libraries(detect_minima_test PRIVATE CLIc::CLIc)
set_target_properties(detect_minima_test PROPERTIES FOLDER "Tests")
# target_compile_features(detect_minima_test PRIVATE cxx_std_17)

add_executable(difference_of_gaussian_test difference_of_gaussian_test.cpp)
add_dependencies(difference_of_gaussian_test CLIc)
target_link_libraries(difference_of_gaussian_test PRIVATE CLIc::CLIc)
Expand Down Expand Up @@ -476,6 +482,7 @@ add_test(NAME convolve_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAN
add_test(NAME copy_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND copy_test)
add_test(NAME crop_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND crop_test)
add_test(NAME detect_maxima_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND detect_maxima_test)
add_test(NAME detect_minima_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND detect_minima_test)
add_test(NAME difference_of_gaussian_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND difference_of_gaussian_test)
add_test(NAME dilate_sphere_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND dilate_sphere_test)
add_test(NAME gradient_x_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND gradient_x_test)
Expand Down Expand Up @@ -557,6 +564,7 @@ set_tests_properties(absolute_test
copy_test
crop_test
detect_maxima_test
detect_minima_test
difference_of_gaussian_test
dilate_sphere_test
equal_constant_test
Expand Down
20 changes: 17 additions & 3 deletions tests/detect_maxima_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,15 @@ run_test(const std::array<size_t, 3> & shape, const cle::MemoryType & mem_type)
std::vector<type> valid(shape[0] * shape[1] * shape[2]);
std::fill(input.begin(), input.end(), static_cast<type>(0));
std::fill(valid.begin(), valid.end(), static_cast<type>(0));
int center = (shape[0] / 2) + (shape[1] / 2) * shape[0] + (shape[2] / 2) * shape[0] * shape[1];
input[center] = static_cast<type>(100);
valid[center] = static_cast<type>(1);

// An example of a case where the maximal value is located in the center
// int center = (shape[0] / 2) + (shape[1] / 2) * shape[0] + (shape[2] / 2) * shape[0] * shape[1];
// input[center] = static_cast<type>(100);
// valid[center] = static_cast<type>(1);

// An example of a case where the maximal value is located at the bottom right
input[input.size() - 1] = static_cast<type>(0);
valid[valid.size() - 1] = static_cast<type>(1);

cle::Clesperanto cle;
cle.GetDevice()->WaitForKernelToFinish();
Expand Down Expand Up @@ -134,6 +140,14 @@ main(int argc, char ** argv) -> int
return EXIT_FAILURE;
}

/* Although it works for the above tests, here is an example in which detecting the maximal value when it is located
in the center of a 3D array of shape (3, 3, 2) does not work.

if (!run_test<float>({ 3, 3, 2 }, cle::BUFFER))
{
return EXIT_FAILURE;
} */

// if (!run_test<float>({ 10, 1, 1 }, cle::IMAGE))
// {
// return EXIT_FAILURE;
Expand Down
152 changes: 152 additions & 0 deletions tests/detect_minima_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@


#include <random>

#include "clesperanto.hpp"

template <class type>
auto
run_test(const std::array<size_t, 3> & shape, const cle::MemoryType & mem_type) -> bool
{
std::vector<type> input(shape[0] * shape[1] * shape[2]);
std::vector<type> valid(shape[0] * shape[1] * shape[2]);
std::fill(input.begin(), input.end(), static_cast<type>(100));
std::fill(valid.begin(), valid.end(), static_cast<type>(0));

// An example of a case where the maximal value is located in the center
// int center = (shape[0] / 2) + (shape[1] / 2) * shape[0] + (shape[2] / 2) * shape[0] * shape[1];
// input[center] = static_cast<type>(0);
// valid[center] = static_cast<type>(1);

// An example of a case where the maximal value is located at the bottom right
input[input.size() - 1] = static_cast<type>(0);
valid[valid.size() - 1] = static_cast<type>(1);

cle::Clesperanto cle;
cle.GetDevice()->WaitForKernelToFinish();
auto gpu_input = cle.Push<type>(input, shape, mem_type);
auto gpu_output = cle.Create<type>(shape, mem_type);
cle.DetectMinima(gpu_input, gpu_output);
auto output = cle.Pull<type>(gpu_output);

return std::equal(output.begin(), output.end(), valid.begin());
}

auto
main(int argc, char ** argv) -> int
{
if (!run_test<float>({ 10, 1, 1 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<int32_t>({ 10, 1, 1 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<uint32_t>({ 10, 1, 1 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<int16_t>({ 10, 1, 1 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<uint16_t>({ 10, 1, 1 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<int8_t>({ 10, 1, 1 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<uint8_t>({ 10, 1, 1 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<float>({ 4, 3, 1 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<int32_t>({ 4, 3, 1 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<uint32_t>({ 4, 3, 1 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<int16_t>({ 4, 3, 1 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<uint16_t>({ 4, 3, 1 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<int8_t>({ 4, 3, 1 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<uint8_t>({ 4, 3, 1 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<float>({ 5, 6, 3 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<int32_t>({ 5, 6, 3 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<uint32_t>({ 5, 6, 3 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<int16_t>({ 5, 6, 3 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<uint16_t>({ 5, 6, 3 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<int8_t>({ 5, 6, 3 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

if (!run_test<uint8_t>({ 5, 6, 3 }, cle::BUFFER))
{
return EXIT_FAILURE;
}

/* Although it works for the above tests, here is an example in which detecting the minimal value when it is located
in the center of a 3D array of shape (3, 3, 2) does not work.

if (!run_test<float>({ 3, 3, 2 }, cle::BUFFER))
{
return EXIT_FAILURE;
} */

return EXIT_SUCCESS;
}