zoukankan      html  css  js  c++  java
  • Opencv形态学变换 膨胀腐蚀

      1 //生成三种基元 矩形 十字 椭圆
      2 cv::Mat my_get_morph_struct_element(cv::MorphShapes shapeType, cv::Size s)
      3 {
      4     CV_Assert(shapeType == cv::MORPH_RECT || shapeType == cv::MORPH_CROSS || shapeType == cv::MORPH_ELLIPSE);
      5 
      6     cv::Mat mat = cv::Mat::zeros(s, CV_8UC1);
      7     switch (shapeType)
      8     {
      9         case cv::MORPH_RECT:
     10         {
     11             mat = 1;
     12             break;
     13         }
     14         case cv::MORPH_CROSS:
     15         {
     16             cv::Mat rowROI(mat, cv::Rect(0, s.height / 2, s.width, 1));
     17             rowROI = 1;
     18             cv::Mat colROI(mat, cv::Rect(s.width / 2, 0, 1, s.height));
     19             colROI = 1;
     20             break;
     21         }
     22         case cv::MORPH_ELLIPSE:
     23         {
     24             int a = s.width / 2;
     25             int b = s.height / 2;
     26             //椭圆 公式 (x-xc)^2 / a^2 + (y-yc)^2 / b^2 = 1
     27             for (int i = 0; i < s.height; i++)
     28             {
     29                 int dy = i - b;
     30                 int startx = 0;
     31                 int endx = 0;
     32                 if (std::abs(dy) <= b)
     33                 {
     34                     int dx = 0;
     35                     if (b > 0)
     36                     {
     37                         dx = cv::saturate_cast<int>(a * std::sqrt(1 - (1.0 * dy / b)*(1.0 * dy / b)));
     38                     }
     39                     startx =std::max(a - dx, 0);
     40                     endx = std::min(a + dx + 1, s.width);
     41                 }
     42 
     43                 uchar * p = mat.ptr<uchar>(i);
     44                 for (int j = startx; j < endx; j++)
     45                 {
     46                     p[j] = 1;
     47                 }
     48             }
     49             break;
     50         }
     51         default:
     52             CV_Assert(false);
     53             break;
     54     }
     55 
     56     return mat;
     57 }
     58 
     59 //测试自己生成的基元
     60 void test_my_get_morph_struct_element()
     61 {
     62     cv::MorphShapes shape = cv::MORPH_RECT;
     63     cv::Size s(7, 8);
     64     cv::Mat rectSE = cv::getStructuringElement(shape, s);
     65     cv::Mat myRectSE = my_get_morph_struct_element(shape, s);
     66     std::cout << "rectSE:
    " << rectSE << std::endl;
     67     std::cout << "myrectSE:
    " << myRectSE << std::endl;
     68 
     69     shape = cv::MORPH_CROSS;
     70     rectSE = cv::getStructuringElement(shape, s);
     71     myRectSE = my_get_morph_struct_element(shape, s);
     72     std::cout << "CROSSSE:
    " << rectSE << std::endl;
     73     std::cout << "mCROSSSE:
    " << myRectSE << std::endl;
     74 
     75     shape = cv::MORPH_ELLIPSE;
     76     rectSE = cv::getStructuringElement(shape, s);
     77     myRectSE = my_get_morph_struct_element(shape, s);
     78     std::cout << "MORPH_ELLIPSE:
    " << rectSE << std::endl;
     79     std::cout << "mMORPH_ELLIPSE:
    " << myRectSE << std::endl;
     80 }
     81 
     82 //侵蚀与膨胀变换:
     83 //图像上的一个点,以这个点为中心(假设为(i,j)点),结构元素的中心与这个中心重合
     84 //然后取出图像上被结构元素覆盖的那一小片(对于边界处,作边界扩展),如果结构元素的值
     85 //为1,则从这一小片图像中对于的位置取出值,所有结构元素为1的位置都取出了对应那一
     86 //小片图像中的值后,这些值中再取出最大值和最小值,对于侵蚀变换,则点(i,j)的值设置
     87 //为最小值,而膨胀变换,则点(i,j)的值设置为最大值。
     88 
     89 /*
     90  *matPadded 按照结构元补充过边界后的矩阵
     91  */
     92 cv::Mat my_erode_dilate(const cv::Mat& matPadded, const cv::Mat& se, bool isErode)
     93 {
     94     CV_Assert(matPadded.type() == CV_8UC1);
     95     CV_Assert(se.type() == CV_8UC1);
     96     
     97     int rows = matPadded.rows - se.rows;
     98     int cols = matPadded.cols - se.cols;
     99     cv::Mat mat(rows, cols, CV_8UC1);
    100     for (int i = 0; i < rows; i++)
    101     {
    102         uchar *p = mat.ptr<uchar>(i);
    103         for (int j = 0; j < cols; j++)
    104         {
    105             cv::Mat roi(matPadded, cv::Rect(j, i, se.cols, se.rows));
    106             std::vector<uchar> v;
    107             for (int ii = 0; ii < roi.rows; ii++)
    108             {
    109                 uchar * pp = roi.ptr<uchar>(ii);
    110                 const uchar * ppp = se.ptr<uchar>(ii);
    111                 for (int jj = 0; jj < roi.cols; jj++)
    112                 {
    113                     if (ppp[jj] == 1)
    114                     {
    115                         v.push_back(pp[jj]);
    116                     }
    117                 }
    118             }
    119             std::sort(v.begin(), v.end());
    120             p[j] = isErode ? v[0] : v[v.size() - 1];
    121         }
    122     }
    123 
    124     return mat;
    125 }
    126 
    127 
    128 void test_my_erode_dilate()
    129 {
    130     cv::Mat src = cv::imread("D:\programfiles\OpenCV\opencv-4.4.0\samples\data\lena.jpg", IMREAD_GRAYSCALE);
    131     if (src.empty())
    132     {
    133         std::cout << "Failed to load img!!" << std::endl;
    134         return;
    135     }
    136 
    137     //opencv自带
    138     cv::MorphShapes shape = cv::MorphShapes::MORPH_ELLIPSE;
    139     cv::Size seSize(7, 8);
    140     cv::Mat se = cv::getStructuringElement(shape, seSize);
    141     cv::Mat erodeMat;
    142     cv::Mat dilateMat;
    143     cv::erode(src, erodeMat, se);
    144     cv::dilate(src, dilateMat, se);
    145     cv::imshow("erode", erodeMat);
    146     cv::imshow("dilate", dilateMat);
    147 
    148     //自己实现的
    149     //填充边界
    150     int padLeft = se.cols / 2;
    151     int padRight = (se.cols % 2 == 0) ? se.cols / 2 - 1 : se.cols / 2;
    152     int padTop = se.rows / 2;
    153     int padBot = (se.rows % 2 == 0) ? se.rows / 2 - 1 : se.rows / 2;
    154     cv::Mat paddedMat;
    155     cv::copyMakeBorder(src, paddedMat, padTop, padBot, padLeft, padRight, BORDER_REFLECT101);
    156     cv::Mat myErodeMat = my_erode_dilate(paddedMat, se, true);
    157     cv::Mat myDilateMat = my_erode_dilate(paddedMat, se, false);
    158     cv::imshow("myErodeMat", myErodeMat);
    159     cv::imshow("myDilateMat", myDilateMat);
    160 
    161     waitKey(0);
    162 }
  • 相关阅读:
    leetcode 141. Linked List Cycle
    leetcode 367. Valid Perfect Square
    leetcode150 Evaluate Reverse Polish Notation
    小a与星际探索
    D. Diverse Garland
    C. Nice Garland
    数的划分(动态规划)
    平衡二叉树(笔记)
    1346:【例4-7】亲戚(relation)
    1192:放苹果(dp + 搜索)
  • 原文地址:https://www.cnblogs.com/merlinzjl/p/14354340.html
Copyright © 2011-2022 走看看