test_image_conversion.cpp 4.17 KB
Newer Older
1
#include <fstream>
2
3
4
#include <numeric>

#include "catch.hpp"
5
6
7
#include "common/config.h"
#include "common/io.h"
#include "common/mesh.h"
Steffen Schotthöfer's avatar
Steffen Schotthöfer committed
8
#include "toolboxes/interpolation.h"
9
#include "toolboxes/textprocessingtoolbox.h"
10

11
TEST_CASE( "convert image data to grayscale matrix", "[image I/O]" ) {
Steffen Schotthöfer's avatar
Steffen Schotthöfer committed
12
    std::string config_file_name = std::string( TESTS_PATH ) + "input/unit_tests/common/image_conversion.cfg";
13
14
15

    Config* config = new Config( config_file_name );    // just to init spdlog

Steffen Schotthöfer's avatar
Steffen Schotthöfer committed
16
    std::string testImage = std::string( TESTS_PATH ) + "input/unit_tests/common/mini_phantom.png";
17
18
19
    std::string testMesh  = config->GetMeshFile();

    Matrix gsImage = createSU2MeshFromImage( testImage, testMesh );
jannick.wolters's avatar
jannick.wolters committed
20
    gsImage.transpose();
jannick.wolters's avatar
jannick.wolters committed
21
22
23
24
25
26
    SECTION( "grayscale matrix" ) {
        REQUIRE( std::filesystem::exists( testMesh ) );    // mesh has been created
        REQUIRE( gsImage.rows() > 0 );                     // atleast some data is stored
        REQUIRE( gsImage.columns() > 0 );                  //
        REQUIRE( blaze::min( gsImage ) >= 0 );             // lower bound
        REQUIRE( blaze::max( gsImage ) <= 1.0 );           // upper bound
27

jannick.wolters's avatar
jannick.wolters committed
28
        // load reference matrix from csv file
Steffen Schotthöfer's avatar
Steffen Schotthöfer committed
29
        std::string refMatrixFile = std::string( TESTS_PATH ) + "input/unit_tests/common/phantom.csv";
jannick.wolters's avatar
jannick.wolters committed
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
        std::ifstream data( refMatrixFile );
        REQUIRE( data.is_open() );
        std::string line;
        std::vector<std::vector<double>> refMatrix;
        while( std::getline( data, line ) ) {
            std::stringstream lineStream( line );
            std::string cell;
            std::vector<double> row;
            while( std::getline( lineStream, cell, ',' ) ) {
                row.push_back( std::stod( cell ) );
            }
            refMatrix.push_back( row );
        }

        REQUIRE( refMatrix.size() == gsImage.rows() );          // equal number of rows
        REQUIRE( refMatrix[0].size() == gsImage.columns() );    // equal number of columns
        REQUIRE( std::all_of( begin( refMatrix ), end( refMatrix ), [refMatrix]( const std::vector<double>& x ) {
            return x.size() == refMatrix[0].size();
        } ) );    // consistency check if all columns of the read-in file have equal length

50
        bool matricesEqual = true;
jannick.wolters's avatar
jannick.wolters committed
51
52
        for( unsigned i = 0; i < gsImage.rows(); ++i ) {
            for( unsigned j = 0; j < gsImage.columns(); ++j ) {
53
                if( refMatrix[i][j] != gsImage( i, j ) ) matricesEqual = false;    // all values match
jannick.wolters's avatar
jannick.wolters committed
54
            }
55
        }
56
        REQUIRE( matricesEqual );
57
58
    }

jannick.wolters's avatar
jannick.wolters committed
59
60
61
62
63
64
65
66
67
68
69
70
71
    SECTION( "interpolation of grayscale matrix onto the generated mesh" ) {
        Mesh* mesh       = LoadSU2MeshFromFile( config );
        auto cellCenters = mesh->GetCellMidPoints();
        auto bounds      = mesh->GetBounds();

        double xMin = bounds[0].first;
        double xMax = bounds[0].second;
        double yMin = bounds[1].first;
        double yMax = bounds[1].second;

        unsigned m = gsImage.rows();
        unsigned n = gsImage.columns();

jannick.wolters's avatar
jannick.wolters committed
72
73
74
        Vector x( m ), y( n );
        for( unsigned i = 0; i < m; ++i ) x[i] = static_cast<double>( i ) / static_cast<double>( m - 1 ) * ( xMax - xMin );
        for( unsigned i = 0; i < n; ++i ) y[i] = static_cast<double>( i ) / static_cast<double>( n - 1 ) * ( yMax - yMin );
75

76
        Interpolation interp( x, y, gsImage );
jannick.wolters's avatar
jannick.wolters committed
77
78
        std::vector<double> result( mesh->GetNumCells(), 0.0 );
        for( unsigned i = 0; i < mesh->GetNumCells(); ++i ) {
79
            result[i] = std::clamp( interp( cellCenters[i][0], cellCenters[i][1] ), 0.0, 1.0 );
80
        }
jannick.wolters's avatar
jannick.wolters committed
81
82

        std::vector<std::string> fieldNames{ "CT Data" };
83
84
        std::vector<std::vector<std::string>> fieldNamesWrapper{ fieldNames };

jannick.wolters's avatar
jannick.wolters committed
85
86
87
88
        std::vector<std::vector<double>> scalarField( 1, result );
        std::vector<std::vector<std::vector<double>>> results{ scalarField };
        std::string outputFile = config->GetOutputFile();
        if( !TextProcessingToolbox::StringEndsWith( outputFile, ".vtk" ) ) outputFile.append( ".vtk" );
89
        ExportVTK( outputFile, results, fieldNamesWrapper, mesh );
jannick.wolters's avatar
jannick.wolters committed
90
91
92
93
94

        REQUIRE( std::filesystem::exists( outputFile ) );

        delete mesh;

jannick.wolters's avatar
jannick.wolters committed
95
        std::remove( outputFile.c_str() );
96
97
98
99
    }

    std::remove( testMesh.c_str() );
}