1. 程式人生 > >cv::cornerSubPix()亞畫素角點檢測

cv::cornerSubPix()亞畫素角點檢測

轉自https://blog.csdn.net/guduruyu/article/details/69537083
cv::goodFeaturesToTrack()提取到的角點只能達到畫素級別,在很多情況下並不能滿足實際的需求,這時,我們則需要使用cv::cornerSubPix()對檢測到的角點作進一步的優化計算,可使角點的精度達到亞畫素級別。

具體呼叫形式如下:
    void cv::cornerSubPix(
        cv::InputArray image, // 輸入影象
        cv::InputOutputArray corners, // 角點(既作為輸入也作為輸出)
        cv::Size winSize, // 區域大小為 NXN; N=(winSize*2+1)
        cv::Size zeroZone, // 類似於winSize,但是總具有較小的範圍,Size(-1,-1)表示忽略
        cv::TermCriteria criteria // 停止優化的標準
    );

第一個引數是輸入影象,和cv::goodFeaturesToTrack()中的輸入影象是同一個影象。
第二個引數是檢測到的角點,即是輸入也是輸出。

第三個引數是計算亞畫素角點時考慮的區域的大小,大小為NXN; N=(winSize*2+1)。

第四個引數作用類似於winSize,但是總是具有較小的範圍,通常忽略(即Size(-1, -1))。

第五個引數用於表示計算亞畫素時停止迭代的標準,可選的值有cv::TermCriteria::MAX_ITER 、cv::TermCriteria::EPS(可以是兩者其一,或兩者均選),前者表示迭代次數達到了最大次數時停止,後者表示角點位置變化的最小值已經達到最小時停止迭代。二者均使用cv::TermCriteria()建構函式進行指定。

下面就通過一個示例看看cv::cornerSubPix()亞畫素角點檢測的具體效果。


    cv::Mat image_color = cv::imread("image.jpg", cv::IMREAD_COLOR);
 
    //用於繪製亞畫素角點
    cv::Mat image_copy = image_color.clone();
    //使用灰度影象進行角點檢測
    cv::Mat image_gray;
    cv::cvtColor(image_color, image_gray, cv::COLOR_BGR2GRAY);
 
    //設定角點檢測引數
    std::vector<cv::Point2f> corners;
    int max_corners = 100;
    double quality_level = 0.01;
    double min_distance = 10;
    int block_size = 3;
    bool use_harris = false;
    double k = 0.04;
 
    //角點檢測
    cv::goodFeaturesToTrack(image_gray,
        corners,
        max_corners,
        quality_level,
        min_distance,
        cv::Mat(),
        block_size,
        use_harris,
        k);
 
    //將檢測到的角點繪製到原圖上
    for (int i = 0; i < corners.size(); i++)
    {
        cv::circle(image_color, corners[i], 5, cv::Scalar(0, 0, 255), 2, 8, 0);
    }
 
    //指定亞畫素計算迭代標註
    cv::TermCriteria criteria = cv::TermCriteria(
                    cv::TermCriteria::MAX_ITER + cv::TermCriteria::EPS,
                    40,
                    0.01);
 
    //亞畫素檢測
    cv::cornerSubPix(image_gray, corners, cv::Size(5, 5), cv::Size(-1, -1), criteria);
 
    //將檢測到的亞畫素角點繪製到原圖上
    for (int i = 0; i < corners.size(); i++)
    {
        cv::circle(image_copy, corners[i], 5, cv::Scalar(0, 255, 0), 2, 8, 0);
    }
 
    cv::imshow("corner", image_color);
    cv::imshow("sub pixel corner", image_copy);
 
    cv::imwrite("corner.jpg", image_color);
    cv::imwrite("corner_sub.jpg", image_copy);
    cv::waitKey(0);
    return;


直接角點檢測和亞畫素角點檢測的結果分別如下,從檢測的效果來看,使用亞畫素角點檢測后角點的精細度確實得到了顯著的提升。