aihot  2017-05-18 19:17:53  OpenCV |   查看评论   

实现代码threshold.hpp:

  1. // fbc_cv是免费软件,并且使用与OpenCV相同的许可证
  2.   
  3. #ifndef FBC_CV_THRESHOLD_HPP_  
  4. #define FBC_CV_THRESHOLD_HPP_  
  5.   
  6. /* reference: include/opencv2/imgproc.hpp 
  7.               modules/imgproc/src/thresh.cpp 
  8. */  
  9.   
  10. #include <typeinfo>  
  11. #include "core/mat.hpp"  
  12. #include "imgproc.hpp"  
  13.   
  14. namespace fbc {  
  15.   
  16. template<typename _Tp, int chs> static double getThreshVal_Otsu_8u(const Mat_<_Tp, chs>& src);  
  17. template<typename _Tp, int chs> static double getThreshVal_Triangle_8u(const Mat_<_Tp, chs>& src);  
  18. template<typename _Tp, int chs> static void thresh_8u(const Mat_<_Tp, chs>& _src, Mat_<_Tp, chs>& _dst, uchar thresh, uchar maxval, int type);  
  19. template<typename _Tp, int chs> static void thresh_32f(const Mat_<_Tp, chs>& _src, Mat_<_Tp, chs>& _dst, float thresh, float maxval, int type);  
  20.   
  21. // 将固定级别阈值应用于单通道阵列  
  22. // 大理和三角方法仅适用于8位图像 
  23. // 支持类型:uchar/float,单通道  
  24. template<typename _Tp, int chs>  
  25. double threshold(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst, double thresh, double maxval, int type)  
  26. {  
  27.     FBC_Assert(typeid(uchar).name() == typeid(_Tp).name() || typeid(float).name() == typeid(_Tp).name()); // uchar || float  
  28.     if (dst.empty()) {  
  29.         dst = Mat_<_Tp, chs>(src.rows, src.cols);  
  30.     } else {  
  31.         FBC_Assert(src.rows == dst.rows && src.cols == dst.cols);  
  32.     }  
  33.   
  34.     int automatic_thresh = (type & ~THRESH_MASK);  
  35.     type &= THRESH_MASK;  
  36.   
  37.     FBC_Assert(automatic_thresh != (THRESH_OTSU | THRESH_TRIANGLE));  
  38.     if (automatic_thresh == THRESH_OTSU) {  
  39.         FBC_Assert(sizeof(_Tp) == 1);  
  40.         thresh = getThreshVal_Otsu_8u(src);  
  41.     } else if (automatic_thresh == THRESH_TRIANGLE) {  
  42.         FBC_Assert(sizeof(_Tp) == 1);  
  43.         thresh = getThreshVal_Triangle_8u(src);  
  44.     }  
  45.   
  46.     if (sizeof(_Tp) == 1) {  
  47.         int ithresh = fbcFloor(thresh);  
  48.         thresh = ithresh;  
  49.         int imaxval = fbcRound(maxval);  
  50.         if (type == THRESH_TRUNC)  
  51.             imaxval = ithresh;  
  52.         imaxval = saturate_cast<uchar>(imaxval);  
  53.   
  54.         if (ithresh < 0 || ithresh >= 255) {  
  55.             if (type == THRESH_BINARY || type == THRESH_BINARY_INV ||  
  56.                 ((type == THRESH_TRUNC || type == THRESH_TOZERO_INV) && ithresh < 0) ||  
  57.                 (type == THRESH_TOZERO && ithresh >= 255)) {  
  58.                 int v = type == THRESH_BINARY ? (ithresh >= 255 ? 0 : imaxval) :  
  59.                     type == THRESH_BINARY_INV ? (ithresh >= 255 ? imaxval : 0) :  
  60.                     /*type == THRESH_TRUNC ? imaxval :*/ 0;  
  61.                 dst.setTo(v);  
  62.             }  
  63.             else  
  64.                 src.copyTo(dst);  
  65.             return thresh;  
  66.         }  
  67.         thresh = ithresh;  
  68.         maxval = imaxval;  
  69.     } else if (sizeof(_Tp) == 4) {  
  70.     } else {  
  71.         FBC_Error("UnsupportedFormat");  
  72.     }  
  73.   
  74.     if (sizeof(_Tp) == 1) {  
  75.         thresh_8u(src, dst, (uchar)thresh, (uchar)maxval, type);  
  76.     } else {  
  77.         thresh_32f(src, dst, (float)thresh, (float)maxval, type);  
  78.     }  
  79.   
  80.     return 0;  
  81. }  
  82.   
  83. template<typename _Tp, int chs>  
  84. static double getThreshVal_Otsu_8u(const Mat_<_Tp, chs>& _src)  
  85. {  
  86.     Size size = _src.size();  
  87.     const int N = 256;  
  88.     int i, j, h[N] = { 0 };  
  89.   
  90.     for (i = 0; i < size.height; i++) {  
  91.         const uchar* src = _src.ptr(i);  
  92.         j = 0;  
  93.         for (; j <= size.width - 4; j += 4) {  
  94.             int v0 = src[j], v1 = src[j + 1];  
  95.             h[v0]++; h[v1]++;  
  96.             v0 = src[j + 2]; v1 = src[j + 3];  
  97.             h[v0]++; h[v1]++;  
  98.         }  
  99.         for (; j < size.width; j++)  
  100.             h[src[j]]++;  
  101.     }  
  102.   
  103.     double mu = 0, scale = 1. / (size.width*size.height);  
  104.     for (i = 0; i < N; i++)  
  105.         mu += i*(double)h[i];  
  106.   
  107.     mu *= scale;  
  108.     double mu1 = 0, q1 = 0;  
  109.     double max_sigma = 0, max_val = 0;  
  110.   
  111.     for (i = 0; i < N; i++) {  
  112.         double p_i, q2, mu2, sigma;  
  113.   
  114.         p_i = h[i] * scale;  
  115.         mu1 *= q1;  
  116.         q1 += p_i;  
  117.         q2 = 1. - q1;  
  118.   
  119.         if (std::min(q1, q2) < FLT_EPSILON || std::max(q1, q2) > 1. - FLT_EPSILON)  
  120.             continue;  
  121.   
  122.         mu1 = (mu1 + i*p_i) / q1;  
  123.         mu2 = (mu - q1*mu1) / q2;  
  124.         sigma = q1*q2*(mu1 - mu2)*(mu1 - mu2);  
  125.         if (sigma > max_sigma) {  
  126.             max_sigma = sigma;  
  127.             max_val = i;  
  128.         }  
  129.     }  
  130.   
  131.     return max_val;  
  132. }  
  133.   
  134. template<typename _Tp, int chs>  
  135. static double getThreshVal_Triangle_8u(const Mat_<_Tp, chs>& _src)  
  136. {  
  137.     Size size = _src.size();  
  138.     const int N = 256;  
  139.     int i, j, h[N] = { 0 };  
  140.   
  141.     for (i = 0; i < size.height; i++) {  
  142.         const uchar* src = _src.ptr(i);  
  143.         j = 0;  
  144.         for (; j <= size.width - 4; j += 4) {  
  145.             int v0 = src[j], v1 = src[j + 1];  
  146.             h[v0]++; h[v1]++;  
  147.             v0 = src[j + 2]; v1 = src[j + 3];  
  148.             h[v0]++; h[v1]++;  
  149.         }  
  150.   
  151.         for (; j < size.width; j++)  
  152.             h[src[j]]++;  
  153.     }  
  154.   
  155.     int left_bound = 0, right_bound = 0, max_ind = 0, max = 0;  
  156.     int temp;  
  157.     bool isflipped = false;  
  158.   
  159.     for (i = 0; i < N; i++) {  
  160.         if (h[i] > 0) {  
  161.             left_bound = i;  
  162.             break;  
  163.         }  
  164.     }  
  165.     if (left_bound > 0)  
  166.         left_bound--;  
  167.   
  168.     for (i = N - 1; i > 0; i--) {  
  169.         if (h[i] > 0) {  
  170.             right_bound = i;  
  171.             break;  
  172.         }  
  173.     }  
  174.     if (right_bound < N - 1)  
  175.         right_bound++;  
  176.   
  177.     for (i = 0; i < N; i++) {  
  178.         if (h[i] > max) {  
  179.             max = h[i];  
  180.             max_ind = i;  
  181.         }  
  182.     }  
  183.   
  184.     if (max_ind - left_bound < right_bound - max_ind) {  
  185.         isflipped = true;  
  186.         i = 0, j = N - 1;  
  187.         while (i < j) {  
  188.             temp = h[i]; h[i] = h[j]; h[j] = temp;  
  189.             i++; j--;  
  190.         }  
  191.         left_bound = N - 1 - right_bound;  
  192.         max_ind = N - 1 - max_ind;  
  193.     }  
  194.   
  195.     double thresh = left_bound;  
  196.     double a, b, dist = 0, tempdist;  
  197.   
  198.     // 我们不需要在这里计算精确距离。 距离最大化,所以一些常数可以  
  199.     // 被省略 这样可以加快计算速度。
  200.     a = max; b = left_bound - max_ind;  
  201.     for (i = left_bound + 1; i <= max_ind; i++) {  
  202.         tempdist = a*i + b*h[i];  
  203.         if (tempdist > dist) {  
  204.             dist = tempdist;  
  205.             thresh = i;  
  206.         }  
  207.     }  
  208.     thresh--;  
  209.   
  210.     if (isflipped)  
  211.         thresh = N - 1 - thresh;  
  212.   
  213.     return thresh;  
  214. }  
  215.   
  216. template<typename _Tp, int chs>  
  217. static void thresh_8u(const Mat_<_Tp, chs>& _src, Mat_<_Tp, chs>& _dst, uchar thresh, uchar maxval, int type)  
  218. {  
  219.     int i, j, j_scalar = 0;  
  220.     uchar tab[256];  
  221.     Size roi = _src.size();  
  222.     roi.width *= _src.channels;  
  223.   
  224.     switch (type) {  
  225.     case THRESH_BINARY:  
  226.         for (i = 0; i <= thresh; i++)  
  227.             tab[i] = 0;  
  228.         for (; i < 256; i++)  
  229.             tab[i] = maxval;  
  230.         break;  
  231.     case THRESH_BINARY_INV:  
  232.         for (i = 0; i <= thresh; i++)  
  233.             tab[i] = maxval;  
  234.         for (; i < 256; i++)  
  235.             tab[i] = 0;  
  236.         break;  
  237.     case THRESH_TRUNC:  
  238.         for (i = 0; i <= thresh; i++)  
  239.             tab[i] = (uchar)i;  
  240.         for (; i < 256; i++)  
  241.             tab[i] = thresh;  
  242.         break;  
  243.     case THRESH_TOZERO:  
  244.         for (i = 0; i <= thresh; i++)  
  245.             tab[i] = 0;  
  246.         for (; i < 256; i++)  
  247.             tab[i] = (uchar)i;  
  248.         break;  
  249.     case THRESH_TOZERO_INV:  
  250.         for (i = 0; i <= thresh; i++)  
  251.             tab[i] = (uchar)i;  
  252.         for (; i < 256; i++)  
  253.             tab[i] = 0;  
  254.         break;  
  255.     default:  
  256.         FBC_Error("Unknown threshold type");  
  257.     }  
  258.   
  259.     if (j_scalar < roi.width) {  
  260.         for (i = 0; i < roi.height; i++) {  
  261.             const uchar* src = _src.ptr(i);  
  262.             uchar* dst = _dst.ptr(i);  
  263.             j = j_scalar;  
  264.   
  265.             for (; j <= roi.width - 4; j += 4) {  
  266.                 uchar t0 = tab[src[j]];  
  267.                 uchar t1 = tab[src[j + 1]];  
  268.   
  269.                 dst[j] = t0;  
  270.                 dst[j + 1] = t1;  
  271.   
  272.                 t0 = tab[src[j + 2]];  
  273.                 t1 = tab[src[j + 3]];  
  274.   
  275.                 dst[j + 2] = t0;  
  276.                 dst[j + 3] = t1;  
  277.             }  
  278.   
  279.             for (; j < roi.width; j++)  
  280.                 dst[j] = tab[src[j]];  
  281.         }  
  282.     }  
  283. }  
  284.   
  285. template<typename _Tp, int chs>  
  286. static void thresh_32f(const Mat_<_Tp, chs>& _src, Mat_<_Tp, chs>& _dst, float thresh, float maxval, int type)  
  287. {  
  288.     int i, j;  
  289.     Size roi = _src.size();  
  290.     roi.width *= _src.channels;  
  291.     const float* src = (const float*)_src.ptr();  
  292.     float* dst = (float*)_dst.ptr();  
  293.     size_t src_step = _src.step / sizeof(src[0]);  
  294.     size_t dst_step = _dst.step / sizeof(dst[0]);  
  295.   
  296.     switch (type) {  
  297.     case THRESH_BINARY:  
  298.         for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) {  
  299.             for (j = 0; j < roi.width; j++)  
  300.                 dst[j] = src[j] > thresh ? maxval : 0;  
  301.         }  
  302.         break;  
  303.   
  304.     case THRESH_BINARY_INV:  
  305.         for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) {  
  306.             for (j = 0; j < roi.width; j++)  
  307.                 dst[j] = src[j] <= thresh ? maxval : 0;  
  308.         }  
  309.         break;  
  310.   
  311.     case THRESH_TRUNC:  
  312.         for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) {  
  313.             for (j = 0; j < roi.width; j++)  
  314.                 dst[j] = std::min(src[j], thresh);  
  315.         }  
  316.         break;  
  317.   
  318.     case THRESH_TOZERO:  
  319.         for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) {  
  320.             for (j = 0; j < roi.width; j++) {  
  321.                 float v = src[j];  
  322.                 dst[j] = v > thresh ? v : 0;  
  323.             }  
  324.         }  
  325.         break;  
  326.   
  327.     case THRESH_TOZERO_INV:  
  328.         for (i = 0; i < roi.height; i++, src += src_step, dst += dst_step) {  
  329.             for (j = 0; j < roi.width; j++) {  
  330.                 float v = src[j];  
  331.                 dst[j] = v <= thresh ? v : 0;  
  332.             }  
  333.         }  
  334.         break;  
  335.     default:  
  336.         FBC_Error("BadArg");  
  337.     }  
  338. }  
  339.   
  340. // namespace fbc  
  341.   
  342. #endif // FBC_CV_THRESHOLD_HPP_  

 

除特别注明外,本站所有文章均为 赢咖4注册 原创,转载请注明出处来自OpenCV代码提取: threshold函数的实现

留言与评论(共有 0 条评论)
   
验证码:
[lianlun]1[/lianlun]