URL:
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-03-19 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Add a new file translating IGR Matlab code.
* fabien/bin/dump2pbm.cc: Minor fix.
* fabien/igr/Makefile: Update.
* fabien/igr/check.sh: Update.
* fabien/igr/matlab.cc: New file translating matlab code.
* fabien/igr/med.cc: Update.
* fabien/igr/thres.cc: Update.
* fabien/magick/load.hh: Moved to mln/io/magick.
* fabien/magick/magick.cc: Update.
---
TODO | 12 +++--
bin/dump2pbm.cc | 28 +++++++++---
igr/Makefile | 3 +
igr/check.sh | 10 ++--
igr/matlab.cc | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
igr/med.cc | 47 ++++++++++++++++++++
igr/thres.cc | 7 ++-
magick/magick.cc | 9 +++
8 files changed, 223 insertions(+), 19 deletions(-)
Index: trunk/milena/sandbox/fabien/igr/matlab.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/matlab.cc (revision 0)
+++ trunk/milena/sandbox/fabien/igr/matlab.cc (revision 3545)
@@ -0,0 +1,126 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+#include <mln/core/image/image_if.hh>
+#include <mln/core/image/cast_image.hh>
+#include <mln/core/image/slice_image.hh>
+#include <mln/core/routine/duplicate.hh>
+
+#include <mln/value/int_u12.hh>
+
+#include <mln/io/dicom/load.hh>
+
+#include <mln/accu/count.hh>
+#include <mln/accu/mean.hh>
+#include <mln/accu/sum.hh>
+#include <mln/accu/image/all.hh>
+#include <mln/arith/minus.hh>
+#include <mln/data/fill.hh>
+#include <mln/data/paste.hh>
+#include <mln/level/compute.hh>
+#include <mln/math/abs.hh>
+#include <mln/pw/all.hh>
+#include <mln/trait/concrete.hh>
+#include <mln/util/array.hh>
+
+#include <cmath>
+
+using namespace mln;
+
+
+inline
+image2d<float> mean_slices(util::array<image2d<float> >& arr_ima,
int first, int last)
+{
+ image2d<accu::mean<float> > result;
+
+ mln_precondition(first >=0 && first < arr_ima.nelements());
+ mln_precondition(last >=0 && last < arr_ima.nelements());
+
+ accu::image::init(result);
+ for (int i = first; i < last; ++i)
+ accu::image::take(result, arr_ima[i]);
+
+ return accu::image::to_result(result);
+}
+
+
+int main(int argc, char* argv[])
+{
+ if (argc != 2)
+ {
+ std::cout << "Usage: " << argv[0] << "input"
<< std::endl;
+ return 1;
+ }
+
+ image3d<value::int_u12> input;
+ io::dicom::load(input, argv[1]);
+ util::array<image2d<float> > arr_ima;
+ for (int i = 0; i < input.nslices(); ++i)
+ arr_ima.append(duplicate(cast_image<float>(slice(input, i))));
+
+ int acqui = 3; // durée acqui et temps interimages; en secondes
+ int fseuil = 4; // ratio entre signaux trop faibles, éliminés, et bruit de fond mesuré
sur l image
+ int ini = 9; // nombre images ligne de base
+ int ini2 = 20; // a la fin de la montée vasculaire, à la dixieme image post injection:
lissage des images par trois
+
+ // Calcul signal initialmoyen : 8 images de 2 à 9 moyennées=ligne de base
+ image2d<float> imageini = mean_slices(arr_ima, 1, 8);
+
+ int dim1 = imageini.nrows();
+ int dim2 = imageini.ncols();
+ int dim3 = arr_ima.nelements();
+
+ // Calcul auc aire sous la courbe
+ util::array<image2d<float> > arr_sous;
+ for (int k = 0; k < arr_ima.nelements(); ++k)
+ arr_sous.append(arr_ima[k] - imageini);
+
+ // Mesure bruit de fond pour seuiller
+ // calculé sur la première image
+ image2d<bool> roi_noise; // FIXME: init this ROI, should be a domain
+ accu::count<bool> accu_nbrpix1;
+ unsigned nbrpix1 = level::compute(accu_nbrpix1, roi_noise);
+ image2d<float> datasli = arr_ima[0];
+
+ image2d<float> prodsignal1;
+ data::fill(prodsignal1, 0.0);
+ data::paste(datasli | pw::value(roi_noise) == pw::cst(true), prodsignal1);
+
+ // moyenne
+ accu::mean<float> accu_mean;
+ float moysignal1 = level::compute(accu_mean, prodsignal1 | pw::value(roi_noise) ==
pw::cst(true));
+ // ecart type
+ int som1 = 0;
+ int kk = 0;
+ mln_piter_(image2d<float>) p(datasli.domain());
+ for_all(p)
+ {
+ if (roi_noise(p))
+ som1 += std::pow(math::abs(datasli(p) - moysignal1), 2);
+ }
+ float ectys = std::sqrt(som1 / (nbrpix1 - 1));
+ float seuil = fseuil * ectys;
+
+ // Calcul du masque
+ image2d<bool> masque; // FIXME: init this ROI, should be a domain
+ initialize(masque, datasli);
+ data::fill(masque, false)
+ data::fill(masque | pw::value(datasli) > pw::cst(seuil), true);
+ // si on a choisi une région avec roi2
+ if (nargin>2)
+ masque=masque.*roi2;
+
+ //on applique le masque sur image et imasoustraite
+
+ for k=2:dim3
+ for i=1:dim1
+ for j=1:dim2
+ if(masque(i,j)==0)
+ image(i,j,k)=0;
+ imasoustraite(i,j,k)=0;
+ end;
+ end;
+ end;
+ end;
+
+ return 0;
+}
Index: trunk/milena/sandbox/fabien/igr/check.sh
===================================================================
--- trunk/milena/sandbox/fabien/igr/check.sh (revision 3544)
+++ trunk/milena/sandbox/fabien/igr/check.sh (revision 3545)
@@ -15,11 +15,11 @@
echo " nbasins = $nbasins"
../bin/dumpl32_to_colorize wst.dump $dim $nbasins
results/colorize_${3}_${lambda_closing}.ppm
median=`./med wst.dump $dim $input $nbasins`
- echo " median = $median"
+#echo " median = $median"
threshold=$(($median / 2))
../bin/dumpi12_to_pgm med.dump $dim results/median_${3}_${lambda_closing}.pgm
./thres med.dump $dim $threshold
- mv result.pbm results/result_${3}_${lambda_closing}.pbm
+ ../bin/dump2pbm result.dump $dim results/result_${3}_${lambda_closing}.pbm
#if [ $2 -eq 2 ]; then
# if [ ${lambda_closing} -eq 100 ]; then
@@ -39,8 +39,8 @@
}
process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0049.dcm" 2
"49"
-#process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0052.dcm" 3
"52"
+process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0052.dcm" 3
"52"
process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0055.dcm" 2
"55"
process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0058.dcm" 2
"58"
-#process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0061.dcm" 3
"61"
-#process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0064.dcm" 3
"64"
+process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0061.dcm" 3
"61"
+process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0064.dcm" 3
"64"
Index: trunk/milena/sandbox/fabien/igr/med.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/med.cc (revision 3544)
+++ trunk/milena/sandbox/fabien/igr/med.cc (revision 3545)
@@ -63,6 +63,8 @@
}
unsigned median = 0;
+ int bg = 0;
+ int fg = 0;
if (dim == 2)
{
@@ -88,14 +90,57 @@
accu::median_h<int_u12> accu_med;
median = level::compute(accu_med, ima_histo | pw::value(ima_histo) != pw::cst(0));
+ for (int i = 0; i < histogram.nvalues(); ++i)
+ {
+ if (histogram[i])
+ {
+ if (histogram[i] > median / 2)
+ ++fg;
+ else ++bg;
+ }
+ }
+
io::dump::save(wst_mean, "med.dump");
}
else
{
- // FIXME
+ image3d<L> labels;
+ io::dump::load(labels, argv[1]);
+ image3d<int_u12> dcm;
+ io::dicom::load(dcm, argv[3]);
+
+ mln_VAR(wst_dilate, morpho::elementary::dilation(extend(labels | (pw::value(labels)
== 0u), labels), c26()));
+ data::fill((labels | (pw::value(labels) == 0u)).rw(), wst_dilate);
+ mln_VAR(wst_mean, labeling::mean_values(dcm, labels, nbasins));
+
+ histo::array<int_u12> histogram = histo::compute(wst_mean);
+ int j = 0;
+ int k = 0;
+ for (int i = 0; i < histogram.nvalues(); ++i)
+ {
+ if (histogram[i])
+ histogram[i] = i;
+ }
+ image1d<unsigned> ima_histo;
+ convert::from_to(histogram, ima_histo);
+ accu::median_h<int_u12> accu_med;
+ median = level::compute(accu_med, ima_histo | pw::value(ima_histo) != pw::cst(0));
+
+ for (int i = 0; i < histogram.nvalues(); ++i)
+ {
+ if (histogram[i])
+ {
+ if (histogram[i] > median / 2)
+ ++fg;
+ else ++bg;
+ }
+ }
+
+ io::dump::save(wst_mean, "med.dump");
}
std::cout << median << std::endl;
+ std::cerr << " [ " << bg << " <" <<
median / 2 << "> " << fg << " ]" <<
std::endl;
return 0;
}
Index: trunk/milena/sandbox/fabien/igr/thres.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/thres.cc (revision 3544)
+++ trunk/milena/sandbox/fabien/igr/thres.cc (revision 3545)
@@ -56,11 +56,14 @@
image2d<int_u12> input;
io::dump::load(input, argv[1]);
image2d<bool> bin_result = binarization::threshold(input, threshold);
- io::pbm::save(bin_result, "result.pbm");
+ io::dump::save(bin_result, "result.dump");
}
else
{
- // FIXME
+ image3d<int_u12> input;
+ io::dump::load(input, argv[1]);
+ image3d<bool> bin_result = binarization::threshold(input, threshold);
+ io::dump::save(bin_result, "result.dump");
}
return 0;
Index: trunk/milena/sandbox/fabien/igr/Makefile
===================================================================
--- trunk/milena/sandbox/fabien/igr/Makefile (revision 3544)
+++ trunk/milena/sandbox/fabien/igr/Makefile (revision 3545)
@@ -48,5 +48,8 @@
thres: thres.cc
g++ -I../../../ ${CXXFLAGS} $^ -o thres
+matlab: matlab.cc
+ g++ -I../../../ ${DICOM_INC} ${DICOM_LIBS} ${CXXFLAGS} -lm $^ -o matlab
+
clean:
rm -rf *.dump *.p?m *.plot *.log *.csv *.dSYM
Index: trunk/milena/sandbox/fabien/TODO
===================================================================
--- trunk/milena/sandbox/fabien/TODO (revision 3544)
+++ trunk/milena/sandbox/fabien/TODO (revision 3545)
@@ -30,7 +30,13 @@
[X] Test 3D workflow on 2D images
[X] Create colorized colors for graph
[X] Diff with %
-[ ] Find biggest dark regions (threshold value or median accu - median / 2 - )
- [ ] Learn regions value
- [ ] Threshold
+[X] Find biggest dark regions (threshold value or median accu - median / 2 - )
+ [X] Learn regions value
+ [X] Threshold
+ [X] 3D
+ [X] Print nb bg regions // nb fg objets
[ ] Profile for performance
+[ ] ImageMagick support
+[ ] Integrate external libraries (GDCM, IM)
+[ ] Send result images to lrde account
+[ ] Translate Matlab code
Index: trunk/milena/sandbox/fabien/bin/dump2pbm.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dump2pbm.cc (revision 3544)
+++ trunk/milena/sandbox/fabien/bin/dump2pbm.cc (revision 3545)
@@ -1,5 +1,6 @@
-
#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+#include <mln/core/image/slice_image.hh>
#include <mln/make/image3d.hh>
#include <mln/debug/slices_2d.hh>
@@ -12,7 +13,7 @@
void usage(char* argv[])
{
- std::cerr << "usage: " << argv[0] << " input.dump
output.pbm" << std::endl;
+ std::cerr << "usage: " << argv[0] << " input.dump dim
output.pbm" << std::endl;
abort();
}
@@ -23,13 +24,28 @@
using namespace mln;
using value::int_u16;
- if (argc != 3)
+ if (argc != 4)
usage(argv);
+ unsigned dim = atoi(argv[2]);
+ if (dim != 2 && dim != 3)
+ {
+ std::cout << "dimensions invalid" << std::endl;
+ return 1;
+ }
+
+ if (dim == 2)
+ {
+ image2d<bool> ima;
+ io::dump::load(ima, argv[1]);
+ io::pbm::save(ima, argv[3]);
+ }
+ else
+ {
image3d<bool> vol;
io::dump::load(vol, argv[1]);
- int_u16 bg = 0;
- image2d<bool> ima = debug::slices_2d(vol, 1.f, bg);
- io::pbm::save(ima, argv[2]);
+ image2d<bool> ima = debug::slices_2d(vol, 1.f, false);
+ io::pbm::save(ima, argv[3]);
+ }
}
Index: trunk/milena/sandbox/fabien/magick/load.hh (deleted)
===================================================================
Index: trunk/milena/sandbox/fabien/magick/magick.cc
===================================================================
--- trunk/milena/sandbox/fabien/magick/magick.cc (revision 3544)
+++ trunk/milena/sandbox/fabien/magick/magick.cc (revision 3545)
@@ -1,11 +1,15 @@
#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
#include <mln/value/rgb8.hh>
-#include "load.hh"
+#include <mln/io/magick/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/pbm/save.hh>
int main(int argc, char* argv[])
{
using namespace mln;
+ using value::int_u8;
using value::rgb8;
if (argc != 2)
@@ -14,9 +18,10 @@
return 1;
}
- image2d<rgb8> lena;
+ image2d<bool> lena;
io::magick::load(lena, argv[1]);
+ io::pbm::save(lena, "result.pbm");
return 0;
}