1 // This is brl/bseg/brec/brec_part_gaussian.h
2 #ifndef brec_part_gaussian_h_
3 #define brec_part_gaussian_h_
4 //:
5 // \file
6 // \brief class to represent primitive parts as non-isotropic gaussian filters oriented in various ways
7 //
8 // \author Ozge C Ozcanli (ozge@lems.brown.edu)
9 // \date Oct 16, 2008
10 //
11 // \verbatim
12 //  Modifications
13 //   <none yet>
14 // \endverbatim
15 
16 #include <vector>
17 #include <iostream>
18 #include "brec_part_base.h"
19 #ifdef _MSC_VER
20 #  include <vcl_msvc_warnings.h>
21 #endif
22 #include "brec_part_gaussian_sptr.h"
23 
24 #include <vnl/vnl_vector_fixed.h>
25 
26 #include <vil/vil_image_resource_sptr.h>
27 #include <vil/vil_image_view.h>
28 #include <vbl/vbl_array_2d.h>
29 #include <bsta/bsta_weibull.h>
30 
31 #include <vul/vul_psfile.h>
32 
33 class brec_part_gaussian : public brec_part_instance
34 {
35  public:
36 
37   brec_part_gaussian(float x, float y, float strength, float lambda0, float lambda1, float theta, bool bright, unsigned type);
38 
39   //: the following constructor should only be used during parsing
40   brec_part_gaussian();
41 
42   bool mark_receptive_field(vil_image_view<vxl_byte>& img, unsigned plane) override;
43   bool mark_center(vil_image_view<vxl_byte>& img, unsigned plane) override;
44   bool mark_receptive_field(vil_image_view<float>& img, float val) override;
45   bool mark_center(vil_image_view<float>& img, float val) override;
46 
47   vnl_vector_fixed<float,2> direction_vector(void) override;  // return a unit vector that gives direction of this instance in the image
48 
49   //: Print an ascii summary to the stream
print_summary(std::ostream & os)50   void print_summary(std::ostream &os) const override
51   {
52     os << "x: " << x_ << " y: " << y_ << " strength: " << strength_ << std::endl
53        << "lambda0: " << lambda0_ << " lambda1: " << lambda1_ << " theta: " << theta_ << std::endl;
54   }
55 
56   brec_part_gaussian* cast_to_gaussian(void) override;
57 
58   bxml_data_sptr xml_element() override;
59   bool xml_parse_element(bxml_data_sptr data) override;
60   void initialize_mask();
61 
62   //: run the operator on \p mean_img and use the response to construct a response model for this operator
63   //  The \p mean_img and the \p std_dev_img are float images with values in [0,1] range
64   //  They are supposedly extracted from the background model of the scene
65   bool construct_bg_response_model(vil_image_view<float>& mean_img, vil_image_view<float>& std_dev_img, vil_image_view<float> &lambda_img, vil_image_view<float> &k_img);
66   bool construct_bg_response_model_gauss(vil_image_view<float>& mean_img, vil_image_view<float>& std_dev_img, vil_image_view<float> &mu_img, vil_image_view<float> &sigma_img);
67 
68   //: collect operator responses from the input image
69   //  Use responses from class regions to estimate lambda and k for the class response model
70   //  Use responses from non-class regions to estimate lambda and k for the non-class response model
71   //  Class and non-class regions are specified by the class_prob_img which is a float image with values in [0,1] range
72   bool construct_class_response_models(vil_image_view<float>& img, vil_image_view<float>& class_prob_img,
73     vil_image_view<bool>& mask_img, double &lambda, double &k, double &lambda_non_class, double &k_non_class);
74 
75   //: collect operator responses from the input image's foreground regions
76   //  The input \p img and the \p fg_prob_img (foreground probability image) are float images with values in [0,1] range
77   //  Assumes histogram is initialized
78   bool update_response_hist(vil_image_view<float>& img, vil_image_view<float>& fg_prob_img, vil_image_view<bool>& mask_img, bsta_histogram<float>& fg_h) override;
79   //: for gaussian operators we use weibull distribution as the parametric model
80   bool fit_distribution_to_response_hist(bsta_histogram<float>& fg_h) override;
81 
82   //: use the background \p mean_img and \p std_dev_img to construct response model for background and calculate posterior ratio of foreground and background
83   //  Assumes that \p k_ and \p lambda_ for the foreground response model have already been set
84   bool update_foreground_posterior(vil_image_view<float>& inp,
85                                            vil_image_view<float>& fg_prob_img,
86                                            vil_image_view<bool>& mask,
87                                            vil_image_view<float>& mean_img,
88                                            vil_image_view<float>& std_dev_img) override;
89 
90   //: run the operator on the input \p img rotated by the given angle and save the instances in the input vector
91   //  Use the response models saved in the \p model_dir to set the operator response strength which is equivalent to posterior probability of this pixel being foreground given the operator response
92   //  i.e. p(x in foreground | operator response) = p(operator response | x in foreground) / [p(operator response | x in foreground) + p(operator response | x in background)]
93   //  \return all the instances which have a posterior larger than zero (--> no thresholding, return "all" the responses)
94   //  \p fg_prob_img is the probability of being foreground for each pixel
95   //  \p pb_zero is the constant required for the background response model (probability of zero response)
96   bool extract(vil_image_view<float>& img, vil_image_view<float>& fg_prob_img, float rot_angle, const std::string& model_dir, std::vector<brec_part_instance_sptr>& instances, float prior_class);
97 
98   //: extract and set rho to class probability density of the response
99   //  Assumes weibull parameters have already been fitted (i.e. fitted_weibull_ = true)
100   //  This method is to be used during training and it returns an instance if class_prob >= 0.9
101   bool extract(vil_image_view<float>& img, vil_image_view<float>& class_prob_image, float rot_angle, std::vector<brec_part_instance_sptr>& instances);
102 
103   //: find P(alpha in foreground): the probability that this operator alpha is in foreground
104   //  P(alpha in foreground) = argmax_x_kl P(x_kl in foreground) where x_kl is in mask of operator alpha
105   float fg_prob_operator(vil_image_view<float>& fg_prob_img, unsigned i, unsigned j);
106   //: find P(alpha in background): the probability that this operator alpha is in background
107   //  P(alpha in background) = 1-argmax_x_kl P(x_kl in foreground) where x_kl is in mask of operator alpha
108   float bg_prob_operator(vil_image_view<float>& fg_prob_img, unsigned i, unsigned j);
109 
110   std::string string_identifier();
111 
112  public:
113   float lambda0_;  // axis
114   float lambda1_;
115   float theta_;    // orientation angle (in degrees)
116   bool bright_;
117 
118   //: parameter to define how big a receptive field will be marked, default is 0.01 so 1% of the tails of the gaussian is cut off
119   float cutoff_percentage_;
120 
121   vbl_array_2d<bool> mask_;
122   int rj_, ri_;
123 
124   float lambda_, k_;  // we fit Weibull distribution to Gaussian operators' response model
125   float lambda_non_class_, k_non_class_;  // we fit Weibull distribution to Gaussian operators' response model
126   bool fitted_weibull_;
127 };
128 
129 //: extracts only one type of primitive and adds to the part vector
130 //  Strength_threshold in [0,1] - min strength to declare the part as detected
131 bool extract_gaussian_primitives(const vil_image_resource_sptr& img, float lambda0, float lambda1, float theta, bool bright, float cutoff_percentage, float strength_threshold, unsigned type, std::vector<brec_part_instance_sptr>& parts);
132 
133 bool draw_gauss_to_ps(vul_psfile& ps, const brec_part_gaussian_sptr& pi, float x, float y, float cr, float cg, float cb);
134 
135 #endif // brec_part_gaussian_h_
136