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
00036 #include <swri_image_util/image_normalization.h>
00037
00038 namespace swri_image_util
00039 {
00040 void normalize_illumination(cv::Mat NormImage,
00041 cv::Mat SourceImage,
00042 cv::Mat& DestImage)
00043 {
00044
00045
00046 cv::Mat tempIm1;
00047 SourceImage.convertTo(tempIm1, CV_32FC1, 1.0, 0.0);
00048 cv::divide(tempIm1, NormImage, tempIm1, 1.0);
00049 cv::Mat firstImage;
00050 cv::Mat secondImage;
00051 tempIm1.convertTo(DestImage, CV_8UC1);
00052 }
00053
00054 cv::Mat generate_normalization_image(const std::vector<cv::Mat>& image_list)
00055 {
00056 cv::Mat norm_image;
00057 if (image_list.empty())
00058 {
00059 return cv::Mat();
00060 }
00061
00062 const cv::Mat& rep_im = image_list.front();
00063
00064 cv::Mat image_sum(cv::Size(rep_im.cols, rep_im.rows), CV_64F);
00065
00066 for (uint32_t i = 0; i < image_list.size(); i++)
00067 {
00068 cv::Mat temp_im;
00069 image_list[i].convertTo(temp_im, CV_64F, 1.0, 0.0);
00070
00071 image_sum = image_sum + temp_im;
00072 }
00073
00074 image_sum = image_sum / static_cast<double>(image_list.size());
00075
00076 cv::Mat mean_image;
00077 image_sum.convertTo(mean_image, CV_8U);
00078 cv::Mat temp_norm_image;
00079
00080 cv::medianBlur(mean_image, temp_norm_image, 45);
00081
00082 cv::Mat temp_norm_image2;
00083 temp_norm_image.convertTo(temp_norm_image2, CV_32F);
00084 double max1 = 0;
00085 for (int32_t i = 0; i < temp_norm_image2.rows; i++)
00086 {
00087 for (int32_t j = 0; j < temp_norm_image2.cols; j++)
00088 {
00089 if (temp_norm_image2.at<float>(i, j) > max1)
00090 {
00091 max1 = temp_norm_image2.at<float>(i, j);
00092 }
00093 }
00094 }
00095
00096 temp_norm_image2 = temp_norm_image2 * (255.0 / max1);
00097
00098 cv::Mat temp_norm_image3;
00099 temp_norm_image2.convertTo(temp_norm_image3, CV_8U, 1.0, 0.0);
00100
00101
00102 cv::GaussianBlur(temp_norm_image3,
00103 norm_image,
00104 cv::Size(25, 25),
00105 5,
00106 5);
00107
00108 return norm_image;
00109 }
00110
00111 void MaskedBoxFilter(cv::Mat& mat, cv::Mat& mask, int32_t kernel_size)
00112 {
00113 mask.setTo(1, mask);
00114 cv::Mat local_sums;
00115 cv::boxFilter(
00116 mat,
00117 local_sums,
00118 mat.depth(),
00119 cv::Size(kernel_size, kernel_size),
00120 cv::Point(-1, -1),
00121 false);
00122 cv::Mat local_mask_sums;
00123 cv::boxFilter(
00124 mask,
00125 local_mask_sums,
00126 mat.depth(),
00127 cv::Size(kernel_size, kernel_size),
00128 cv::Point(-1, -1),
00129 false);
00130 cv::Mat blurred;
00131 cv::divide(local_sums, local_mask_sums, blurred, 1, mat.type());
00132 blurred.copyTo(mat, local_mask_sums != 0);
00133 }
00134
00135 void ContrastStretch(
00136 int32_t grid_size,
00137 const cv::Mat& source_image,
00138 cv::Mat& dest_image,
00139 const cv::Mat& mask,
00140 double max_min,
00141 double min_max)
00142 {
00143 int x_bin_w = std::floor(static_cast<double>(source_image.cols) / grid_size);
00144 int y_bin_h = std::floor(static_cast<double>(source_image.rows) / grid_size);
00145
00146
00147
00148 cv::Mat max_vals(grid_size + 1, grid_size + 1, CV_64F);
00149 cv::Mat min_vals(grid_size + 1, grid_size + 1, CV_64F);
00150 cv::Mat grid_mask = cv::Mat::ones(grid_size + 1, grid_size + 1, CV_8U) * 255;
00151
00152 bool has_mask = !mask.empty();
00153 for(int i = 0; i < grid_size + 1; i++)
00154 {
00155 for(int j = 0; j < grid_size + 1; j++)
00156 {
00157 double minVal = 0;
00158 double maxVal = 255;
00159
00160 cv::Rect roi = cv::Rect(j * x_bin_w - x_bin_w / 2,
00161 i * y_bin_h - y_bin_h / 2, x_bin_w, y_bin_h);
00162 roi.x = std::max(0, roi.x);
00163 roi.y = std::max(0, roi.y);
00164 roi.width = std::min(source_image.cols - roi.x, roi.width);
00165 roi.height = std::min(source_image.rows - roi.y, roi.height);
00166
00167 if (has_mask)
00168 {
00169 if (cv::countNonZero(mask(roi)) > 0)
00170 {
00171
00172 cv::minMaxLoc(source_image(roi), &minVal, &maxVal, 0, 0, mask(roi));
00173 }
00174 else
00175 {
00176 grid_mask.at<uint8_t>(i, j) = 0;
00177 }
00178 }
00179 else
00180 {
00181 cv::minMaxLoc(source_image(roi), &minVal, &maxVal, 0, 0);
00182 }
00183 max_vals.at<double>(i, j) = maxVal;
00184 min_vals.at<double>(i, j) = minVal;
00185 }
00186 }
00187
00188 MaskedBoxFilter(max_vals, grid_mask, 3);
00189 MaskedBoxFilter(min_vals, grid_mask, 3);
00190
00191
00192 for(int i = 0; i < source_image.rows; i++)
00193 {
00194 int ii = i / y_bin_h;
00195 double py = (i - ii * y_bin_h) / static_cast<double>(y_bin_h);
00196
00197 for(int j = 0; j < source_image.cols; j++)
00198 {
00199
00200 int jj = j / x_bin_w;
00201
00202
00203 double minVal = min_vals.at<double>(ii, jj);
00204 double maxVal = max_vals.at<double>(ii, jj);
00205
00206
00207 double px = (j - jj * x_bin_w) / static_cast<double>(x_bin_w);
00208
00209
00210 double xM1 = maxVal + px * (max_vals.at<double>(ii, jj+1) - maxVal);
00211 double xM2 = max_vals.at<double>(ii+1, jj) + px * (max_vals.at<double>(ii+1, jj+1) - max_vals.at<double>(ii+1, jj));
00212 double M = xM1 + py * (xM2 - xM1);
00213
00214 double xm1 = minVal + px*(min_vals.at<double>(ii, jj+1) - minVal);
00215 double xm2 = min_vals.at<double>(ii+1, jj) + px*(min_vals.at<double>(ii+1, jj+1) - min_vals.at<double>(ii+1, jj));
00216 double m = xm1 + py*(xm2 - xm1);
00217 minVal = m;
00218 maxVal = M;
00219
00220 if(maxVal > 255) maxVal = 255;
00221 if(minVal < 0) minVal = 0;
00222
00223
00224 maxVal = std::max(maxVal, min_max);
00225 minVal = std::min(minVal, max_min);
00226
00227 double val = source_image.at<uint8_t>(i,j);
00228 val = 255.0 * (val - minVal) / (maxVal - minVal);
00229 if(val > 255) val = 255;
00230 if(val < 0) val = 0;
00231 dest_image.at<uint8_t>(i,j) = val;
00232 }
00233 }
00234 }
00235
00236 void NormalizeResponse(
00237 const cv::Mat& src,
00238 cv::Mat& dst,
00239 int winsize,
00240 int ftzero,
00241 uchar* buf)
00242 {
00243 if (dst.empty())
00244 {
00245 dst.create(src.size(), CV_8U);
00246 }
00247
00248
00249 int x, y, wsz2 = winsize / 2;
00250 int* vsum = reinterpret_cast<int*>(cv::alignPtr(buf + (wsz2 + 1) * sizeof(vsum[0]), 32));
00251 int scale_g = winsize * winsize / 8, scale_s = (1024 + scale_g) / (scale_g * 2);
00252 const int OFS = 256 * 5, TABSZ = OFS * 2 + 256;
00253 uchar tab[TABSZ];
00254 const uchar* sptr = src.ptr();
00255 int srcstep = src.step;
00256 cv::Size size = src.size();
00257
00258 scale_g *= scale_s;
00259
00260 for (x = 0; x < TABSZ; x++)
00261 {
00262 tab[x] = (uchar)(x - OFS < -ftzero ? 0 : x - OFS > ftzero ? ftzero * 2 : x - OFS + ftzero);
00263 }
00264
00265 for (x = 0; x < size.width; x++)
00266 {
00267 vsum[x] = (ushort)(sptr[x] * (wsz2 + 2));
00268 }
00269
00270 for (y = 1; y < wsz2; y++)
00271 {
00272 for (x = 0; x < size.width; x++)
00273 {
00274 vsum[x] = (ushort)(vsum[x] + sptr[srcstep*y + x]);
00275 }
00276 }
00277
00278 for (y = 0; y < size.height; y++)
00279 {
00280 const uchar* top = sptr + srcstep * MAX(y - wsz2 - 1, 0);
00281 const uchar* bottom = sptr + srcstep * MIN(y + wsz2, size.height - 1);
00282 const uchar* prev = sptr + srcstep * MAX(y - 1, 0);
00283 const uchar* curr = sptr + srcstep * y;
00284 const uchar* next = sptr + srcstep * MIN(y + 1, size.height - 1);
00285 uchar* dptr = dst.ptr<uchar>(y);
00286
00287 for (x = 0; x < size.width; x++)
00288 {
00289 vsum[x] = (ushort)(vsum[x] + bottom[x] - top[x]);
00290 }
00291
00292 for (x = 0; x <= wsz2; x++)
00293 {
00294 vsum[-x-1] = vsum[0];
00295 vsum[size.width + x] = vsum[size.width - 1];
00296 }
00297
00298 int sum = vsum[0] * (wsz2 + 1);
00299 for( x = 1; x <= wsz2; x++ )
00300 {
00301 sum += vsum[x];
00302 }
00303
00304 int val = ((curr[0] * 5 + curr[1] + prev[0] + next[0]) * scale_g - sum * scale_s) >> 10;
00305 dptr[0] = tab[val + OFS];
00306
00307 for( x = 1; x < size.width-1; x++ )
00308 {
00309 sum += vsum[x + wsz2] - vsum[x - wsz2 - 1];
00310 val = ((curr[x] * 4 + curr[x - 1] + curr[x + 1] + prev[x] + next[x]) * scale_g - sum * scale_s) >> 10;
00311 dptr[x] = tab[val + OFS];
00312 }
00313
00314 sum += vsum[x+wsz2] - vsum[x - wsz2 - 1];
00315 val = ((curr[x] * 5 + curr[x - 1] + prev[x] + next[x]) * scale_g - sum * scale_s) >> 10;
00316 dptr[x] = tab[val + OFS];
00317 }
00318 }
00319
00320 cv::Mat scale_2_8bit(const cv::Mat& image)
00321 {
00322 if (image.type() == CV_8UC1)
00323 return image;
00324 cv::Mat Image8Bit(image.rows, image.cols, CV_8U), Image8BitColor;
00325
00326 cv::Mat ImageFloat;
00327 image.convertTo(ImageFloat, CV_32F, 1, 0);
00328 double maxVal;
00329 cv::minMaxLoc(ImageFloat.reshape(1,1), NULL, &maxVal);
00330
00331 ImageFloat = ImageFloat*((1 << 8)/pow(2, ceil(log(maxVal)/log(2))));
00332 ImageFloat.convertTo(Image8Bit,CV_8U, 1, 0);
00333 return Image8Bit;
00334 }
00335
00336 cv::Mat scale_2_8bit_color(const cv::Mat& image)
00337 {
00338 if (image.type() == CV_8UC3)
00339 return image;
00340 cv::Mat Image8Bit = scale_2_8bit(image), Image8BitColor;
00341 cvtColor(Image8Bit, Image8BitColor, CV_GRAY2BGR);
00342 return Image8BitColor;
00343 }
00344 }