CC Localization
localization.cc
Go to the documentation of this file.
1 #include "tiff.hh"
3 #include "nelder_mead.hh"
4 #include "utils.hh"
5 #include <iostream>
6 #include <cmath>
7 
9 double psf_ig2(double x, double y, double const * p)
10 {
11  double s2s = sqrt(2)*p[2]*p[2];
12  double ex = (erf((x-p[0]+.5)/s2s)-erf((x-p[0]-.5)/s2s))*.5;
13  double ey = (erf((y-p[1]+.5)/s2s)-erf((y-p[1]-.5)/s2s))*.5;
14  return ex*ey*p[3]*p[3]+p[4]*p[4];
15 }
16 
18 double likelihood(
19  double const * i,
20  int l,
21  int w,
22  double const * p
23 )
24 {
25  double tl = 0;
26  for (int y = 0; y<l; y++) for (int x = 0; x<l; x++) {
27  auto psf = psf_ig2(x,y,p);
28  tl += i[y*w+x]*log(psf)-psf;
29  }
30  return -tl;
31 }
32 
33 // additional parameters for function
34 double const * fn_im;
35 int fn_w;
36 unsigned fn_cnt;
37 
39 double fn(double const * p)
40 {
41  fn_cnt ++;
42  return likelihood(fn_im, 9, fn_w, p);
43 }
44 
47  double const * data,
48  int w,
49  int h
50 )
51 {
52  // convolution kernels
53  double const wk1[] = {1./16,1./4,3./8,1./4,1./16};
54  double const wk2[] = {1./16,0,1./4,0,3./8,0,1./4,0,1./16};
55  auto sz = w*h;
56  // workspace
57  std::vector<double> bf(sz);
58 
59  // calculate v1,f1
60  std::vector<double> v1(sz);
61  for (auto i = 0; i<sz; i++) {
62  auto x = i%w;
63  double s = 0;
64  auto r1 = x+2<w?5:w+2-x;
65  for (auto j = x<2?2-x:0; j<r1; j++) s += data[i+j-2]*wk1[j];
66  bf[i] = s;
67  }
68  double f1a = 0;
69  double f1a2 = 0;
70  for (auto i = 0; i<sz; i++) {
71  auto y = i/w;
72  double s = 0;
73  auto r1 = y+2<h?5:h+2-y;
74  for (auto j = y<2?2-y:0; j<r1; j++) s += bf[i+j*w-2*w]*wk1[j];
75  v1[i] = s;
76  double f1 = data[i]-s;
77  f1a += f1;
78  f1a2 += f1*f1;
79  }
80  f1a /= sz;
81  f1a2 /= sz;
82  double threshold = 1.5*sqrt(f1a2-f1a*f1a);
83  debug << "threshold = " << threshold << '\n';
84 
85  // calculate f2
86  std::vector<double> f2(sz);
87  for (auto i = 0; i<sz; i++) {
88  auto x = i%w;
89  double s = 0;
90  auto r1 = x+4<w?9:w+4-x;
91  for (auto j = x<4?4-x:0; j<r1; j++) s += v1[i+j-4]*wk2[j];
92  bf[i] = s;
93  }
94  for (auto i = 0; i<sz; i++) {
95  auto y = i/w;
96  double s = 0;
97  auto r1 = y+4<h?9:h+4-y;
98  for (auto j = y<4?4-y:0; j<r1; j++) s += bf[i+j*w-4*w]*wk2[j];
99  f2[i] = v1[i]-s;
100  }
101 
102  // find 8-connected local maximum by forward elimination
103  std::vector<int> nd{1,w+1,w,w-1};
104  std::vector<bool> n8(sz,true);
105  double stps[] = {1,1,0.2,1,1}; // step size
106  auto ne = sz-w-1;
107  for (int i = 0; i<ne; i++) {
108  for (auto d: nd) {
109  if (f2[i]>f2[i+d]) n8[i+d] = false;
110  else n8[i] = false;
111  }
112  int x = i%w;
113  int y = i/w;
114  if (n8[i]&&x>=4&&x<w-4&&y>=4&&y<h-4&&f2[i]>threshold) {
115  // a local maximum, perform fitting to PSF
116  double const * sq = data+i-(w+1)*4; // keeping starting corner of square
117  // initial guess
118  double mx = sq[0];
119  double mn = sq[0];
120  for (int y = 0; y<9; y++) for (int x = 0; x<9; x++) {
121  auto vv = sq[y*w+x];
122  if (vv>mx) mx = vv;
123  else if (vv<mn) mn = vv;
124  }
125  double p[] = {4,4,sqrt(1.6),sqrt(mx-mn),sqrt(mn)};
126  fn_im = sq;
127  fn_w = w;
128  fn_cnt = 0;
129  nelder_mead(&fn, 5, p, stps);
130  std::string s = "[";
131  for (int i = 0; i<5; i++) {
132  std::cout << s << p[i];
133  s = ", ";
134  }
135  std::cout << "]\n";
136  }
137  }
138 }
139 
140 
141 
142 
143 
145 int main(int argc, char ** argv)
146 {
147  if (argc<2) {
148  std::cerr << "Missing expected filename!\nUsage:\n";
149  std::cerr << '\t' << argv[0] << " <filename of TIFF>\n\n";
150  return EXIT_FAILURE;
151  }
152 
153  Tiff tf(std::make_shared<std::ifstream>(argv[1]));
154  tf.start();
155 
156  uint32_t nxt = 0;
157  unsigned icnt = 0;
158  do {
159  nxt = tf.parse_ifd(nxt);
160  auto w = tf.image_width;
161  auto h = tf.image_length;
162  auto sz = w*h;
163  auto imd = tf.read_image();
164  uint16_t * v = reinterpret_cast<uint16_t *>(imd.data());
165  // convert to double
166  std::vector<double> im(v,v+sz);
167  std::cout << "\n\n\nicnt = " << icnt << "\n===================\n";
168  process_image(im.data(), w, h);
169  icnt ++;
170  } while (nxt);
171  return 0;
172 }
double fn(double const *p)
Function to be minimized.
Definition: localization.cc:39
double nelder_mead(func_t f, int n, double *x, double const *steps, double mxrngy, double mxrngx, int mxiter)
Perform minimization with Nelder–Mead method.
Definition: nelder_mead.cc:12
TIFF file processor.
Definition: tiff.hh:13
double psf_ig2(double x, double y, double const *p)
Point-spread function with integrated Gaussian.
Definition: localization.cc:9
std::vector< char > read_image()
Definition: tiff.cc:168
uint32_t image_width
width of image
Definition: tiff.hh:125
uint32_t image_length
length of image
Definition: tiff.hh:126
double likelihood(double const *i, int l, int w, double const *p)
negative Likelihood calculation for given parameter
Definition: localization.cc:18
double const * fn_im
cropped square image data
Definition: localization.cc:34
void process_image(double const *data, int w, int h)
Process a single 2D image.
Definition: localization.cc:46
int main(int argc, char **argv)
Main function for localization.
int fn_w
image width
Definition: localization.cc:35
void start()
Definition: tiff.cc:113
unsigned fn_cnt
count of function calls
Definition: localization.cc:36
Nelder–Mead method for function minimization.
std::ostream & debug
stream for debug messages
Definition: utils.cc:53
Miscellaneous utilities.
uint32_t parse_ifd(uint32_t i=0)
Parse image file directory (IFD)
Definition: tiff.cc:127
Class for processing TIFF file.