opencv-distanceTransform 距離計算函數


 

 

用於計算圖像中每一個非零點距離離自己最近的零點的距離 

1.png

 

 

    cv::Mat src = cv::imread("D:/bb/tu1/1.png",0);
        
    cv::Mat imageThin(src.size(), CV_32FC1); //定義保存距離變換結果的Mat矩陣
    distanceTransform(src, imageThin, CV_DIST_L2, 3);  //距離計算
    /*
    參數1:8-bit, 單通道輸入圖片
    參數2:輸出結果中包含計算的距離,這是一個32-bit  float 單通道的Mat類型,大小與輸入圖片相同
    參數3:distanceType計算距離的類型
        distanceType        maskSize         a \ b \ c     
        CV_DIST_C            3(3X3)         a = 1, b = 1
        CV_DIST_L1            3(3X3)           a = 1, b = 2
        CV_DIST_L2            3(3X3)         a=0.955, b=1.3693
        CV_DIST_L2            5(5X5)         a=1, b=1.4, c=2.1969
    參數4:maskSize – 距離變換掩碼矩陣的大小
        3(CV_DIST_L1、 CV_DIST_L2 、CV_DIST_C)
        5(CV_DIST_L2 )
           CV_DIST_MASK_PRECISE (這個只能在4參數的API中使用)
  參數5:目標矩陣的數據類型
      CV_8U
說明:其中 a b c 含義:在這個函數中計算每個非0像素到黑色像素(0值像素)的最短距離,因此需要通過最短的移動方式找到這個點計算他們之間的值。通常來說移動有水平方向、豎直方向、對角方向、跳躍式幾個移動方法。雖然計算距離的方法都是一些很基礎的公式,但是這個這個掩碼矩陣必須是對陣的,因此掩碼矩陣上所有水平和豎直方向的變化量,這里用 a 代表;對角方向的變化量用 b 代表;跳躍移動的變化量用 c 代表。CV_DIST_C、CV_DIST_L1、CV_DIST_L2(maskSize=5)的計算結果是精確的,CV_DIST_L2(maskSize=3)是一個快速計算方法
*/

 

應用一:細化輪廓

2.png

 

 

    float maxValue = 0;  //保存距離變換矩陣中的最大值
    cv::Mat src = cv::imread("D:/bb/tu1/2.png",0);
    cv::Mat imageGray=~src;  //取反
    cv::GaussianBlur(imageGray, imageGray, cv::Size(5, 5), 2); //濾波-去除雜點
    cv::threshold(imageGray, imageGray, 10, 200, 0); 
    cv::namedWindow("imageGray");
    cv::imshow("imageGray",imageGray);
    cv::Mat imageThin(imageGray.size(), CV_32FC1);
    cv::distanceTransform(imageGray, imageThin, CV_DIST_L2, 3);  //距離計算
    cv::Mat distShow;
    distShow = cv::Mat::zeros(imageGray.size(), CV_8UC1); 
    for (int i = 0; i < imageThin.rows; i++)
    {
        for (int j = 0; j < imageThin.cols; j++)
        {
            if (imageThin.at<float>(i, j) > maxValue)
            {
                maxValue = imageThin.at<float>(i, j);  //獲取距離變換的最大值
            }
        }
    }
    for (int i = 0; i < imageThin.rows; i++)
    {
        for (int j = 0; j < imageThin.cols; j++)
        {
            if (imageThin.at<float>(i, j) > maxValue / 1.9)
            {
                distShow.at<uchar>(i, j) = 255;   //符合距離大於最大值一定比例條件的點設為255
            }
        }
    }
    cv::namedWindow("distShow");
    cv::imshow("distShow", distShow);

 

 

應用二:查找物體質心

3.png

 

 

    cv::Mat src = cv::imread("D:/bb/tu1/3.png");
    cv::Mat imageGray;
    cv::cvtColor(src, imageGray, CV_RGB2GRAY);
    imageGray = ~imageGray;
    
    cv::threshold(imageGray, imageGray, 20, 255, 0);
    cv::Mat imageThin(imageGray.size(), CV_32FC1);
    cv::distanceTransform(imageGray, imageThin, CV_DIST_L2, 3);  //距離變換
    cv::Mat distShow;
    distShow = cv::Mat::zeros(imageGray.size(), CV_8UC1);
    float maxValue = 0;
    cv::Point Pt(0, 0);
    for (int i = 0; i < imageThin.rows; i++)
    {
        for (int j = 0; j < imageThin.cols; j++)
        {
            distShow.at<uchar>(i, j) = imageThin.at<float>(i, j);
            //把float轉換成uchar之后,距離越遠的地方越亮
            if (imageThin.at<float>(i, j) > maxValue)
            {
                maxValue = imageThin.at<float>(i, j);  //獲取距離變換的最大值
                Pt = cv::Point(j, i);  //最大值的坐標
            }
        }
    }
    cv::normalize(distShow, distShow, 0, 255, CV_MINMAX); //為了顯示清晰,做了0~255歸一化
    cv::circle(src, Pt, maxValue, cv::Scalar(0, 0, 255), 3);
    cv::circle(src, Pt, 3, cv::Scalar(0, 255, 0), 3);

    cv::namedWindow("src1");
    cv::imshow("src1", src);
    
    cv::waitKey();

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM