Advertisement
Guest User

Untitled

a guest
Nov 12th, 2019
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.57 KB | None | 0 0
  1. //============================================================================
  2. // Name : Dip2.cpp
  3. // Author : Ronny Haensch
  4. // Version : 2.0
  5. // Copyright : -
  6. // Description :
  7. //============================================================================
  8.  
  9. #include "Dip2.h"
  10.  
  11. using namespace std;
  12.  
  13.  
  14. namespace dip2 {
  15.  
  16. float distance(int currentX, int currentY, int neighborX, int neighborY)
  17. {
  18. return float(sqrt(pow(currentX - neighborX, 2) + pow(currentY - neighborY, 2)));
  19. }
  20.  
  21. float CalculateKernelBilateralFilter(float distance, float sigma)
  22. {
  23. return exp(-(pow(distance, 2)) / (2 * pow(sigma, 2))) / (2 * CV_PI * pow(sigma, 2));
  24. }
  25. /**
  26. * @brief Convolution in spatial domain.
  27. * @details Performs spatial convolution of image and filter kernel.
  28. * @params src Input image
  29. * @params kernel Filter kernel
  30. * @returns Convolution result
  31. */
  32.  
  33. cv::Mat_<float> spatialConvolution(const cv::Mat_<float>& src, const cv::Mat_<float>& kernel)
  34. {
  35. cv::Mat_<float> result = cv::Mat::zeros(src.size(), src.type());
  36. cv::Mat_<float> tempKernel = cv::Mat::zeros(kernel.size(), kernel.type());
  37. int colMiddle, rowMiddle;
  38. int row, col, i, j;
  39. double sum = 0;
  40. colMiddle = ((kernel.cols-1) / 2);
  41. rowMiddle = ((kernel.rows-1) / 2);
  42.  
  43. /*flip columns*/
  44. for( row = 0; row < kernel.rows; row++){
  45. for ( col = 0; col < kernel.cols; col++) {
  46. if ((col != colMiddle) && (col < colMiddle))
  47. {
  48. tempKernel[row][col] = kernel[row][kernel.cols - 1 - col];
  49. tempKernel[row][kernel.cols - 1 - col] = kernel[row][col];
  50. }
  51. else if(col == colMiddle)
  52. {
  53. tempKernel[row][col] = kernel[row][col];
  54. }
  55. else
  56. {
  57. /*do nothing*/
  58. }
  59. }
  60. }
  61.  
  62. /*flip rows*/
  63. for (col = 0; col < kernel.cols; col++) {
  64. for (row = 0; row < kernel.rows; row++) {
  65. if ((row != rowMiddle) && (row < rowMiddle))
  66. {
  67. tempKernel[row][col] = tempKernel[kernel.rows - 1 - row][col];
  68. tempKernel[kernel.rows - 1 - row][col] = tempKernel[row][col];
  69. }
  70. else if (row == rowMiddle)
  71. {
  72. tempKernel[row][col] = tempKernel[row][col];
  73. }
  74. else
  75. {
  76.  
  77. }
  78. }
  79. }
  80.  
  81. /*multiplication and integration*/
  82. for ( i = 0; i < src.rows; i++) {
  83. for ( j = 0; j < src.cols; j++) {
  84. {
  85. if (((i + tempKernel.rows - 1) > (src.rows - 1)) || ((j + tempKernel.cols - 1) > (src.cols - 1)))
  86. {
  87. /*do nothing*/
  88. // cout << "there is an error here";
  89.  
  90. break;
  91. }
  92. else
  93. {
  94. for (row = 0; row < tempKernel.rows; row++) {
  95. for (col = 0; col < tempKernel.cols; col++) {
  96. // cout << "row=" << row << "\tcol=" << col;
  97. sum = sum + (src[row+i][col+j] * tempKernel[col][row]);
  98. }
  99. }
  100. }
  101.  
  102. }
  103. //cout << "i=" << i << "\tj=" << j;
  104. result[i+1][j+1] = sum;
  105. sum = 0;
  106. }
  107. }
  108.  
  109. return result;
  110. }
  111.  
  112. /**
  113. * @brief Moving average filter (aka box filter)
  114. * @note: you might want to use Dip2::spatialConvolution(...) within this function
  115. * @param src Input image
  116. * @param kSize Window size used by local average
  117. * @returns Filtered image
  118. */
  119. cv::Mat_<float> averageFilter(const cv::Mat_<float>& src, int kSize)
  120. {
  121. cv::Mat_<float> result = cv::Mat::zeros(src.size(), src.type());
  122. cv::Mat kernel = cv::Mat(kSize, kSize, CV_32FC1, 1./9.);
  123. int sum = 0;
  124. result = spatialConvolution(src, kernel);
  125. return result;
  126. }
  127.  
  128. /**
  129. * @brief Median filter
  130. * @param src Input image
  131. * @param kSize Window size used by median operation
  132. * @returns Filtered image
  133. */
  134. cv::Mat_<float> medianFilter(const cv::Mat_<float>& src, int kSize)
  135. {
  136. cv::Mat_<float> result = cv::Mat::zeros(src.size(), src.type());
  137. int size = kSize * kSize;
  138. int element = 0;
  139. vector<float> array(size);
  140. int center = 0;
  141. int index = 0;
  142. float median = 0;
  143. for (int i = 0; i < src.rows; i++) {
  144. for (int j = 0; j < src.cols; j++) {
  145. if (((i+kSize-1)>(src.rows-1))||((j+kSize-1)>(src.cols-1)))
  146. {
  147. /*do nothing*/
  148. continue;
  149. }
  150. else
  151. {
  152. for (int row = 0; row < kSize; row++){
  153. for (int col = 0; col < kSize; col++) {
  154. array[element++] = src[row+i][col+j];
  155. }
  156. }
  157. }
  158. /*find center index*/
  159. if ((element % 2) == 0)
  160. {
  161. center = element / 2;
  162. }
  163. else
  164. {
  165. center = (element + 1) / 2;
  166. }
  167. element = 0;
  168. /*sort the array*/
  169. sort(array.begin(), array.end());
  170. /*find median*/
  171. median = array[center];
  172. /*median filtered matrix*/
  173. result[i + 1][j + 1] = median;
  174. median = 0;
  175. }
  176. }
  177. return result;
  178. }
  179.  
  180. /**
  181. * @brief Bilateral filer
  182. * @param src Input image
  183. * @param kSize Size of the kernel
  184. * @param sigma_spatial Standard-deviation of the spatial kernel
  185. * @param sigma_radiometric Standard-deviation of the radiometric kernel
  186. * @returns Filtered image
  187. */
  188.  
  189. cv::Mat_<float> bilateralFilter(const cv::Mat_<float>& src, int kSize, float sigma_spatial, float sigma_radiometric)
  190. {
  191. cv::Mat_<float> result = cv::Mat::ones(src.size(), src.type());
  192. cv::Mat_<float> spatWts, radioWts;
  193. float imgFilt = 0, accWt = 0;
  194. float hSpat = 1, hRad = 1, wtCombined = 1;
  195. int neighbourX = 0, neighbourY = 0;
  196. int half = kSize / 2;
  197.  
  198. for (int i = 2; i < src.rows-2; i++) {
  199. for (int j = 2; j < src.cols-2; j++) {
  200. for (int row = 0; row < kSize; row++)
  201. {
  202. for (int col = 0; col < kSize; col++)
  203. {
  204. neighbourX = i - (half - row);
  205. neighbourY = j - (half - col);
  206. hSpat = CalculateKernelBilateralFilter(distance(i, j, neighbourX, neighbourY), sigma_spatial);
  207. hRad = CalculateKernelBilateralFilter(src.at<float>(neighbourX,neighbourY) - src.at<float>(i,j), sigma_radiometric);
  208. wtCombined = hSpat * hRad;
  209. imgFilt = imgFilt + (src[neighbourX][neighbourY]*wtCombined);
  210. accWt = accWt + wtCombined;
  211. }
  212. }
  213. imgFilt = imgFilt / accWt;
  214. result[i][j] = imgFilt;
  215. accWt = 0;
  216. imgFilt = 0;
  217. }
  218. }
  219. return result;
  220. }
  221.  
  222. /**
  223. * @brief Non-local means filter
  224. * @note: This one is optional!
  225. * @param src Input image
  226. * @param searchSize Size of search region
  227. * @param sigma Optional parameter for weighting function
  228. * @returns Filtered image
  229. */
  230. cv::Mat_<float> nlmFilter(const cv::Mat_<float>& src, int searchSize, double sigma)
  231. {
  232. return src.clone();
  233. }
  234.  
  235. /**
  236. * @brief Chooses the right algorithm for the given noise type
  237. * @note: Figure out what kind of noise NOISE_TYPE_1 and NOISE_TYPE_2 are and select the respective "right" algorithms.
  238. */
  239. NoiseReductionAlgorithm chooseBestAlgorithm(NoiseType noiseType)
  240. {
  241. switch (noiseType) {
  242. case NOISE_TYPE_1:
  243. cout << "\nFor Shot noise, median filter has better filtering";
  244. return NR_MEDIAN_FILTER;
  245. break;
  246. case NOISE_TYPE_2:
  247. cout << "\nFor Gaussian noise, moving average filter has better filtering";
  248. return NR_MOVING_AVERAGE_FILTER;
  249. break;
  250. default:
  251. throw std::runtime_error("Unhandled noise type!");
  252. }
  253. }
  254.  
  255.  
  256.  
  257. cv::Mat_<float> denoiseImage(const cv::Mat_<float> &src, NoiseType noiseType, dip2::NoiseReductionAlgorithm noiseReductionAlgorithm)
  258. {
  259.  
  260. // for each combination find reasonable filter parameters
  261.  
  262. switch (noiseReductionAlgorithm) {
  263. case dip2::NR_MOVING_AVERAGE_FILTER:
  264. switch (noiseType) {
  265. case NOISE_TYPE_1:
  266. return dip2::averageFilter(src,3);
  267. case NOISE_TYPE_2:
  268. return dip2::averageFilter(src,3);
  269. default:
  270. throw std::runtime_error("Unhandled noise type!");
  271. }
  272. case dip2::NR_MEDIAN_FILTER:
  273. switch (noiseType) {
  274. case NOISE_TYPE_1:
  275. return dip2::medianFilter(src,3);
  276. case NOISE_TYPE_2:
  277. return dip2::medianFilter(src,3);
  278. default:
  279. throw std::runtime_error("Unhandled noise type!");
  280. }
  281. case dip2::NR_BILATERAL_FILTER:
  282. switch (noiseType) {
  283. case NOISE_TYPE_1:
  284. return dip2::bilateralFilter(src,5, 1.0f,1.0f);
  285. case NOISE_TYPE_2:
  286. return dip2::bilateralFilter(src,5, 1.0f, 1.0f);
  287. default:
  288. throw std::runtime_error("Unhandled noise type!");
  289. }
  290. default:
  291. throw std::runtime_error("Unhandled filter type!");
  292. }
  293. }
  294.  
  295.  
  296. // Helpers, don't mind these
  297.  
  298. const char *noiseTypeNames[NUM_NOISE_TYPES] = {
  299. "NOISE_TYPE_1",
  300. "NOISE_TYPE_2",
  301. };
  302.  
  303. const char *noiseReductionAlgorithmNames[NUM_FILTERS] = {
  304. "NR_MOVING_AVERAGE_FILTER",
  305. "NR_MEDIAN_FILTER",
  306. "NR_BILATERAL_FILTER",
  307. };
  308.  
  309.  
  310. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement