Commit f51866f335cbc3c06695c3392fdc67a438cec67e

Authored by David Mayerich
0 parents

initial commit

CMakeLists.txt 0 → 100644
  1 +++ a/CMakeLists.txt
  1 +#Specify the version being used aswell as the language
  2 +cmake_minimum_required(VERSION 2.8.11)
  3 +
  4 +#Name your project here
  5 +project(pointmets)
  6 +
  7 +#set the module directory
  8 +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}")
  9 +
  10 +#find the STIM library
  11 +find_package(STIM REQUIRED)
  12 +
  13 +#find the approximate nearest neighbor library
  14 +find_package(ANN REQUIRED)
  15 +
  16 +#find the pthreads package
  17 +find_package(Threads)
  18 +
  19 +include_directories(
  20 + ${STIM_INCLUDE_DIRS}
  21 + ${ANN_INCLUDE_DIR}
  22 + )
  23 +
  24 +#Assign source files to the appropriate variables
  25 +file(GLOB SRC_CPP "*.cpp")
  26 +file(GLOB SRC_H "*.h")
  27 +
  28 +#create an executable file
  29 +add_executable(pointmets
  30 + ${SRC_H}
  31 + ${SRC_CPP}
  32 + )
  33 +
  34 +#set the link libraries
  35 +target_link_libraries(pointmets
  36 + ${CMAKE_THREAD_LIBS_INIT}
  37 + ${ANN_LIBRARY}
  38 + )
  39 +
  40 +#copy an OBJ test case
  41 +configure_file(data/blue_gt.txt blue_gt.txt COPYONLY)
  42 +configure_file(data/blue_t.txt blue_t.txt COPYONLY)
  43 +configure_file(data/blue_gt.bmp blue_gt.bmp COPYONLY)
0 44 \ No newline at end of file
... ...
FindANN.cmake 0 → 100644
  1 +++ a/FindANN.cmake
  1 +# - Try to find ANN
  2 +# Once done this will define
  3 +#
  4 +# ANN_FOUND - system has ANN
  5 +# ANN_INCLUDE_DIR - the ANN include directory
  6 +# ANN_LIBRARY - Link these to use ANN
  7 +#
  8 +
  9 +IF (ANN_INCLUDE_DIRS)
  10 + # Already in cache, be silent
  11 + SET(ANN_FIND_QUIETLY TRUE)
  12 +ENDIF (ANN_INCLUDE_DIRS)
  13 +
  14 +FIND_PATH( ANN_INCLUDE_DIR ANN/ANN.h
  15 + PATHS "/usr/include" "C:/libs/ANN/include")
  16 +
  17 +if( WIN32 )
  18 +
  19 + set(ANN_LIBRARY $ENV{ANN_PATH}\\ANN.lib)
  20 + set(ANN_INCLUDE_DIR $ENV{ANN_PATH})
  21 +
  22 +
  23 + # Store the library dir. May be used for linking to dll!
  24 + # GET_FILENAME_COMPONENT( ANN_LIBRARY_DIR ${ANN_LIBRARY} PATH )
  25 +
  26 + find_package_handle_standard_args(ANN DEFAULT_MSG ANN_INCLUDE_DIR)
  27 +
  28 +else (WIN32)
  29 +
  30 + FIND_LIBRARY( ANN_LIBRARY
  31 + NAMES ann ANN
  32 + PATHS /lib /usr/lib /usr/lib64 /usr/local/lib )
  33 +
  34 +endif( WIN32)
  35 +
  36 +
  37 +IF (ANN_INCLUDE_DIR AND ANN_LIBRARY)
  38 + SET(ANN_FOUND TRUE)
  39 +ELSE (ANN_INCLUDE_DIR AND ANN_LIBRARY)
  40 + SET( ANN_FOUND FALSE )
  41 +ENDIF (ANN_INCLUDE_DIR AND ANN_LIBRARY)
  42 +
... ...
FindSTIM.cmake 0 → 100644
  1 +++ a/FindSTIM.cmake
  1 +include(FindPackageHandleStandardArgs)
  2 +
  3 +set(STIM_INCLUDE_DIR $ENV{STIMLIB_PATH})
  4 +
  5 +find_package_handle_standard_args(STIM DEFAULT_MSG STIM_INCLUDE_DIR)
  6 +
  7 +if(STIM_FOUND)
  8 + set(STIM_INCLUDE_DIRS ${STIM_INCLUDE_DIR})
  9 +endif()
