remove_small_connnected_area.cc 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "opencv2/highgui.hpp"
  15. #include "opencv2/imgproc/imgproc.hpp"
  16. #include "ultra_infer/vision/visualize/visualize.h"
  17. namespace ultra_infer {
  18. namespace vision {
  19. cv::Mat RemoveSmallConnectedArea(const cv::Mat &alpha_pred, float threshold) {
  20. cv::Mat gray, binary;
  21. alpha_pred.convertTo(gray, CV_8UC1, 255.f);
  22. cv::Mat alpha_pred_clone = alpha_pred.clone();
  23. // 255 * 0.05 ~ 13
  24. unsigned int binary_threshold = static_cast<unsigned int>(255.f * threshold);
  25. cv::threshold(gray, binary, binary_threshold, 255, cv::THRESH_BINARY);
  26. // morphologyEx with OPEN operation to remove noise first.
  27. auto kernel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3, 3),
  28. cv::Point(-1, -1));
  29. cv::morphologyEx(binary, binary, cv::MORPH_OPEN, kernel);
  30. // Computationally connected domain
  31. cv::Mat labels = cv::Mat::zeros(alpha_pred_clone.size(), CV_32S);
  32. cv::Mat stats, centroids;
  33. int num_labels =
  34. cv::connectedComponentsWithStats(binary, labels, stats, centroids, 8, 4);
  35. if (num_labels <= 1) {
  36. // no noise, skip.
  37. return alpha_pred;
  38. }
  39. // find max connected area, 0 is background
  40. int max_connected_id = 1; // 1,2,...
  41. int max_connected_area = stats.at<int>(max_connected_id, cv::CC_STAT_AREA);
  42. for (int i = 1; i < num_labels; ++i) {
  43. int tmp_connected_area = stats.at<int>(i, cv::CC_STAT_AREA);
  44. if (tmp_connected_area > max_connected_area) {
  45. max_connected_area = tmp_connected_area;
  46. max_connected_id = i;
  47. }
  48. }
  49. const int h = alpha_pred_clone.rows;
  50. const int w = alpha_pred_clone.cols;
  51. // remove small connected area.
  52. for (int i = 0; i < h; ++i) {
  53. int *label_row_ptr = labels.ptr<int>(i);
  54. float *alpha_row_ptr = alpha_pred_clone.ptr<float>(i);
  55. for (int j = 0; j < w; ++j) {
  56. if (label_row_ptr[j] != max_connected_id)
  57. alpha_row_ptr[j] = 0.f;
  58. }
  59. }
  60. return alpha_pred_clone;
  61. }
  62. cv::Mat Visualize::RemoveSmallConnectedArea(const cv::Mat &alpha_pred,
  63. float threshold) {
  64. cv::Mat gray, binary;
  65. alpha_pred.convertTo(gray, CV_8UC1, 255.f);
  66. cv::Mat alpha_pred_clone = alpha_pred.clone();
  67. // 255 * 0.05 ~ 13
  68. unsigned int binary_threshold = static_cast<unsigned int>(255.f * threshold);
  69. cv::threshold(gray, binary, binary_threshold, 255, cv::THRESH_BINARY);
  70. // morphologyEx with OPEN operation to remove noise first.
  71. auto kernel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3, 3),
  72. cv::Point(-1, -1));
  73. cv::morphologyEx(binary, binary, cv::MORPH_OPEN, kernel);
  74. // Computationally connected domain
  75. cv::Mat labels = cv::Mat::zeros(alpha_pred_clone.size(), CV_32S);
  76. cv::Mat stats, centroids;
  77. int num_labels =
  78. cv::connectedComponentsWithStats(binary, labels, stats, centroids, 8, 4);
  79. if (num_labels <= 1) {
  80. // no noise, skip.
  81. return alpha_pred;
  82. }
  83. // find max connected area, 0 is background
  84. int max_connected_id = 1; // 1,2,...
  85. int max_connected_area = stats.at<int>(max_connected_id, cv::CC_STAT_AREA);
  86. for (int i = 1; i < num_labels; ++i) {
  87. int tmp_connected_area = stats.at<int>(i, cv::CC_STAT_AREA);
  88. if (tmp_connected_area > max_connected_area) {
  89. max_connected_area = tmp_connected_area;
  90. max_connected_id = i;
  91. }
  92. }
  93. const int h = alpha_pred_clone.rows;
  94. const int w = alpha_pred_clone.cols;
  95. // remove small connected area.
  96. for (int i = 0; i < h; ++i) {
  97. int *label_row_ptr = labels.ptr<int>(i);
  98. float *alpha_row_ptr = alpha_pred_clone.ptr<float>(i);
  99. for (int j = 0; j < w; ++j) {
  100. if (label_row_ptr[j] != max_connected_id)
  101. alpha_row_ptr[j] = 0.f;
  102. }
  103. }
  104. return alpha_pred_clone;
  105. }
  106. } // namespace vision
  107. } // namespace ultra_infer