00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <cpl_visual_features/saliency/center_surround.h>
00036 #include <opencv2/highgui/highgui.hpp>
00037
00038 #include <iostream>
00039 #include <sstream>
00040
00041
00042
00043
00044
00045 #define R_INDEX 2
00046 #define G_INDEX 1
00047 #define B_INDEX 0
00048
00049 using cv::Mat;
00050 using std::vector;
00051 namespace cpl_visual_features
00052 {
00053
00054
00055
00056
00057 CenterSurroundMapper::CenterSurroundMapper(int min_c, int max_c, int min_delta,
00058 int max_delta) :
00059 min_c_(min_c), max_c_(max_c), min_delta_(min_delta), max_delta_(max_delta),
00060 N_(4), gabor_size_(7)
00061 {
00062 num_scales_ = max_c_ + max_delta_;
00063 generateGaborFilters();
00064 }
00065
00066 void CenterSurroundMapper::generateGaborFilters()
00067 {
00068 Mat base_x(gabor_size_, gabor_size_, CV_64FC1);
00069 Mat base_y(gabor_size_, gabor_size_, CV_64FC1);
00070
00071
00072 for (int i = 0; i < base_x.cols; ++i)
00073 {
00074 for (int j = 0; j < base_x.rows; ++j)
00075 {
00076 base_x.at<double>(i,j) = i - gabor_size_/2;
00077 base_y.at<double>(i,j) = j - gabor_size_/2;
00078 }
00079 }
00080
00081 for (int alpha = 0; alpha < N_; ++alpha)
00082 {
00083 float theta = M_PI / N_*alpha;
00084 Mat x_theta = base_x * cos(theta) + base_y * sin(theta);
00085 Mat y_theta = base_x * -sin(theta) + base_y * cos(theta);
00086
00087 Mat gabor_alpha(gabor_size_, gabor_size_, CV_64FC1, 1.0);
00088 gabor_alpha *= 1/(2*M_PI);
00089
00090 Mat to_exp(gabor_size_, gabor_size_, CV_64FC1);
00091 to_exp = (x_theta.mul(x_theta) + y_theta.mul(y_theta))*-0.5;
00092
00093 for(int i = 0; i < gabor_size_; i++)
00094 {
00095 for(int j = 0; j < gabor_size_; j++)
00096 {
00097 gabor_alpha.at<double>(i,j) *= exp(to_exp.at<double>(i,j))*
00098 cos(x_theta.at<double>(i,j)*M_PI*2);
00099 }
00100 }
00101
00102 gabor_filters_.push_back(gabor_alpha);
00103 }
00104 }
00105
00106
00107
00108
00109
00110 Mat CenterSurroundMapper::operator()(Mat& frame, bool use_gradient)
00111 {
00112 Mat saliency_map = getSaliencyMap(frame);
00113 Mat gradient_map(saliency_map.rows, saliency_map.cols, CV_32FC1);
00114 if (use_gradient)
00115 {
00116 saliency_map.copyTo(gradient_map);
00117
00118 for (int i = 0; i < gradient_map.rows; ++i)
00119 {
00120 for (int j = 0; j < gradient_map.cols; ++j)
00121 {
00122 gradient_map.at<float>(i,j) = i*1.0/gradient_map.rows;
00123
00124
00125
00126 }
00127 }
00128
00129 saliency_map = saliency_map*0.75 + gradient_map*0.25;
00130 }
00131
00132
00133 Mat scaled = scaleMap(saliency_map);
00134 Mat display_scaled = upSampleResponse(scaled, min_delta_, frame.size());
00135 #ifdef DISPLAY_SALIENCY_MAPS
00136 if (use_gradient)
00137 cv::imshow("Top Down map", gradient_map);
00138 cv::imshow("Saliency", scaled);
00139 cv::imshow("Map", saliency_map);
00140 cv::waitKey();
00141 #endif // DISPLAY_SALIENCY_MAPS
00142
00143 return display_scaled;
00144 }
00145
00146
00147 Mat CenterSurroundMapper::operator()(Mat& frame, Mat& depth_map)
00148 {
00149
00150
00151
00152 Mat frame_saliency = getSaliencyMap(frame);
00153 Mat depth_i = getIntensityMap(depth_map);
00154 Mat depth_o = getOrientationMap(depth_map);
00155
00156
00157 float bar_max = 0;
00158 for (int r = 0; r < depth_i.rows; ++r)
00159 {
00160 for (int c = 0; c < depth_i.cols; ++c)
00161 {
00162 if (depth_i.at<float>(r,c) > bar_max)
00163 bar_max = depth_i.at<float>(r,c);
00164 if (depth_o.at<float>(r,c) > bar_max)
00165 bar_max = depth_o.at<float>(r,c);
00166 if (frame_saliency.at<float>(r,c) > bar_max)
00167 bar_max = frame_saliency.at<float>(r,c);
00168 }
00169 }
00170
00171
00172 Mat saliency_map(frame_saliency.rows, frame_saliency.cols, CV_32FC1);
00173 saliency_map = (normalize(frame_saliency, bar_max)*0.75 +
00174 normalize(depth_i, bar_max)*0.125 +
00175 normalize(depth_o, bar_max)*0.125);
00176 Mat scaled;
00177 scaled = scaleMap(saliency_map);
00178 Mat display_scaled = upSampleResponse(scaled, min_delta_, frame.size());
00179 #ifdef DISPLAY_SALIENCY_MAPS
00180 Mat display_fs = upSampleResponse(frame_saliency, min_delta_, frame.size());
00181 Mat display_i = upSampleResponse(depth_i, min_delta_, frame.size());
00182 Mat display_o = upSampleResponse(depth_o, min_delta_, frame.size());
00183 cv::imshow("Frame Saliency", display_fs);
00184 cv::imshow("Depth i", display_i);
00185 cv::imshow("Depth o", display_o);
00186 cv::imshow("Combined Saliency", display_scaled);
00187
00188 #endif // DISPLAY_SALIENCY_MAPS
00189
00190 return display_scaled;
00191 }
00192
00193
00194
00195
00196
00197 Mat CenterSurroundMapper::getSaliencyMap(Mat& frame)
00198 {
00199 Mat I(frame.rows, frame.cols, CV_32FC1);
00200 Mat R(frame.rows, frame.cols, CV_32FC1);
00201 Mat G(frame.rows, frame.cols, CV_32FC1);
00202 Mat B(frame.rows, frame.cols, CV_32FC1);
00203 Mat Y(frame.rows, frame.cols, CV_32FC1);
00204
00205 vector<Mat> I_scales;
00206 vector<Mat> R_scales;
00207 vector<Mat> G_scales;
00208 vector<Mat> B_scales;
00209 vector<Mat> Y_scales;
00210 vector<vector<Mat> > O_n_theta;
00211
00212
00213
00214 vector<Mat> channels;
00215 Mat to_split(frame.rows, frame.cols, CV_32FC3);
00216 frame.convertTo(to_split, to_split.type(), 1.0/255.0);
00217 split(to_split, channels);
00218
00219
00220 I = channels[R_INDEX]/3.0 + channels[G_INDEX]/3.0 + channels[B_INDEX]/3.0;
00221
00222 float max_i = 0;
00223 for(int r = 0; r < I.rows; ++r)
00224 {
00225 for(int c = 0; c < I.cols; ++c)
00226 {
00227 if (I.at<float>(r,c) > max_i)
00228 max_i = I.at<float>(r,c);
00229 }
00230 }
00231
00232
00233 for(int r = 0; r < I.rows; ++r)
00234 {
00235 for(int c = 0; c < I.cols; ++c)
00236 {
00237 if (I.at<float>(r,c) > max_i*0.10)
00238 {
00239 float intensity = I.at<float>(r,c);
00240 channels[R_INDEX].at<float>(r,c) = (channels[R_INDEX].at<float>(r,c) /
00241 intensity);
00242 channels[G_INDEX].at<float>(r,c) = (channels[G_INDEX].at<float>(r,c) /
00243 intensity);
00244 channels[B_INDEX].at<float>(r,c) = (channels[B_INDEX].at<float>(r,c) /
00245 intensity);
00246 }
00247 else
00248 {
00249 channels[0].at<float>(r,c) = 0;
00250 channels[1].at<float>(r,c) = 0;
00251 channels[2].at<float>(r,c) = 0;
00252 }
00253 }
00254 }
00255
00256
00257 R = channels[R_INDEX] - (channels[G_INDEX]/2.0 + channels[B_INDEX]/2.0);
00258 G = channels[G_INDEX] - (channels[R_INDEX]/2.0 + channels[B_INDEX]/2.0);
00259 B = channels[B_INDEX] - (channels[R_INDEX]/2.0 + channels[G_INDEX]/2.0);
00260
00261 Mat Y_abs(Y.rows, Y.cols, Y.type());
00262 for(int r = 0; r < Y.rows; ++r)
00263 {
00264 for(int c = 0; c < Y.cols; ++c)
00265 {
00266 Y_abs.at<float>(r,c) = std::abs(channels[R_INDEX].at<float>(r,c)/2.0 -
00267 channels[G_INDEX].at<float>(r,c)/2.0);
00268 }
00269 }
00270
00271 Y = (channels[R_INDEX]/2.0 + channels[G_INDEX]/2.0) - Y_abs-channels[B_INDEX];
00272
00273 #ifdef DISPLAY_COLOR_MAPS
00274 cv::imshow("I",I);
00275 cv::imshow("R",R);
00276 cv::imshow("G",G);
00277 cv::imshow("B",B);
00278 cv::imshow("Y",Y);
00279 cv::waitKey();
00280 #endif // DISPLAY_COLOR_MAPS
00281
00282
00283 cv::buildPyramid(I, I_scales, num_scales_);
00284 cv::buildPyramid(R, R_scales, num_scales_);
00285 cv::buildPyramid(G, G_scales, num_scales_);
00286 cv::buildPyramid(B, B_scales, num_scales_);
00287 cv::buildPyramid(Y, Y_scales, num_scales_);
00288
00289
00290
00291
00292
00293
00294 for(unsigned int i = 0; i < I_scales.size(); ++i)
00295 {
00296 Mat lap;
00297 cv::Laplacian(I_scales[i], lap, I_scales[i].depth());
00298 vector<Mat> O_theta;
00299
00300
00301 for (int a = 0; a < N_; a++)
00302 {
00303 Mat m_a(lap.rows, lap.cols, lap.type());
00304 cv::filter2D(lap, m_a, -1, gabor_filters_[a]);
00305
00306
00307 O_theta.push_back(m_a);
00308
00309
00310
00311
00312 }
00313 O_n_theta.push_back(O_theta);
00314 }
00315
00316
00317
00318
00319 vector<Mat> I_cs;
00320 vector<Mat> RG_cs;
00321 vector<Mat> BY_cs;
00322 vector<Mat> C_cs;
00323 vector<vector<Mat> > O_theta_cs;
00324
00325
00326 for (int a = 0; a < N_; ++a)
00327 {
00328 vector<Mat> O_cs;
00329 O_cs.clear();
00330 O_theta_cs.push_back(O_cs);
00331 }
00332
00333
00334 for (int c = min_c_; c <= max_c_; c++)
00335 {
00336 for (int s = c + min_delta_; s <= c + max_delta_; s++)
00337 {
00338
00339 I_cs.push_back(mapDifference(I_scales[c], I_scales[s], c, s));
00340
00341
00342 Mat RG_c = R_scales[c] - G_scales[c];
00343 Mat GR_s = G_scales[s] - R_scales[s];
00344 RG_cs.push_back(mapDifference(RG_c, GR_s, c, s));
00345
00346
00347 Mat BY_c = B_scales[c] - Y_scales[c];
00348 Mat YB_s = Y_scales[s] - B_scales[s];
00349 BY_cs.push_back(mapDifference(BY_c, YB_s, c, s));
00350
00351
00352 for (int a = 0; a < N_; ++a)
00353 {
00354 O_theta_cs[a].push_back(mapDifference(O_n_theta[c][a],
00355 O_n_theta[s][a], c, s));
00356 }
00357 }
00358 }
00359
00360
00361
00362
00363
00364
00365 float I_max = 0;
00366 float C_max = 0;
00367 vector<float> O_theta_max(N_, 0);
00368
00369 for (unsigned int i = 0; i < I_cs.size(); ++i)
00370 {
00371 for(int r = 0; r < I_cs[i].rows; ++r)
00372 {
00373 for(int c = 0; c < I_cs[i].cols; ++c)
00374 {
00375 if (I_cs[i].at<float>(r,c) > I_max)
00376 I_max = I_cs[i].at<float>(r,c);
00377 if (RG_cs[i].at<float>(r,c) > C_max)
00378 C_max = RG_cs[i].at<float>(r,c);
00379 if (BY_cs[i].at<float>(r,c) > C_max)
00380 C_max = BY_cs[i].at<float>(r,c);
00381
00382 for (int a = 0; a < N_; ++a)
00383 {
00384 if (O_theta_cs[a][i].at<float>(r,c) > O_theta_max[a])
00385 {
00386 O_theta_max[a] = O_theta_cs[a][i].at<float>(r,c);
00387 }
00388 }
00389 }
00390 }
00391 }
00392
00393
00394 for (unsigned int i = 0; i < I_cs.size(); ++i)
00395 {
00396
00397 I_cs[i] = normalize(I_cs[i], I_max);
00398 cv::Mat rg_norm = normalize(RG_cs[i], C_max);
00399 cv::Mat by_norm = normalize(BY_cs[i], C_max);
00400 cv::Mat c_csi = rg_norm + by_norm;
00401 C_cs.push_back(c_csi);
00402 for (int a = 0; a < N_; ++a)
00403 {
00404 O_theta_cs[a][i] = normalize(O_theta_cs[a][i], O_theta_max[a]);
00405 }
00406 }
00407
00408
00409 Mat I_bar;
00410 Mat C_bar;
00411 vector<Mat> O_bars;
00412 I_bar = mapSum(I_cs);
00413 C_bar = mapSum(C_cs);
00414
00415
00416
00417 for (int a = 0; a < N_; ++a)
00418 {
00419 Mat O_bar_a = mapSum(O_theta_cs[a]);
00420 O_bars.push_back(O_bar_a);
00421 }
00422
00423
00424
00425
00426 Mat O_bar(I_bar.rows, I_bar.cols, I_bar.type(), 0.0);
00427 float O_max = 0;
00428
00429
00430 for (int a = 0; a < N_; ++a)
00431 {
00432 for(int r = 0; r < O_bars[a].rows; ++r)
00433 {
00434 for(int c = 0; c < O_bars[a].cols; ++c)
00435 {
00436 if (O_bars[a].at<float>(r,c) > O_max)
00437 O_max = O_bars[a].at<float>(r,c);
00438 }
00439 }
00440 }
00441 for (int a = 0; a < N_; ++a)
00442 {
00443 cv::Mat norm_o_bar = normalize(O_bars[a], O_max);
00444 O_bar += norm_o_bar;
00445 }
00446
00447
00448
00449
00450
00451
00452 float bar_max = 0;
00453 for (int r = 0; r < I_bar.rows; ++r)
00454 {
00455 for (int c = 0; c < I_bar.cols; ++c)
00456 {
00457 if (I_bar.at<float>(r,c) > bar_max)
00458 bar_max = I_bar.at<float>(r,c);
00459 if (C_bar.at<float>(r,c) > bar_max)
00460 bar_max = C_bar.at<float>(r,c);
00461 if (O_bar.at<float>(r,c) > bar_max)
00462 bar_max = O_bar.at<float>(r,c);
00463 }
00464 }
00465
00466
00467 Mat saliency_map(I_bar.rows, I_bar.cols, CV_32FC1);
00468 Mat I_bar_norm = normalize(I_bar, bar_max);
00469 Mat C_bar_norm = normalize(C_bar, bar_max);
00470 Mat O_bar_norm = normalize(O_bar, bar_max);
00471 saliency_map = (I_bar_norm*(1/3.0)+C_bar_norm*(1/3.0)+O_bar_norm*(1/3.0));
00472
00473 #ifdef DISPLAY_SALIENCY_MAPS
00474 Mat display_I_bar = upSampleResponse(I_bar, min_delta_, frame.size());
00475 Mat display_C_bar = upSampleResponse(C_bar, min_delta_, frame.size());
00476 Mat display_O_bar = upSampleResponse(O_bar, min_delta_, frame.size());
00477 cv::imshow("C bar small", C_bar);
00478
00479 cv::imshow("C bar", display_C_bar);
00480 cv::imshow("O bar", display_O_bar);
00481 double min_val = 0;
00482 double max_val = 0;
00483 cv::minMaxLoc(display_O_bar, &min_val, &max_val);
00484 std::cout << "O_bar Min_val: " << min_val << std::endl;
00485 std::cout << "O_bar Max_val: " << max_val << std::endl;
00486 cv::minMaxLoc(display_C_bar, &min_val, &max_val);
00487 std::cout << "C_bar Min_val: " << min_val << std::endl;
00488 std::cout << "C_bar Max_val: " << max_val << std::endl;
00489 cv::minMaxLoc(display_I_bar, &min_val, &max_val);
00490 std::cout << "I_bar Min_val: " << min_val << std::endl;
00491 std::cout << "I_bar Max_val: " << max_val << std::endl;
00492 cv::minMaxLoc(saliency_map, &min_val, &max_val);
00493 std::cout << "sal_map Min_val: " << min_val << std::endl;
00494 std::cout << "sal_map Max_val: " << max_val << std::endl;
00495 #endif // DISPLAY_SALIENCY_MAPS
00496 return saliency_map;
00497 }
00498
00499 Mat CenterSurroundMapper::getIntensityMap(Mat& frame)
00500 {
00501 Mat I(frame.rows, frame.cols, CV_32FC1);
00502 vector<Mat> I_scales;
00503
00504
00505 if(frame.channels() == 3)
00506 {
00507
00508 vector<Mat> channels;
00509 Mat to_split(frame.rows, frame.cols, CV_32FC3);
00510 frame.convertTo(to_split, to_split.type(), 1.0/255.0);
00511 split(to_split, channels);
00512 I = channels[R_INDEX]/3.0 + channels[G_INDEX]/3.0 + channels[B_INDEX]/3.0;
00513 }
00514 else
00515 {
00516 frame.convertTo(I, CV_32FC1);
00517 }
00518
00519 float max_i = 0;
00520 for(int r = 0; r < I.rows; ++r)
00521 {
00522 for(int c = 0; c < I.cols; ++c)
00523 {
00524 if (I.at<float>(r,c) > max_i)
00525 max_i = I.at<float>(r,c);
00526 }
00527 }
00528
00529
00530 cv::buildPyramid(I, I_scales, num_scales_);
00531
00532
00533
00534
00535 vector<Mat> I_cs;
00536
00537
00538 for (int c = min_c_; c <= max_c_; c++)
00539 {
00540 for (int s = c + min_delta_; s <= c + max_delta_; s++)
00541 {
00542
00543 I_cs.push_back(mapDifference(I_scales[c], I_scales[s], c, s));
00544 }
00545 }
00546
00547
00548 float I_max = 0;
00549 for (unsigned int i = 0; i < I_cs.size(); ++i)
00550 {
00551 for(int r = 0; r < I_cs[i].rows; ++r)
00552 {
00553 for(int c = 0; c < I_cs[i].cols; ++c)
00554 {
00555 if (I_cs[i].at<float>(r,c) > I_max)
00556 I_max = I_cs[i].at<float>(r,c);
00557 }
00558 }
00559 }
00560
00561
00562 for (unsigned int i = 0; i < I_cs.size(); ++i)
00563 {
00564
00565 I_cs[i] = normalize(I_cs[i], I_max);
00566 }
00567
00568
00569 Mat I_bar;
00570 I_bar = mapSum(I_cs);
00571 return I_bar;
00572 }
00573
00574 Mat CenterSurroundMapper::getOrientationMap(Mat& frame)
00575 {
00576 vector<vector<Mat> > O_n_theta;
00577
00578 Mat I(frame.rows, frame.cols, CV_32FC1);
00579 vector<Mat> I_scales;
00580
00581
00582 if(frame.channels() == 3)
00583 {
00584
00585 vector<Mat> channels;
00586 Mat to_split(frame.rows, frame.cols, CV_32FC3);
00587 frame.convertTo(to_split, to_split.type(), 1.0/255.0);
00588 split(to_split, channels);
00589 I = channels[R_INDEX]/3.0 + channels[G_INDEX]/3.0 + channels[B_INDEX]/3.0;
00590 }
00591 else
00592 {
00593 frame.convertTo(I, CV_32FC1);
00594 }
00595
00596 float max_i = 0;
00597 for(int r = 0; r < I.rows; ++r)
00598 {
00599 for(int c = 0; c < I.cols; ++c)
00600 {
00601 if (I.at<float>(r,c) > max_i)
00602 max_i = I.at<float>(r,c);
00603 }
00604 }
00605
00606
00607 cv::buildPyramid(I, I_scales, num_scales_);
00608
00609
00610 for(unsigned int i = 0; i < I_scales.size(); ++i)
00611 {
00612 Mat lap;
00613 cv::Laplacian(I_scales[i], lap, I_scales[i].depth());
00614 vector<Mat> O_theta;
00615
00616
00617 for (int a = 0; a < N_; a++)
00618 {
00619 Mat m_a(lap.rows, lap.cols, lap.type());
00620 cv::filter2D(lap, m_a, -1, gabor_filters_[a]);
00621
00622
00623 O_theta.push_back(m_a);
00624
00625 #ifdef DISPLAY_GABOR_FILTERS
00626 std::stringstream m_name;
00627 m_name << "O_" << i << "_" << a;
00628 cv::imshow(m_name.str(), m_a);
00629 cv::waitKey();
00630 #endif // DISPLAY_GABOR_FILTERS
00631
00632 }
00633 O_n_theta.push_back(O_theta);
00634 }
00635
00636
00637
00638
00639
00640 vector<vector<Mat> > O_theta_cs;
00641
00642
00643 for (int a = 0; a < N_; ++a)
00644 {
00645 vector<Mat> O_cs;
00646 O_cs.clear();
00647 O_theta_cs.push_back(O_cs);
00648 }
00649
00650
00651 for (int c = min_c_; c <= max_c_; c++)
00652 {
00653 for (int s = c + min_delta_; s <= c + max_delta_; s++)
00654 {
00655
00656 for (int a = 0; a < N_; ++a)
00657 {
00658 O_theta_cs[a].push_back(mapDifference(O_n_theta[c][a],
00659 O_n_theta[s][a], c, s));
00660 }
00661 }
00662 }
00663
00664
00665 vector<float> O_theta_max(N_, 0);
00666 for (unsigned int i = 0; i < O_theta_cs[0].size(); ++i)
00667 {
00668 for(int r = 0; r < O_theta_cs[0][i].rows; ++r)
00669 {
00670 for(int c = 0; c < O_theta_cs[0][i].cols; ++c)
00671 {
00672 for (int a = 0; a < N_; ++a)
00673 {
00674 if (O_theta_cs[a][i].at<float>(r,c) > O_theta_max[a])
00675 O_theta_max[a] = O_theta_cs[a][i].at<float>(r,c);
00676 }
00677 }
00678 }
00679 }
00680
00681
00682 for (unsigned int i = 0; i < O_theta_cs[0].size(); ++i)
00683 {
00684 for (int a = 0; a < N_; ++a)
00685 {
00686 O_theta_cs[a][i] = normalize(O_theta_cs[a][i], O_theta_max[a]);
00687 }
00688 }
00689
00690
00691 vector<Mat> O_bars;
00692
00693
00694
00695 for (int a = 0; a < N_; ++a)
00696 {
00697 Mat O_bar_a = mapSum(O_theta_cs[a]);
00698 O_bars.push_back(O_bar_a);
00699 }
00700
00701
00702
00703
00704 int min_rows = 10000;
00705 int min_cols = 10000;
00706
00707
00708 for (unsigned int i = 0; i < O_bars.size(); ++i)
00709 {
00710 if (O_bars[i].rows < min_rows)
00711 {
00712 min_rows = O_bars[i].rows;
00713 min_cols = O_bars[i].cols;
00714 }
00715 }
00716
00717 Mat O_bar = Mat::zeros(min_rows, min_cols, CV_32FC1);
00718 float O_max = 0;
00719
00720
00721 for (int a = 0; a < N_; ++a)
00722 {
00723 for(int r = 0; r < O_bars[a].rows; ++r)
00724 {
00725 for(int c = 0; c < O_bars[a].cols; ++c)
00726 {
00727 if (O_bars[a].at<float>(r,c) > O_max)
00728 O_max = O_bars[a].at<float>(r,c);
00729 }
00730 }
00731 }
00732
00733 for (int a = 0; a < N_; ++a)
00734 {
00735 O_bar += normalize(O_bars[a], O_max);
00736 }
00737 return O_bar;
00738 }
00739
00740 Mat CenterSurroundMapper::getColorMap(Mat& frame)
00741 {
00742 Mat R(frame.rows, frame.cols, CV_32FC1);
00743 Mat G(frame.rows, frame.cols, CV_32FC1);
00744 Mat B(frame.rows, frame.cols, CV_32FC1);
00745 Mat Y(frame.rows, frame.cols, CV_32FC1);
00746 Mat I(frame.rows, frame.cols, CV_32FC1);
00747 vector<Mat> R_scales;
00748 vector<Mat> G_scales;
00749 vector<Mat> B_scales;
00750 vector<Mat> Y_scales;
00751
00752
00753 vector<Mat> channels;
00754 Mat to_split(frame.rows, frame.cols, CV_32FC3);
00755 frame.convertTo(to_split, to_split.type(), 1.0/255.0);
00756
00757 split(to_split, channels);
00758
00759
00760 I = channels[R_INDEX]/3.0 + channels[G_INDEX]/3.0 + channels[B_INDEX]/3.0;
00761
00762 float max_i = 0;
00763 for(int r = 0; r < I.rows; ++r)
00764 {
00765 for(int c = 0; c < I.cols; ++c)
00766 {
00767 if (I.at<float>(r,c) > max_i)
00768 max_i = I.at<float>(r,c);
00769 }
00770 }
00771
00772
00773 for(int r = 0; r < I.rows; ++r)
00774 {
00775 for(int c = 0; c < I.cols; ++c)
00776 {
00777 if (I.at<float>(r,c) > max_i*0.10)
00778 {
00779 float intensity = I.at<float>(r,c);
00780 channels[R_INDEX].at<float>(r,c) = (channels[R_INDEX].at<float>(r,c) /
00781 intensity);
00782 channels[G_INDEX].at<float>(r,c) = (channels[G_INDEX].at<float>(r,c) /
00783 intensity);
00784 channels[B_INDEX].at<float>(r,c) = (channels[B_INDEX].at<float>(r,c) /
00785 intensity);
00786 }
00787 else
00788 {
00789 channels[0].at<float>(r,c) = 0;
00790 channels[1].at<float>(r,c) = 0;
00791 channels[2].at<float>(r,c) = 0;
00792 }
00793 }
00794 }
00795
00796
00797 R = channels[R_INDEX] - (channels[G_INDEX]/2.0 + channels[B_INDEX]/2.0);
00798 G = channels[G_INDEX] - (channels[R_INDEX]/2.0 + channels[B_INDEX]/2.0);
00799 B = channels[B_INDEX] - (channels[R_INDEX]/2.0 + channels[G_INDEX]/2.0);
00800
00801 Mat Y_abs(Y.rows, Y.cols, Y.type());
00802 for(int r = 0; r < Y.rows; ++r)
00803 {
00804 for(int c = 0; c < Y.cols; ++c)
00805 {
00806 Y_abs.at<float>(r,c) = std::abs(channels[R_INDEX].at<float>(r,c)/2.0 -
00807 channels[G_INDEX].at<float>(r,c)/2.0);
00808 }
00809 }
00810
00811 Y = (channels[R_INDEX]/2.0 + channels[G_INDEX]/2.0) - Y_abs-channels[B_INDEX];
00812
00813 #ifdef DISPLAY_COLOR_MAPS
00814 cv::imshow("I",I);
00815 cv::imshow("R",R);
00816 cv::imshow("G",G);
00817 cv::imshow("B",B);
00818 cv::imshow("Y",Y);
00819 cv::waitKey();
00820 #endif // DISPLAY_COLOR_MAPS
00821
00822 cv::buildPyramid(R, R_scales, num_scales_);
00823 cv::buildPyramid(G, G_scales, num_scales_);
00824 cv::buildPyramid(B, B_scales, num_scales_);
00825 cv::buildPyramid(Y, Y_scales, num_scales_);
00826
00827
00828
00829
00830 vector<Mat> RG_cs;
00831 vector<Mat> BY_cs;
00832 vector<Mat> C_cs;
00833
00834
00835 for (int c = min_c_; c <= max_c_; c++)
00836 {
00837 for (int s = c + min_delta_; s <= c + max_delta_; s++)
00838 {
00839
00840 Mat RG_c = R_scales[c] - G_scales[c];
00841 Mat GR_s = G_scales[s] - R_scales[s];
00842 RG_cs.push_back(mapDifference(RG_c, GR_s, c, s));
00843
00844
00845 Mat BY_c = B_scales[c] - Y_scales[c];
00846 Mat YB_s = Y_scales[s] - B_scales[s];
00847 BY_cs.push_back(mapDifference(BY_c, YB_s, c, s));
00848 }
00849 }
00850
00851
00852
00853
00854
00855
00856 float C_max = 0;
00857 for (unsigned int i = 0; i < RG_cs.size(); ++i)
00858 {
00859 for(int r = 0; r < RG_cs[i].rows; ++r)
00860 {
00861 for(int c = 0; c < RG_cs[i].cols; ++c)
00862 {
00863 if (RG_cs[i].at<float>(r,c) > C_max)
00864 C_max = RG_cs[i].at<float>(r,c);
00865 if (BY_cs[i].at<float>(r,c) > C_max)
00866 C_max = BY_cs[i].at<float>(r,c);
00867 }
00868 }
00869 }
00870
00871
00872 for (unsigned int i = 0; i < RG_cs.size(); ++i)
00873 {
00874
00875 C_cs.push_back(normalize(RG_cs[i], C_max) + normalize(BY_cs[i], C_max));
00876 }
00877
00878 Mat C_bar;
00879 C_bar = mapSum(C_cs);
00880 return C_bar;
00881 }
00882
00883
00884
00885
00886 Mat CenterSurroundMapper::mapDifference(Mat& m_c, Mat& m_s, int c, int s)
00887 {
00888
00889 Mat m_s_prime(m_s.rows, m_s.cols, CV_32FC1);
00890 Mat temp;
00891 m_s.copyTo(temp);
00892
00893
00894 vector<cv::Size> sizes;
00895 cv::Size current_size(m_c.cols, m_c.rows);
00896 for (int i = c; i < s; i++)
00897 {
00898 sizes.push_back(current_size);
00899 current_size.width /= 2;
00900 current_size.height /= 2;
00901 }
00902
00903 for (int i = c; i < s; i++)
00904 {
00905 cv::Size up_size;
00906 up_size = sizes.back();
00907 sizes.pop_back();
00908 cv::pyrUp(temp, m_s_prime, up_size);
00909 temp = m_s_prime;
00910 }
00911
00912
00913 Mat diff = abs(m_c - m_s_prime);
00914
00915 return diff;
00916 }
00917
00918 Mat CenterSurroundMapper::mapSum(vector<Mat>& maps)
00919 {
00920 int min_rows = 10000;
00921 int min_cols = 10000;
00922
00923
00924 for (unsigned int i = 0; i < maps.size(); ++i)
00925 {
00926 if (maps[i].rows < min_rows)
00927 {
00928 min_rows = maps[i].rows;
00929 min_cols = maps[i].cols;
00930 }
00931 }
00932
00933 Mat sum = Mat::zeros(min_rows, min_cols, CV_32FC1);
00934
00935 for (unsigned int i = 0; i < maps.size(); ++i)
00936 {
00937 Mat m_prime = maps[i];
00938 Mat temp = maps[i];
00939
00940 while (temp.cols > min_cols)
00941 {
00942 cv::pyrDown(temp, m_prime);
00943 temp = m_prime;
00944 }
00945 sum += m_prime;
00946 }
00947
00948 return sum;
00949 }
00950
00951 Mat CenterSurroundMapper::normalize(Mat& map, float M)
00952 {
00953
00954 float cur_max_val = 0;
00955 for(int r = 0; r < map.rows; ++r)
00956 {
00957 for (int c = 0; c < map.cols; ++c)
00958 {
00959 if (map.at<float>(r,c) > cur_max_val)
00960 cur_max_val = map.at<float>(r,c);
00961 }
00962 }
00963
00964 if (cur_max_val == 0)
00965 {
00966 std::cout << "Max value is 0, don't want to get nans..." << std::endl;
00967 std::cout << "M value is: " << M << std::endl;
00968 cur_max_val = M;
00969
00970 }
00971
00972 Mat normalized = map * (M/float(cur_max_val));
00973 float thresh = M*0.20;
00974
00975
00976
00977 vector<float> maxima;
00978 int nan_count = 0;
00979 for(int r = 0; r < map.rows; ++r)
00980 {
00981 for(int c = 0; c < map.cols; ++c)
00982 {
00983 float val = map.at<float>(r,c);
00984 if (isnan(val))
00985 {
00986
00987 nan_count++;
00988 val = 0;
00989 map.at<float>(r,c) = 0;
00990 }
00991 if (val > thresh)
00992 {
00993
00994
00995 if (c > 0)
00996 {
00997 if( val < map.at<float>(r,c-1))
00998 continue;
00999 if (r > 0 && val < map.at<float>(r - 1, c - 1))
01000 continue;
01001 if (r < map.rows - 1 && val < map.at<float>(r + 1, c - 1))
01002 continue;
01003 }
01004 if (c < map.cols - 1)
01005 {
01006 if( val < map.at<float>(r,c + 1))
01007 continue;
01008 if (r > 0 && val < map.at<float>(r - 1, c + 1))
01009 continue;
01010 if (r < map.rows - 1 && val < map.at<float>(r + 1, c + 1))
01011 continue;
01012 }
01013 if (r > 0 && val < map.at<float>(r - 1, c))
01014 continue;
01015 if (r < map.rows - 1 && val < map.at<float>(r + 1, c))
01016 continue;
01017
01018
01019 maxima.push_back(val);
01020 }
01021 }
01022 }
01023
01024 if (nan_count > 0)
01025 {
01026 std::cout << "Image has: " << nan_count << " nans" << std::endl;
01027 }
01028
01029 float m_bar = 0;
01030
01031 for (unsigned int i = 0; i < maxima.size(); ++i)
01032 {
01033 m_bar += maxima[i];
01034 }
01035
01036 m_bar /= maxima.size();
01037
01038
01039
01040 float fact = (M - m_bar)*(M - m_bar);
01041
01042
01043 fact *= 1.0/(fact*M);
01044 normalized *= fact;
01045 return normalized;
01046 }
01047
01048 Mat CenterSurroundMapper::scaleMap(Mat saliency_map)
01049 {
01050 Mat scaled;
01051 Mat saliency_int(saliency_map.rows, saliency_map.cols, CV_8UC1);
01052 saliency_map *= 255;
01053 saliency_map.convertTo(saliency_int, saliency_int.type());
01054 cv::equalizeHist(saliency_int, scaled);
01055 return scaled;
01056 }
01057
01058 cv::Mat CenterSurroundMapper::upSampleResponse(cv::Mat& m_s, int s, cv::Size size0)
01059 {
01060
01061 cv::Mat m_s_prime = m_s.clone();
01062 cv::Mat temp = m_s.clone();
01063
01064
01065 std::vector<cv::Size> sizes;
01066 cv::Size current_size = size0;
01067 while (true)
01068 {
01069 sizes.push_back(current_size);
01070 current_size.width /= 2;
01071 current_size.height /= 2;
01072 if (current_size.width == m_s.cols)
01073 {
01074 break;
01075 }
01076 else if (current_size.width-1 == m_s.cols)
01077 {
01078 std::cout << "Breaking on -1" << std::endl;
01079 }
01080 else if (current_size.width+1 == m_s.cols)
01081 {
01082 std::cout << "Breaking on +1" << std::endl;
01083 }
01084 }
01085 int num_ups = sizes.size();
01086 for (int i = 0; i < num_ups; i++)
01087 {
01088 cv::Size up_size;
01089 up_size = sizes.back();
01090 sizes.pop_back();
01091 cv::pyrUp(temp, m_s_prime, up_size);
01092 temp = m_s_prime;
01093 }
01094
01095 return m_s_prime;
01096 }
01097
01098 }