0 10 \ No newline at end of file
... ...
data/blue_gt.bmp 0 → 100644
No preview for this file type
data/blue_gt.txt 0 → 100644
  1 +++ a/data/blue_gt.txt
  1 +3 686
  2 +19 537
  3 +46 587
  4 +57 785
  5 +73 465
  6 +99 367
  7 +103 657
  8 +109 1038
  9 +115 304
  10 +149 665
  11 +175 984
  12 +187 324
  13 +191 1069
  14 +200 628
  15 +205 566
  16 +218 388
  17 +242 494
  18 +242 633
  19 +249 288
  20 +249 745
  21 +259 442
  22 +270 193
  23 +292 984
  24 +297 539
  25 +297 688
  26 +313 463
  27 +322 342
  28 +329 842
  29 +337 304
  30 +342 407
  31 +380 517
  32 +382 1003
  33 +394 306
  34 +398 372
  35 +400 1071
  36 +401 658
  37 +410 236
  38 +419 585
  39 +421 421
  40 +433 101
  41 +433 182
  42 +433 793
  43 +435 492
  44 +471 341
  45 +474 515
  46 +479 244
  47 +480 1012
  48 +484 310
  49 +485 873
  50 +489 95
  51 +498 174
  52 +501 443
  53 +501 772
  54 +504 388
  55 +524 338
  56 +529 239
  57 +531 488
  58 +544 556
  59 +558 411
  60 +561 99
  61 +562 276
  62 +566 728
  63 +574 624
  64 +574 1044
  65 +578 220
  66 +580 146
  67 +586 44
  68 +605 326
  69 +606 385
  70 +611 536
  71 +620 95
  72 +625 692
  73 +636 458
  74 +642 213
  75 +645 578
  76 +650 37
  77 +653 283
  78 +656 735
  79 +659 387
  80 +669 106
  81 +698 528
  82 +700 460
  83 +703 10
  84 +708 1073
  85 +711 382
  86 +713 884
  87 +715 292
  88 +715 667
  89 +721 197
  90 +724 735
  91 +731 233
  92 +736 57
  93 +737 582
  94 +746 638
  95 +748 158
  96 +763 483
  97 +775 706
  98 +777 202
  99 +779 531
  100 +779 950
  101 +787 599
  102 +793 102
  103 +793 322
  104 +794 1074
  105 +797 368
  106 +816 278
  107 +829 478
  108 +831 648
  109 +836 191
  110 +840 730
  111 +847 106
  112 +847 938
  113 +849 559
  114 +850 377
  115 +854 814
  116 +874 676
  117 +875 215
  118 +877 329
  119 +879 174
  120 +896 438
  121 +897 22
  122 +904 868
  123 +906 733
  124 +909 217
  125 +910 265
  126 +918 589
  127 +930 645
  128 +931 143
  129 +937 492
  130 +937 690
  131 +945 824
  132 +947 234
  133 +949 408
  134 +965 310
  135 +970 88
  136 +979 135
  137 +979 450
  138 +979 539
  139 +981 290
  140 +999 213
  141 +999 937
  142 +1003 1007
  143 +1004 380
  144 +1019 832
  145 +1029 183
  146 +1029 312
  147 +1035 744
  148 +1036 68
  149 +1063 556
  150 +1083 165
  151 +1083 423
  152 +1092 729
  153 +1099 11
  154 +1099 344
  155 +1104 241
  156 +1117 106
  157 +1118 827
  158 +1129 666
  159 +1133 485
  160 +1149 19
  161 +1157 152
  162 +1159 570
  163 +1160 410
  164 +1176 325
  165 +1179 244
  166 +1185 702
  167 +1189 778
  168 +1192 472
  169 +1217 559
  170 +1222 202
  171 +1244 95
  172 +1245 310
  173 +1251 255
  174 +1252 142
  175 +1253 422
  176 +1278 474
  177 +1280 567
  178 +1304 177
  179 +1309 710
  180 +1338 329
  181 +1339 255
  182 +1339 413
  183 +1363 555
  184 +1363 678
  185 +1364 489
  186 +1367 180
  187 +1369 107
  188 +1384 774
  189 +1405 339
  190 +1447 624
  191 +1453 426
  192 +1461 133
  193 +1462 357
  194 +1473 853
  195 +1488 500
  196 +1488 766
  197 +1516 642
  198 +1551 484
  199 +1578 837
  200 +1588 331
  201 +1603 741
  202 +1632 628
  203 +1635 367
  204 +1641 472
  205 +1654 566
  206 +1686 924
  207 +1704 819
  208 +1754 694
  209 +1777 785
  210 +1852 381
