1 #ifndef boxm2_change_detection_functor_h
2 #define boxm2_change_detection_functor_h
3 //:
4 // \file
5 
6 #include <iostream>
7 #include <boxm2/boxm2_data_traits.h>
8 #include <boxm2/cpp/algo/boxm2_cast_ray_function.h>
9 #include <boxm2/cpp/algo/boxm2_mog3_grey_processor.h>
10 #include <vil/algo/vil_gauss_filter.h>
11 #ifdef DEBUG
12 #ifdef _MSC_VER
13 #  include <vcl_msvc_warnings.h>
14 #endif
15 #endif
16 
17 class boxm2_change_detection_functor
18 {
19  public:
20   //: "default" constructor
21   boxm2_change_detection_functor() = default;
22 
init_data(std::vector<boxm2_data_base * > & datas,vil_image_view<float> * in_img,vil_image_view<float> * expected,vil_image_view<float> * vis_img)23   bool init_data(std::vector<boxm2_data_base*> & datas,vil_image_view<float> * in_img, vil_image_view<float> * expected, vil_image_view<float>* vis_img)
24   {
25       alpha_data_=new boxm2_data<BOXM2_ALPHA>(datas[0]->data_buffer(),datas[0]->buffer_length(),datas[0]->block_id());
26       mog3_data_=new boxm2_data<BOXM2_MOG3_GREY>(datas[1]->data_buffer(),datas[1]->buffer_length(),datas[1]->block_id());
27       expected_img_=expected;
28       vis_img_     =vis_img;
29       in_img_     =in_img;
30       return true;
31   }
32 
33   inline bool step_cell(float seg_len,int index,unsigned i, unsigned j, float abs_depth=0.0)
34   {
35     boxm2_data<BOXM2_ALPHA>::datatype alpha=alpha_data_->data()[index];
36     float vis=(*vis_img_)(i,j);
37     float exp_int=(*expected_img_)(i,j);
38     float intensity=(*in_img_)(i,j);
39     float curr_p=(1-std::exp(-alpha*seg_len))*vis;
40     exp_int+=curr_p*boxm2_processor_type<BOXM2_MOG3_GREY>::type::prob_density(mog3_data_->data()[index],intensity);
41     (*expected_img_)(i,j)=exp_int;
42     vis*=std::exp(-alpha*seg_len);
43     (*vis_img_)(i,j)=vis;
44     return true;
45   }
46  private:
47   boxm2_data<BOXM2_ALPHA> * alpha_data_;
48   boxm2_data<BOXM2_MOG3_GREY> * mog3_data_;
49   vil_image_view<float> *expected_img_;
50   vil_image_view<float> *vis_img_;
51   vil_image_view<float> *in_img_;
52 };
53 
54 //: Functor class to normalize expected image
55 class normalize_foreground_probability_density
56 {
57  public:
58   normalize_foreground_probability_density() = default;
59 
operator()60   float operator()(float &pix) const
61   {
62     return 1.f/(1.f+pix)-0.5f*std::min(pix,1.f/pix);
63   }
64 };
65 
66 class boxm2_change_detection_with_uncertainity_functor
67 {
68  public:
69 
70   //: "default" constructor
boxm2_change_detection_with_uncertainity_functor(unsigned ni,unsigned nj)71   boxm2_change_detection_with_uncertainity_functor(unsigned ni, unsigned nj)
72   {
73     ni_=ni;
74     nj_=nj;
75 
76     //: used only inside the functor.
77     vis_img_       =new vil_image_view<float>(ni_,nj_);
78     expected_img_  =new vil_image_view<float>(ni_,nj_);
79     dist_image_    =new vil_image_view<double>(ni_,nj_);
80     running_weight_=new vil_image_view<float>(ni_,nj_);
81     vis_img_->fill(1.0f);
82     expected_img_->fill(0.0f);
83     running_weight_->fill(0.0f);
84     dist_image_->fill(0.0f);
85   }
86 
set_data(std::vector<boxm2_data_base * > & datas,vil_image_view<float> * in_img,vil_image_view<float> * change_image)87   bool set_data(std::vector<boxm2_data_base*> & datas,
88                 vil_image_view<float> * in_img,
89                 vil_image_view<float> * change_image)
90   {
91     alpha_data_    =new boxm2_data<BOXM2_ALPHA>(datas[0]->data_buffer(),datas[0]->buffer_length(),datas[0]->block_id());
92     mog3_data_     =new boxm2_data<BOXM2_MOG3_GREY>(datas[1]->data_buffer(),datas[1]->buffer_length(),datas[1]->block_id());
93 
94 
95     in_img_=in_img;
96     change_image_=change_image;
97 
98     return true;
99   }
100 
step_cell(float seg_len,int index,unsigned i,unsigned j,float abs_depth)101   inline bool step_cell(float seg_len,int index,unsigned i, unsigned j, float abs_depth)
102   {
103     boxm2_data<BOXM2_ALPHA>::datatype alpha=alpha_data_->data()[index];
104     boxm2_data<BOXM2_MOG3_GREY>::datatype mog3=mog3_data_->data()[index];
105 
106     float vis=(*vis_img_)(i,j);
107     float curr_p=(1-std::exp(-alpha*seg_len))*vis;
108 
109     vnl_vector_fixed<unsigned char,8> updated_exp_distribution((unsigned char)0);
110 
111     (*expected_img_)(i,j)=(*expected_img_)(i,j)+boxm2_processor_type<BOXM2_MOG3_GREY>::type::expected_color(mog3)*curr_p;
112     (*change_image_)(i,j)=(*change_image_)(i,j)+boxm2_processor_type<BOXM2_MOG3_GREY>::type::prob_density(mog3,(*in_img_)(i,j))*curr_p;
113     //: representing 8 bytes of data aby double
114     unsigned img_index=j*ni_+i;
115     unsigned char * exp_distribution_array=reinterpret_cast<unsigned char *>(dist_image_->top_left_ptr()+img_index);
116     vnl_vector_fixed<unsigned char,8> exp_distribution(exp_distribution_array);
117     float w2=(*running_weight_)(i,j);
118 
119     //: merge mixtures only if the weight is non zero.
120     if (w2<=0.0f)
121       updated_exp_distribution=mog3_data_->data()[index];
122     else
123       boxm2_processor_type<BOXM2_MOG3_GREY>::type::merge_mixtures(mog3,curr_p,exp_distribution,w2,updated_exp_distribution);
124 #ifdef DEBUG
125     std::cout<<'[';
126     for (unsigned k=0;k<8;k++)
127       std::cout<<(int)exp_distribution[k]<<',';
128     std::cout<<"] *"<<w2<<" +\n[";
129     for (unsigned k=0;k<8;k++)
130       std::cout<<(int)mog3_data_->data()[index][k]<<',';
131     std::cout<<"]* "<<curr_p<<" =\n [";
132     for (unsigned k=0;k<8;k++)
133       std::cout<<(int)updated_exp_distribution[k]<<',';
134     std::cout<<"]\n\n";
135 #endif
136     (*running_weight_)(i,j)=curr_p+w2;
137 
138     //: representing 8 bytes of data aby double
139     double * final=reinterpret_cast<double *>(updated_exp_distribution.data_block());
140     (*dist_image_)(i,j)=(*final);
141 
142     vis*=std::exp(-alpha*seg_len);
143     (*vis_img_)(i,j)=vis;
144     return true;
145   }
146 
finish()147   void finish()
148   {
149       int count=-1;
150       float sigma =2.0f;
151       for (unsigned j=0;j<nj_;j++)
152           for (unsigned i=0;i<ni_;i++)
153               (*expected_img_)(i,j)+=(*vis_img_)(i,j)*0.5f;
154 
155       vil_image_view<float> expblur(expected_img_->ni(), expected_img_->nj());
156       vil_gauss_filter_2d((*expected_img_), expblur, sigma, (unsigned)(3*sigma+0.01f));
157 
158       for (unsigned j=0;j<nj_;j++)
159           for (unsigned i=0;i<ni_;i++)
160           {
161               float pb=(*change_image_)(i,j);
162               pb+=(*vis_img_)(i,j)*1.0f;
163               float bf=1.f/(1.f+pb)-0.5f*std::min(pb,1.f/pb);
164 
165               ++count;
166               unsigned char * exp_distribution_array=reinterpret_cast<unsigned char *>(dist_image_->top_left_ptr()+count);
167               vnl_vector_fixed<unsigned char,8> exp_distribution(exp_distribution_array);
168               float pr=boxm2_processor_type<BOXM2_MOG3_GREY>::type::prob_density(exp_distribution,expblur(i,j));
169               float br=pr/(1.f+pr)-0.5f*std::min(pr,1.f/pr);
170 
171               (*change_image_)(i,j)=bf*br;
172           }
173   }
174  private:
175   boxm2_data<BOXM2_ALPHA> * alpha_data_;
176   boxm2_data<BOXM2_MOG3_GREY> * mog3_data_;
177   vil_image_view<float> *in_img_;
178   vil_image_view<float> *change_image_;
179 
180   vil_image_view<float> *expected_img_;
181   vil_image_view<float> *vis_img_;
182   vil_image_view<double>* dist_image_;
183   vil_image_view<float> * running_weight_;
184   unsigned ni_;
185   unsigned nj_;
186 };
187 
188 
189 #endif
190