OpenCV開發筆記(六十二):紅胖子8分鐘帶你深刻了解亞像素角點檢測(圖文並茂+淺顯易懂+程序源碼)

若該文爲原創文章,未經容許不得轉載 原博主博客地址:https://blog.csdn.net/qq21497936 原博主博客導航:http://www.javashuo.com/article/p-wxwjppoc-mo.html 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/106665993 各位讀者,知識無窮而人力有窮,要麼改需求,要麼找專業人士,要麼本身研究 紅胖子(紅模仿)的博文大全:開發技術集合(包含Qt實用技術、樹莓派、三維、OpenCV、OpenGL、ffmpeg、OSG、單片機、軟硬結合等等)持續更新中…(點擊傳送門)函數

OpenCV開發專欄(點擊傳送門)

上一篇:《OpenCV開發筆記(六十一):紅胖子8分鐘帶你深刻了解Shi-Tomasi角點檢測(圖文並茂+淺顯易懂+程序源碼)》 下一篇:持續補充中…ui

<br>.net

前言

  紅胖子,來也!   本篇主要說亞像素角點,又叫次級像素角點,其實通俗來講,就是輸入整數座標,使用最小二乘法迭代計算所需精度的實數座標。code

<br>對象

Demo

  在這裏插入圖片描述   在這裏插入圖片描述   在這裏插入圖片描述   在這裏插入圖片描述   在這裏插入圖片描述   在這裏插入圖片描述

<br>blog

亞像素角點

概述

  進行圖像處理提取用於識別的特徵點進行幾何測量,這一般須要更高的精度,而函數goodFeaturesToTrack()只能提供簡單的像素的坐懷值,也就是說,有時候會須要要實數座標值而不是整數座標值。 亞像素級角點檢測的位置在攝像機標定、跟蹤並重建攝像機的軌跡,或者重被功跟蹤目標的三維結構時候,是一個基本的測量值 。圖片

Shi-Tomasi角點檢測

  goodFeaturesToTrack()函數檢測是的Shi-Tomasi角點。   《OpenCV開發筆記(六十一):紅胖子8分鐘帶你深刻了解Shi-Tomasi角點檢測(圖文並茂+淺顯易懂+程序源碼)ci

亞像素角點檢測原理

  在這裏插入圖片描述   其中,(a)點p附近的圖像是均勻的,其梯度爲0,(b)邊緣的梯度與沿地緣方向的q-p向量正交。在圖中的兩種狀況下,p點梯度與q-p向量的點積均爲0。   假設起始角點q在實際亞像素級角點的附近。檢測全部的q-p向量。若點p位於一個均勻的區域,則點p處的梯度爲0。若q-p向量的方向與邊緣的方向一致,則此邊緣上p點處的梯度與q-p向量正交,在這兩種狀況下,p點處的梯度與q-p向量的點積爲0。能夠在p點周圍找到不少組梯度以及相關的向量q節,令其點集爲0,而後能夠經過求解方程組,方程組的解即爲角點q的亞像素級精度的位置,也就是精確的角點位置。開發

TermCriteri迭代標註類的構造函數

TermCriteria(int type,
             int maxCount,
             double epsilon);
  • 參數一:int類型的type,枚舉爲TermCriteria::Type類型,終止標準的類型:   在這裏插入圖片描述
  • 參數二:int類型的maxCount,最大迭代次數/元素數;
  • 參數三:double類型的epsilon,所需的精度。

函數原型

void cornerSubPix( InputArray image,
                   InputOutputArray corners,
                   Size winSize,
                   Size zeroZone,
                   TermCriteria criteria );
  • 參數一:InputArray類型的image,輸入圖像,即源圖像,填Mat類的對象,必須爲單通道圖像;
  • 參數二:InputOutputArray類型的corners,提供輸入角點的初始座標和精確的輸出座標;
  • 參數三:Sjze類型的winSjze,搜索窗口的一半尺寸。若winSize=Size(5,5),那麼就表示使用(52+1)x(52+1)=11x11大小的搜索窗口。
  • 參數四:Size類型的zeroZone,表示死區的一半尺寸。而死區爲不對搜索區的中央位置作求和運算的區域,用來避免自相關矩陣出現的某些可能的奇異性。值爲(-1,-1)表示沒有死區。
  • 參數五:TermCriteria類型的criteria,求角點的迭代過程的終止條件。即角點位置的肯定,要麼迭代數大於某個設定值,或者是精到達某個設定值。cirteria能夠是最大迭代數目,或者是設定的精確度,也能夠是它們的組合。

<br>get

Demo源碼