0 211 \ No newline at end of file
... ...
data/blue_t.txt 0 → 100644
  1 +++ a/data/blue_t.txt
  1 +2 680
  2 +28 535
  3 +44 588
  4 +57 786
  5 +66 556
  6 +73 463
  7 +100 368
  8 +101 657
  9 +113 1037
  10 +116 303
  11 +148 670
  12 +186 325
  13 +186 985
  14 +191 1075
  15 +193 627
  16 +205 562
  17 +218 387
  18 +220 875
  19 +244 749
  20 +245 631
  21 +246 491
  22 +252 287
  23 +259 444
  24 +274 196
  25 +283 1075
  26 +300 543
  27 +300 980
  28 +302 685
  29 +316 464
  30 +324 340
  31 +332 842
  32 +338 306
  33 +344 408
  34 +381 518
  35 +387 998
  36 +397 371
  37 +398 306
  38 +402 1070
  39 +406 661
  40 +409 237
  41 +419 583
  42 +425 420
  43 +433 182
  44 +434 100
  45 +436 797
  46 +442 494
  47 +472 339
  48 +473 519
  49 +478 246
  50 +479 322
  51 +484 873
  52 +488 1004
  53 +490 94
  54 +498 174
  55 +503 773
  56 +504 442
  57 +507 388
  58 +525 338
  59 +527 243
  60 +535 487
  61 +543 558
  62 +559 416
  63 +561 98
  64 +563 278
  65 +569 731
  66 +573 625
  67 +577 223
  68 +577 1036
  69 +583 145
  70 +586 43
  71 +606 327
  72 +607 387
  73 +611 536
  74 +620 98
  75 +628 690
  76 +634 458
  77 +644 215
  78 +644 582
  79 +648 36
  80 +652 286
  81 +656 740
  82 +660 386
  83 +669 105
  84 +697 531
  85 +700 461
  86 +707 0
  87 +709 1075
  88 +713 381
  89 +715 666
  90 +715 883
  91 +717 295
  92 +724 204
  93 +726 741
  94 +731 230
  95 +737 587
  96 +739 57
  97 +744 157
  98 +744 641
  99 +764 479
  100 +774 950
  101 +778 706
  102 +780 205
  103 +781 531
  104 +790 603
  105 +792 314
  106 +794 104
  107 +795 1075
  108 +798 374
  109 +817 282
  110 +832 478
  111 +832 647
  112 +837 193
  113 +842 731
  114 +846 104
  115 +847 382
  116 +848 814
  117 +851 562
  118 +854 936
  119 +877 213
  120 +878 172
  121 +878 333
  122 +880 674
  123 +897 26
  124 +897 437
  125 +903 220
  126 +906 870
  127 +911 264
  128 +913 737
  129 +918 591
  130 +933 142
  131 +936 494
  132 +936 649
  133 +946 690
  134 +946 821
  135 +947 232
  136 +954 405
  137 +970 89
  138 +970 303
  139 +977 136
  140 +983 542
  141 +985 451
  142 +995 934
  143 +1002 209
  144 +1006 381
  145 +1007 1011
  146 +1024 189
  147 +1025 834
  148 +1029 311
  149 +1031 744
  150 +1035 70
  151 +1064 557
  152 +1082 164
  153 +1083 423
  154 +1094 733
  155 +1099 12
  156 +1101 342
  157 +1105 244
  158 +1116 828
  159 +1120 103
  160 +1123 661
  161 +1130 488
  162 +1149 23
  163 +1156 572
  164 +1157 154
  165 +1161 411
  166 +1176 244
  167 +1177 326
  168 +1187 702
  169 +1195 780
  170 +1196 472
  171 +1219 563
  172 +1221 203
  173 +1242 315
  174 +1244 94
  175 +1250 258
  176 +1251 143
  177 +1253 423
  178 +1277 862
  179 +1281 479
  180 +1283 570
  181 +1302 712
  182 +1306 176
  183 +1336 331
  184 +1338 258
  185 +1338 415
  186 +1363 490
  187 +1365 559
  188 +1365 683
  189 +1367 181
  190 +1369 106
  191 +1384 777
  192 +1401 338
  193 +1404 883
  194 +1436 629
  195 +1452 429
  196 +1462 132
  197 +1464 363
  198 +1474 859
  199 +1481 504
  200 +1485 772
  201 +1516 646
  202 +1550 487
  203 +1578 841
  204 +1585 331
  205 +1601 744
  206 +1629 632
  207 +1636 370
  208 +1639 473
  209 +1649 569
  210 +1683 928
  211 +1699 823
  212 +1750 700
  213 +1771 787
  214 +1848 384
