00001 #include "sdet_atmospheric_image_classifier.h"
00002
00003 #include <vnl/vnl_numeric_traits.h>
00004 #include <vul/vul_timer.h>
00005 #include <vbl/io/vbl_io_smart_ptr.h>
00006 #include <vcl_iostream.h>
00007 #include <vcl_cassert.h>
00008 #include <vil/vil_load.h>
00009
00010 bool sdet_atmospheric_image_classifier::atmos_cat(vcl_string const& cat)
00011 {
00012 for (vcl_vector<vcl_string>::iterator cit = atmos_categories_.begin();
00013 cit != atmos_categories_.end(); ++cit)
00014 if (cat == *cit)
00015 return true;
00016 return false;
00017 }
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 void sdet_atmospheric_image_classifier::
00028 category_quality_color_mix(vcl_map<vcl_string, float>& probs,
00029 vnl_vector_fixed<float, 3> const& uncert,
00030 vnl_vector_fixed<float, 3>& color_mix)
00031 {
00032
00033 vcl_map<vcl_string, vcl_vector<float> >::iterator hit = category_histograms_.begin();
00034
00035 float atmos_sum = 0.0f;
00036 float no_atmos_sum = 0.0f;
00037 float prob_sum = 0.0f;
00038 float up = 0.0f;
00039 for (; hit != category_histograms_.end(); ++hit) {
00040 const vcl_string& cat = (*hit).first;
00041 float p = probs[cat];
00042 prob_sum += p;
00043 if (atmos_cat(cat))
00044 atmos_sum += p;
00045 else if (cat=="des")
00046 up = p;
00047 else
00048 no_atmos_sum += p;
00049 }
00050
00051 float u = up/prob_sum;
00052
00053 float p_bad = atmos_sum/(prob_sum-up);
00054 float p_good = no_atmos_sum/(prob_sum-up);
00055
00056 float p_min = p_bad;
00057 if (p_good<p_min) p_min = p_good;
00058 if ((p_min-0.5f*u) < 0.0f) u = 2.0f*p_min;
00059
00060 float b_bad = p_bad - 0.5f*u;
00061 float b_good = p_good - 0.5f*u;
00062 vnl_vector_fixed<float, 3> good, bad;
00063 bad[0] = 1.0f; bad[1] = 0.0f; bad[2] = 0.0f;
00064 good[0] = 0.0f; good[1] = 1.0f; good[2] = 0.0f;
00065 if (up<prob_sum)
00066 color_mix = b_good*good + b_bad*bad + u*uncert;
00067 else
00068 color_mix = u*uncert;
00069 }
00070
00071 #if 0 //=====debug====
00072 static bool required_block(int bidxu, int bidxv, int i,
00073 int j, int block_size, int margin)
00074 {
00075 int idxu = (i-margin)/block_size, idxv = (j-margin)/block_size;
00076 return bidxu == idxu && bidxv == idxv;
00077 }
00078 #endif // 0
00079
00080 vil_image_view<float> sdet_atmospheric_image_classifier::
00081 classify_image_blocks_qual(vcl_string const& img_path)
00082 {
00083 vil_image_resource_sptr resc = vil_load_image_resource(img_path.c_str());
00084 vil_image_view<float> img = scale_image(resc);
00085 vcl_cout << "Classifying quality on image " << img_path << '\n' << vcl_flush;
00086 return classify_image_blocks_qual(img);
00087 }
00088
00089 vil_image_view<float>
00090 sdet_atmospheric_image_classifier::classify_image_blocks_qual(vil_image_view<float> const& image)
00091 {
00092 vcl_cout << "image size(" << image.ni()<< ' ' << image.nj() << ")pixels:["
00093 << texton_dictionary_.size() << "]categories \n" << vcl_flush;
00094 vul_timer t;
00095 if (!color_map_valid_)
00096 this->init_color_map();
00097 if (!texton_index_valid_)
00098 this->compute_texton_index();
00099 this->compute_filter_bank(image);
00100 unsigned dim = filter_responses_.n_levels();
00101 vcl_cout << "texton dimension " << dim +2<< '\n';
00102
00103 int margin = static_cast<int>(this->max_filter_radius());
00104 vcl_cout << "filter kernel margin " << margin << '\n';
00105 int ni = static_cast<int>(image.ni());
00106 int nj = static_cast<int>(image.nj());
00107 if ((ni-margin)<=0 || (nj-margin)<=0) {
00108 vcl_cout << "Image smaller than filter margin\n";
00109 return vil_image_view<float>(0, 0);
00110 }
00111
00112 unsigned block_area = block_size_*block_size_;
00113 float weight = 1.0f/static_cast<float>(block_area);
00114
00115 vil_image_view<float> prob(ni, nj, 3);
00116
00117 vnl_vector_fixed<float, 3> unct;
00118 unct[0] = 0.0f; unct[1] = 0.0f; unct[2] = 1.0f;
00119 for (unsigned j = 0; j<image.nj(); ++j)
00120 for (unsigned i = 0; i<image.ni(); ++i)
00121 for (unsigned p = 0; p<3; ++p)
00122 prob(i,j,p) = unct[p];
00123
00124 unsigned nh = texton_index_.size();
00125 int bidxv = 0;
00126 for (int j = margin; j<(nj-margin); j+=block_size_, ++bidxv) {
00127 int bidxu = 0;
00128 for (int i = margin; i<(ni-margin); i+=block_size_, ++bidxu) {
00129 vcl_vector<float> h(nh, 0.0f);
00130 for (unsigned r = 0; r<block_size_; ++r)
00131 for (unsigned c = 0; c<block_size_; ++c) {
00132 vnl_vector<double> temp(dim+2);
00133 for (unsigned f = 0; f<dim; ++f)
00134 temp[f]=filter_responses_.response(f)(i+c,j+r);
00135 temp[dim]=laplace_(i+c,j+r); temp[dim+1]=gauss_(i+c,j+r);
00136
00137
00138 this->update_hist(temp, weight, h);
00139 }
00140
00141
00142 vcl_map<vcl_string, float> texture_probs =
00143 this->texture_probabilities(h);
00144
00145 #if 0 //=====debug====
00146 int ii = 7518, jj = 2909;
00147 if (required_block(bidxu, bidxv, ii, jj, block_size_, margin)) {
00148 vcl_cout << "probs(" << i << ' ' << j << ")\n";
00149 float psum = 0.0;
00150 for (vcl_map<vcl_string, float>::iterator cit = texture_probs.begin();
00151 cit != texture_probs.end(); ++cit)
00152 psum += (*cit).second;
00153
00154 for (vcl_map<vcl_string, float>::iterator cit =texture_probs.begin();
00155 cit != texture_probs.end(); ++cit)
00156 vcl_cout << (*cit).first << ' ' << ((*cit).second)/psum << '\n';
00157 #ifdef DEBUG
00158 vcl_cout << " hist\n";
00159 for (unsigned i = 0; i<nh; ++i)
00160 vcl_cout << h[i]<< '\n';
00161 #endif
00162 }
00163 #endif
00164 vnl_vector_fixed<float, 3> color;
00165
00166 this->category_quality_color_mix(texture_probs,unct, color);
00167 for (unsigned r = 0; r<block_size_; ++r)
00168 for (unsigned c = 0; c<block_size_; ++c)
00169 for (unsigned b = 0; b<3; ++b)
00170 prob(i+c,j+r,b) = color[b];
00171 }
00172 vcl_cout << '.' << vcl_flush;
00173 }
00174 vcl_cout << "\nBlock classification took " << t.real()/1000.0 << " seconds\n" << vcl_flush;
00175 return prob;
00176 }
00177
00178 vil_image_view<float> sdet_atmospheric_image_classifier::
00179 classify_image_blocks_expected(vcl_string const& img_path,
00180 vcl_string const& exp_path)
00181 {
00182 vil_image_resource_sptr resc = vil_load_image_resource(img_path.c_str());
00183 vil_image_view<float> img = scale_image(resc);
00184 vil_image_resource_sptr resce = vil_load_image_resource(exp_path.c_str());
00185 vil_image_view<float> exp = scale_image(resce);
00186 vcl_cout << "Classifying quality on image " << img_path << " using expected image " << exp_path << '\n' << vcl_flush;
00187 return classify_image_blocks_expected(img, exp);
00188 }
00189
00190 vil_image_view<float> sdet_atmospheric_image_classifier::
00191 classify_image_blocks_expected(vil_image_view<float> const& image,
00192 vil_image_view<float> const& exp
00193 )
00194 {
00195 int ni = static_cast<int>(image.ni());
00196 int nj = static_cast<int>(image.nj());
00197 int ni_exp = static_cast<int>(exp.ni());
00198 int nj_exp = static_cast<int>(exp.nj());
00199 if ((ni != ni_exp) || (nj != nj_exp)) {
00200 vcl_cout << "Incoming image and expected image not of same size\n"
00201 << vcl_flush;
00202 return vil_image_view<float>();
00203 }
00204 vcl_cout << "image size(" << ni << ' '
00205 << nj << ")pixels \n" << vcl_flush;
00206
00207 vul_timer t;
00208
00209 if (!texton_index_valid_)
00210 this->compute_texton_index();
00211 this->compute_filter_bank(image);
00212 unsigned dim = filter_responses_.n_levels();
00213 vcl_cout << "texton dimension " << dim +2<< '\n';
00214
00215 int margin = static_cast<int>(this->max_filter_radius());
00216 vcl_cout << "filter kernel margin " << margin << '\n';
00217 if ((ni-margin)<=0 || (nj-margin)<=0) {
00218 vcl_cout << "Image smaller than filter margin\n";
00219 return vil_image_view<float>(0, 0);
00220 }
00221
00222 vcl_vector<vil_image_view<float> > image_resps =
00223 filter_responses_.responses();
00224 vil_image_view<float> laplace = laplace_;
00225 vil_image_view<float> gauss = gauss_;
00226
00227
00228 this->compute_filter_bank(exp);
00229
00230 vil_image_view<float> prob(ni, nj, 3);
00231
00232 vnl_vector_fixed<float, 3> unct;
00233 unct[0] = 0.0f; unct[1] = 0.0f; unct[2] = 1.0f;
00234 for (unsigned j = 0; j<image.nj(); ++j)
00235 for (unsigned i = 0; i<image.ni(); ++i)
00236 for (unsigned p = 0; p<3; ++p)
00237 prob(i,j,p) = unct[p];
00238
00239 vcl_vector<float>& mod_hist = category_histograms_["mod"];
00240 unsigned nh = mod_hist.size();
00241 if (nh == 0) {
00242 vcl_cout << "No model category to evaluate image\n";
00243 return prob;
00244 }
00245 double thr = dist_["mod"]["mod"];
00246
00247 thr *= 0.25;
00248 int bidxv = 0;
00249 for (int j = margin; j<(nj-margin); j+=block_size_, ++bidxv) {
00250 int bidxu = 0;
00251 for (int i = margin; i<(ni-margin); i+=block_size_, ++bidxu) {
00252 float pr = 0.0f, total =0.0f;
00253 for (unsigned r = 0; r<block_size_; ++r)
00254 for (unsigned c = 0; c<block_size_; ++c) {
00255 vnl_vector<double> temp_img(dim+2), temp_exp(dim+2);
00256 for (unsigned f = 0; f<dim; ++f) {
00257 temp_exp[f]=filter_responses_.response(f)(i+c,j+r);
00258 temp_img[f]=image_resps[f](i+c,j+r);
00259 }
00260 temp_exp[dim]=laplace_(i+c,j+r); temp_exp[dim+1]=gauss_(i+c,j+r);
00261 temp_img[dim]=laplace(i+c,j+r); temp_img[dim+1]=gauss(i+c,j+r);
00262 unsigned indx_exp = this->nearest_texton_index(temp_exp);
00263 double di_exp_img = vnl_vector_ssd(temp_exp, temp_img);
00264 di_exp_img = vcl_sqrt(di_exp_img/temp_exp.size());
00265 total += mod_hist[indx_exp];
00266 if (di_exp_img<thr)
00267 pr += mod_hist[indx_exp];
00268 }
00269 pr /= total;
00270 float u = pr/(1.0f - pr);
00271 if (u>1.0f) u = 1/u;
00272 float b_good = pr - 0.5f*u;
00273 if (b_good< 0.0f) b_good = 0.0f;
00274 float b_bad = 1.0f - u - b_good;
00275 vnl_vector_fixed<float, 3> color;
00276
00277 for (unsigned r = 0; r<block_size_; ++r)
00278 for (unsigned c = 0; c<block_size_; ++c) {
00279 prob(i+c,j+r,0) = b_bad;
00280 prob(i+c,j+r,1) = b_good;
00281 prob(i+c,j+r,2) = u;
00282 }
00283 }
00284 vcl_cout << '.' << vcl_flush;
00285 }
00286 vcl_cout << "\nBlock classification took " << t.real()/1000.0 << " seconds\n" << vcl_flush;
00287 return prob;
00288 }