void OpenCVManager::testCornerSubPix()
{
    QString fileName1 =
            "E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/1.jpg";
    int width = 400;
    int height = 300;

    cv::Mat srcMat = cv::imread(fileName1.toStdString());
    cv::resize(srcMat, srcMat, cv::Size(width, height));

    cv::String windowName = _windowTitle.toStdString();
    cvui::init(windowName);

    cv::Mat windowMat = cv::Mat(cv::Size(srcMat.cols * 2, srcMat.rows * 3),
                                srcMat.type());

    int qualityLevel = 1;
    int minDistance = 10;
    int iterations = 5;
    int epsilon = 1;
    while(true)
    {
        windowMat = cv::Scalar(0, 0, 0);

        cv::Mat mat;

        cv::Mat tempMat;
        // 原圖先copy到左邊
        mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 1),
                        cv::Range(srcMat.cols * 0, srcMat.cols * 1));
        cv::addWeighted(mat, 0.0f, srcMat, 1.0f, 0.0f, mat);

        {
            // 灰度圖
            cv::Mat grayMat;
            cv::cvtColor(srcMat, grayMat, cv::COLOR_BGR2GRAY);
            cv::Mat grayMat2;
            cv::cvtColor(grayMat, grayMat2, cv::COLOR_GRAY2BGR);
            cv::addWeighted(mat, 0.0f, grayMat2, 1.0f, 0.0f, mat);

            cvui::printf(windowMat, width * 1 + 20, height * 0 + 10, "qualityLevel / 100.0f");
            cvui::trackbar(windowMat, width * 1 + 20, height * 0 + 30, 200, &qualityLevel, 1, 99);
            cvui::printf(windowMat, width * 1 + 20, height * 0 + 80, "minDistance");
            cvui::trackbar(windowMat, width * 1 + 20, height * 0 + 100, 200, &minDistance, 1, 100);
            cvui::printf(windowMat, width * 1 + 20, height * 0 + 150, "iterations");
            cvui::trackbar(windowMat, width * 1 + 20, height * 0 + 170, 200, &iterations, 1, 100);
            cvui::printf(windowMat, width * 1 + 20, height * 0 + 220, "epsilon/100.0f");
            cvui::trackbar(windowMat, width * 1 + 20, height * 0 + 240, 200, &epsilon, 1, 1000);

            // Shi-Tomasi角點檢測
            std::vector<cv::Point2f> corners;
            cv::goodFeaturesToTrack(grayMat,    // 輸入圖像
                                    corners,    // 輸出角點
                                    100,        // 最大輸出角點數量
                                    qualityLevel / 100.0f,  // 最小特徵值
                                    minDistance,    // 最小間隔距離
                                    cv::noArray(),  // 感興趣的區域
                                    3,          // 計算矩陣時的領域範圍
                                    false,      // 不適用harris角點檢測
                                    0.04);      // 權重係數

            cv::Mat tempMat4 = srcMat.clone();
            for (int i = 0; i < corners.size(); i++)
            {
                cv::circle(tempMat4, corners[i], 5, cv::Scalar(0, 255, 0), 2, 8, 0);
                cvui::printf(windowMat, width * 0 + 20, height * 1 + 20 * i, "%f,%f", corners[i].x, corners[i].y);
            }
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),
                            cv::Range(srcMat.cols * 0, srcMat.cols * 1));
            cv::addWeighted(mat, 0.0f, tempMat4, 1.0f, 0.0f, mat);
            //指定亞像素計算迭代標註
            cv::TermCriteria criteria = cv::TermCriteria(
                            cv::TermCriteria::EPS,
                            iterations,         // 迭代次數
                            epsilon);           // 精度

            //亞像素檢測

            cv::cornerSubPix(grayMat,
                             corners,
                             cv::Size(5, 5),
                             cv::Size(-1, -1),
                             criteria);

            //將檢測到的亞像素角點繪製到原圖上
            cv::Mat tempMat3 = srcMat.clone();
            for (int i = 0; i < corners.size(); i++)
            {
                cv::circle(tempMat3, corners[i], 5, cv::Scalar(0, 255, 0), 2, 8, 0);
                cvui::printf(windowMat, width * 1 + 20, height * 1 + 20 * i, "%f,%f", corners[i].x, corners[i].y);
            }
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),
                            cv::Range(srcMat.cols * 1, srcMat.cols * 2));
            cv::addWeighted(mat, 0.0f, tempMat3, 1.0f, 0.0f, mat);

        }
        // 更新
        cvui::update();
        // 顯示
        cv::imshow(windowName, windowMat);
        // esc鍵退出
        if(cv::waitKey(25) == 27)
        {
            break;
        }
    }
}

<br>

工程模板:對應版本號v1.56.0

  對應版本號v1.56.0

<br>

上一篇:《OpenCV開發筆記(六十一):紅胖子8分鐘帶你深刻了解Shi-Tomasi角點檢測(圖文並茂+淺顯易懂+程序源碼)》 下一篇:持續補充中…

<br>

原博主博客地址:https://blog.csdn.net/qq21497936 原博主博客導航:http://www.javashuo.com/article/p-wxwjppoc-mo.html 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/106665993

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息