DepthRender.hpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #ifndef PERCIPIO_SAMPLE_COMMON_DEPTH_RENDER_HPP_
  2. #define PERCIPIO_SAMPLE_COMMON_DEPTH_RENDER_HPP_
  3. #include <opencv2/opencv.hpp>
  4. #ifndef CV_VERSION_EPOCH
  5. #if defined (CV_MAJOR_VERSION) && (CV_VERSION_MAJOR == 4)
  6. #include <opencv2/imgproc/types_c.h>
  7. #include <opencv2/imgcodecs/legacy/constants_c.h>
  8. #endif
  9. #endif
  10. #include <map>
  11. #include <vector>
  12. class DepthRender {
  13. public:
  14. enum OutputColorType {
  15. COLORTYPE_RAINBOW = 0,
  16. COLORTYPE_BLUERED = 1,
  17. COLORTYPE_GRAY = 2
  18. };
  19. enum ColorRangeMode {
  20. COLOR_RANGE_ABS = 0,
  21. COLOR_RANGE_DYNAMIC = 1
  22. };
  23. DepthRender() : needResetColorTable(true)
  24. , color_type(COLORTYPE_BLUERED)
  25. , range_mode(COLOR_RANGE_DYNAMIC)
  26. , min_distance(0)
  27. , max_distance(0)
  28. , invalid_label(0)
  29. {}
  30. void SetColorType( OutputColorType ct = COLORTYPE_BLUERED ){
  31. if(ct != color_type){
  32. needResetColorTable = true;
  33. color_type = ct;
  34. }
  35. }
  36. void SetRangeMode( ColorRangeMode rm = COLOR_RANGE_DYNAMIC ){
  37. if(range_mode != rm){
  38. needResetColorTable = true;
  39. range_mode = rm;
  40. }
  41. }
  42. /// for abs mode
  43. void SetColorRange(int minDis, int maxDis){
  44. min_distance = minDis;
  45. max_distance = maxDis;
  46. }
  47. /// input 16UC1 output 8UC3
  48. void Compute(const cv::Mat &src, cv::Mat& dst ){
  49. dst = Compute(src);
  50. }
  51. cv::Mat Compute(const cv::Mat &src){
  52. cv::Mat src16U;
  53. if(src.type() != CV_16U){
  54. src.convertTo(src16U, CV_16U);
  55. }else{
  56. src16U = src;
  57. }
  58. if(needResetColorTable){
  59. BuildColorTable();
  60. needResetColorTable = false;
  61. }
  62. cv::Mat dst;
  63. filtered_mask = (src16U == invalid_label);
  64. clr_disp = src16U.clone();
  65. if(COLOR_RANGE_ABS == range_mode) {
  66. TruncValue(clr_disp, filtered_mask, min_distance, max_distance);
  67. clr_disp -= min_distance;
  68. clr_disp = clr_disp * 255 / (max_distance - min_distance);
  69. clr_disp.convertTo(clr_disp, CV_8UC1);
  70. } else {
  71. short vmax, vmin;
  72. HistAdjustRange(clr_disp, invalid_label, min_distance, vmin, vmax);
  73. clr_disp = (clr_disp - vmin) * 255 / (vmax - vmin);
  74. //clr_disp = 255 - clr_disp;
  75. clr_disp.convertTo(clr_disp, CV_8UC1);
  76. }
  77. switch (color_type) {
  78. case COLORTYPE_GRAY:
  79. clr_disp = 255 - clr_disp;
  80. cv::cvtColor(clr_disp, dst, cv::COLOR_GRAY2BGR);
  81. break;
  82. case COLORTYPE_BLUERED:
  83. //temp = 255 - clr_disp;
  84. CalcColorMap(clr_disp, dst);
  85. //cv::applyColorMap(temp, color_img, cv::COLORMAP_COOL);
  86. break;
  87. case COLORTYPE_RAINBOW:
  88. //cv::cvtColor(color_img, color_img, CV_GRAY2BGR);
  89. cv::applyColorMap(clr_disp, dst, cv::COLORMAP_RAINBOW);
  90. break;
  91. }
  92. ClearInvalidArea(dst, filtered_mask);
  93. return dst;
  94. }
  95. private:
  96. void CalcColorMap(const cv::Mat &src, cv::Mat &dst){
  97. std::vector<cv::Scalar> &table = _color_lookup_table;
  98. assert(table.size() == 256);
  99. assert(!src.empty());
  100. assert(src.type() == CV_8UC1);
  101. dst.create(src.size(), CV_8UC3);
  102. const unsigned char* sptr = src.ptr<unsigned char>();
  103. unsigned char* dptr = dst.ptr<unsigned char>();
  104. for (int i = src.size().area(); i != 0; i--) {
  105. cv::Scalar &v = table[*sptr];
  106. dptr[0] = (unsigned char)v.val[0];
  107. dptr[1] = (unsigned char)v.val[1];
  108. dptr[2] = (unsigned char)v.val[2];
  109. dptr += 3;
  110. sptr += 1;
  111. }
  112. }
  113. void BuildColorTable(){
  114. _color_lookup_table.resize(256);
  115. cv::Scalar from(50, 0, 0xff), to(50, 200, 255);
  116. for (int i = 0; i < 128; i++) {
  117. float a = (float)i / 128;
  118. cv::Scalar &v = _color_lookup_table[i];
  119. for (int j = 0; j < 3; j++) {
  120. v.val[j] = from.val[j] * (1 - a) + to.val[j] * a;
  121. }
  122. }
  123. from = to;
  124. to = cv::Scalar(255, 104, 0);
  125. for (int i = 128; i < 256; i++) {
  126. float a = (float)(i - 128) / 128;
  127. cv::Scalar &v = _color_lookup_table[i];
  128. for (int j = 0; j < 3; j++) {
  129. v.val[j] = from.val[j] * (1 - a) + to.val[j] * a;
  130. }
  131. }
  132. }
  133. //keep value in range
  134. void TruncValue(cv::Mat &img, cv::Mat &mask, short min_val, short max_val){
  135. assert(max_val >= min_val);
  136. assert(img.type() == CV_16SC1);
  137. assert(mask.type() == CV_8UC1);
  138. short* ptr = img.ptr<short>();
  139. unsigned char* mask_ptr = mask.ptr<unsigned char>();
  140. for (int i = img.size().area(); i != 0; i--) {
  141. if (*ptr > max_val) {
  142. *ptr = max_val;
  143. *mask_ptr = 0xff;
  144. } else if (*ptr < min_val) {
  145. *ptr = min_val;
  146. *mask_ptr = 0xff;
  147. }
  148. ptr++;
  149. mask_ptr++;
  150. }
  151. }
  152. void ClearInvalidArea(cv::Mat &clr_disp, cv::Mat &filtered_mask){
  153. assert(clr_disp.type() == CV_8UC3);
  154. assert(filtered_mask.type() == CV_8UC1);
  155. assert(clr_disp.size().area() == filtered_mask.size().area());
  156. unsigned char* filter_ptr = filtered_mask.ptr<unsigned char>();
  157. unsigned char* ptr = clr_disp.ptr<unsigned char>();
  158. int len = clr_disp.size().area();
  159. for (int i = 0; i < len; i++) {
  160. if (*filter_ptr != 0) {
  161. ptr[0] = ptr[1] = ptr[2] = 0;
  162. }
  163. filter_ptr++;
  164. ptr += 3;
  165. }
  166. }
  167. void HistAdjustRange(const cv::Mat &dist, short invalid, int min_display_distance_range
  168. , short &min_val, short &max_val) {
  169. std::map<short, int> hist;
  170. int sz = dist.size().area();
  171. const short* ptr = dist.ptr < short>();
  172. int total_num = 0;
  173. for (int idx = sz; idx != 0; idx--, ptr++) {
  174. if (invalid == *ptr) {
  175. continue;
  176. }
  177. total_num++;
  178. if (hist.find(*ptr) != hist.end()) {
  179. hist[*ptr]++;
  180. } else {
  181. hist.insert(std::make_pair(*ptr, 1));
  182. }
  183. }
  184. if (hist.empty()) {
  185. min_val = 0;
  186. max_val = 2000;
  187. return;
  188. }
  189. const int delta = total_num * 0.01;
  190. int sum = 0;
  191. min_val = hist.begin()->first;
  192. for (std::map<short, int>::iterator it = hist.begin(); it != hist.end();it++){
  193. sum += it->second;
  194. if (sum > delta) {
  195. min_val = it->first;
  196. break;
  197. }
  198. }
  199. sum = 0;
  200. max_val = hist.rbegin()->first;
  201. for (std::map<short, int>::reverse_iterator s = hist.rbegin()
  202. ; s != hist.rend(); s++) {
  203. sum += s->second;
  204. if (sum > delta) {
  205. max_val = s->first;
  206. break;
  207. }
  208. }
  209. const int min_display_dist = min_display_distance_range;
  210. if (max_val - min_val < min_display_dist) {
  211. int m = (max_val + min_val) / 2;
  212. max_val = m + min_display_dist / 2;
  213. min_val = m - min_display_dist / 2;
  214. if (min_val < 0) {
  215. min_val = 0;
  216. }
  217. }
  218. }
  219. bool needResetColorTable;
  220. OutputColorType color_type;
  221. ColorRangeMode range_mode;
  222. int min_distance;
  223. int max_distance;
  224. uint16_t invalid_label;
  225. cv::Mat clr_disp ;
  226. cv::Mat filtered_mask;
  227. std::vector<cv::Scalar> _color_lookup_table;
  228. };
  229. #endif