... ...
main.cpp 0 → 100644
  1 +++ a/main.cpp
  1 +#include <iostream>
  2 +#include <fstream>
  3 +#include <vector>
  4 +#include <string>
  5 +#include <fstream>
  6 +#include <stim/math/vector.h>
  7 +#include <stim/parser/arguments.h>
  8 +#include <stim/parser/filename.h>
  9 +#include <stim/image/image.h>
  10 +#include <ANN/ANN.h>
  11 +
  12 +//load a set of points from an ASCII file
  13 +std::vector< stim::vec<float> > points_from_list(std::string filename){
  14 +
  15 + std::vector< stim::vec<float> > result; //create an array to store the result
  16 +
  17 + std::string str;
  18 +
  19 + //load the ground truth
  20 + std::ifstream gfile(filename.c_str());
  21 + while(std::getline(gfile, str)){
  22 + stim::vec<float> v(str);
  23 + result.push_back(v);
  24 + }
  25 +
  26 + return result; //return the list of points
  27 +}
  28 +
  29 +//load a set of points from an image (nonzero values are point positions)
  30 +std::vector< stim::vec<float> > points_from_image(std::string filename){
  31 +
  32 + stim::image<unsigned char> I; //create an image object
  33 +
  34 + I.load(filename); //load the image file
  35 +
  36 + std::vector<unsigned long> idx = I.sparse_idx(); //get the 1D indices for each nonzero pixel
  37 +
  38 + std::vector< stim::vec<float> > result; //generate an array to store the 2D pixel positions
  39 + result.resize(idx.size()); //allocate the space to save time
  40 +
  41 + unsigned long w = I.width(); //get the image width (used to resolve the 2D pixel position from the 1D index)
  42 +
  43 + unsigned long x, y;
  44 + for(unsigned long i = 0; i < idx.size(); i++){
  45 + y = idx[i] / w;
  46 + x = idx[i] - y * w;
  47 +
  48 + result[i] = stim::vec<float>(x, y);
  49 + }
  50 +
  51 +
  52 + return result; //return the array of points
  53 +
  54 +}
  55 +
  56 +/// This function calculates the number of hits (
  57 +void calc_hitlist(std::vector< unsigned int >& hits,
  58 + std::vector< float >& dists,
  59 + std::vector< stim::vec<float> > data,
  60 + std::vector< stim::vec<float> > query){
  61 +
  62 + int n_data = data.size();
  63 + int n_query = query.size();
  64 +
  65 + //allocate space in the hit lists
  66 + hits.resize(n_query);
  67 + dists.resize(n_query);
  68 +
  69 + //calculate the spatial dimension
  70 + unsigned int dim = 1;
  71 + for(unsigned int i = 0; i < data.size(); i++)
  72 + if(data[i].size() > dim) dim = data[i].size();
  73 +
  74 + //number of data points
  75 + ANNpointArray dataPts = annAllocPts(n_data, dim); //array of data points
  76 + ANNpoint queryPt = annAllocPt(dim); //query point
  77 + ANNidxArray nnIdx = new ANNidx[1]; //indices of nearest neighbors
  78 + ANNdistArray sq_dist = new ANNdist[1]; //array of squared distances to nearest neighbors
  79 +
  80 + //load the ground truth points into the ANN point array
  81 + for(unsigned int i = 0; i < data.size(); i++){
  82 + for(unsigned int d = 0; d < dim; d++){
  83 + dataPts[i][d] = data[i][d];
  84 + }
  85 + }
  86 +
  87 + //create a KD-tree
  88 + ANNkd_tree* kdTree; //KD tree search structure
  89 + kdTree = new ANNkd_tree(dataPts, n_data, dim); //create the KD tree search structure
  90 +
  91 +
  92 + //submit each query point to the KD tree to find the nearest neighbor
  93 + for(unsigned int q = 0; q < n_query; q++){
  94 +
  95 + for(unsigned int d = 0; d < dim; d++){
  96 + queryPt[d] = query[q][d];
  97 + }
  98 +
  99 + //query the KD-tree
  100 + kdTree->annkSearch(queryPt, 1, nnIdx, sq_dist);
  101 +
  102 + //put the result in the hit array
  103 + hits[q] = nnIdx[0];
  104 + dists[q] = sqrt(sq_dist[0]);
  105 + }
  106 +}
  107 +
  108 +int main(int argc, char** argv){
  109 +
  110 + //output advertisement
  111 + std::cout<<std::endl<<std::endl;
  112 + std::cout<<"========================================================================="<<std::endl;
  113 + std::cout<<"Thank you for using the PointMets validation tool!"<<std::endl;
  114 + std::cout<<"Scalable Tissue Imaging and Modeling (STIM) Lab, University of Houston"<<std::endl;
  115 + std::cout<<"Developers: David Mayerich"<<std::endl;
  116 + std::cout<<"Source: https://github.com/stimlab/hsiproc.git"<<std::endl;
  117 + std::cout<<"========================================================================="<<std::endl<<std::endl;
  118 +
  119 +
  120 + stim::arglist args;
  121 +
  122 +#ifdef _WIN32
  123 + args.set_ansi(false);
  124 +#endif
  125 +
  126 + //add arguments
  127 + args.add("help", "prints this help");
  128 + args.add("r", "maximum possible distance to consider a point 'detected'", "10", "[positive value]");
  129 +
  130 + //parse the command line arguments
  131 + args.parse(argc, argv);
  132 +
  133 + //display the help text if requested
  134 + if(args["help"].is_set()){
  135 + std::cout<<std::endl<<"usage: pointmets ground_truth test_case --option [A B C ...]"<<std::endl;
  136 + std::cout<<std::endl<<std::endl
  137 + << "examples: pointmets blue_gt.txt blue_t.txt"<<std::endl;
  138 + std::cout << " pointmets blue_gt.bmp blue_t.bmp" << std::endl;
  139 + std::cout<<std::endl<<std::endl;
  140 + std::cout<<args.str()<<std::endl;
  141 + exit(1);
  142 + }
  143 +
  144 + //if the input and output files aren't specified, throw an error and exit
  145 + if(args.nargs() < 2){
  146 + std::cout<<"ERROR: Two files must be specified for comparison, enter pointmets --help for options."<<std::endl<<std::endl;
  147 + exit(1);
  148 + }
  149 +
  150 + //get the ground truth and test file
  151 + stim::filename gfilename(args.arg(0));
  152 + stim::filename tfilename(args.arg(1));
  153 +
  154 + //set the radius
  155 + float r = args["r"].as_float();
  156 +
  157 + std::vector< stim::vec<float> > G;
  158 + std::vector< stim::vec<float> > T;
  159 +
  160 +
  161 + //if an ASCII list of points is specified
  162 + if(gfilename.get_extension() == "bmp")
  163 + G = points_from_image(gfilename.str());
  164 + else
  165 + G = points_from_list(gfilename.str());
  166 +
  167 + if(tfilename.get_extension() == "bmp")
  168 + T = points_from_image(gfilename.str());
  169 + else
  170 + T = points_from_list(tfilename.str());
  171 +
  172 + //calculate the hit list and distances for the test array
  173 + std::vector< unsigned int > T_hits;
  174 + std::vector< float > T_dists;
  175 + calc_hitlist(T_hits, T_dists, G, T);
  176 +
  177 + //calculate the hit list and distances for the ground truth array
  178 + std::vector< unsigned int > G_hits;
  179 + std::vector< float > G_dists;
  180 + calc_hitlist(G_hits, G_dists, T, G);
  181 +
  182 + //count up metrics for each test point
  183 + std::vector< unsigned int > TP;
  184 + std::vector< unsigned int > FP;
  185 + unsigned int g, t;
  186 + for(t = 0; t < T.size(); t++){
  187 +
  188 + //a true positive has a matching hit in both hit lists, with a distance less than the radius
  189 + g = T_hits[t];
  190 + if(G_hits[g] == t && T_dists[t] <= r) TP.push_back(t);
  191 + else FP.push_back(t);
  192 + }
  193 +
  194 + std::vector< unsigned int > FN;
  195 + for(g = 0; g < G.size(); g++){
  196 + t = G_hits[g];
  197 + if(T_hits[t] != g || G_dists[g] > r) FN.push_back(g);
  198 + }
  199 +
  200 + std::cout<<"N: "<<G.size()<<std::endl;
  201 + std::cout<<"TP: "<<TP.size()<<" ( "<<(double)TP.size() / (double)G.size() * 100<<"% detected)"<<std::endl;
  202 + std::cout<<"FN: "<<FN.size()<<" ( "<<(double)FN.size() / (double)G.size() * 100<<"% undetected)"<<std::endl;
  203 + std::cout<<"FP: "<<FP.size()<<" ( "<<(double)FP.size() / (double)T.size() * 100<<"% incorrectly detected)"<<std::endl;
  204 +
  205 +
  206 +
  207 +}
... ...