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

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

 

前言

  紅胖子,來也!
  作識別,有時候遇到需求,好比識別一個三角形,並求得三角形三個頂點的角度,這種屬於教育場景相似的,還有其餘場景,那麼檢測角點就顯得很重要了,檢測出角點而且求出其角度。工具

 

Demo

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

 

圖像特徵三大類型

  • 邊緣:圖像強度發生突變的區域,其實就是高強度梯度區域;
  • 角點:兩個邊緣相交的地方,看起來像一個角;
  • 斑點:按特徵劃分的區域,強度特別高、強度特別低或具有特定紋理的區域;
 

Harris角點

概述

  Harris角點檢測是一種基於灰度圖像的角點提取算法,穩定性高,在opencv中harris角點檢測的性能相對較低,由於其使用了高斯濾波。
  基於灰度圖像的角點檢測又分爲基於梯度、基於模板和基於模板梯度組合三類型的方法,而Harris算法就是基於灰度圖像中的基於模板類型的算法。性能

原理

  人眼對角點的識別一般是經過一個局部的小窗口內完成的:若是在各個方向上移動這個小窗口,窗口內的灰度發生了較大的變化,那麼說明窗口內存在角點,具體分爲如下三種狀況:ui

  • 若是在各個方向移動,灰度幾乎不變,說明是平坦區域;
  • 若是隻沿着某一個方向移動,灰度幾乎不變,說明是直線;
  • 若是沿各個方向移動,灰度均發生變化,說明是角點。
      基本的原理,以下圖:
      在這裏插入圖片描述
      具體的計算公式以下:
    在這裏插入圖片描述
      在這裏插入圖片描述
      泰勒展開:
      在這裏插入圖片描述
      代入獲得:
      在這裏插入圖片描述
      其中:
      在這裏插入圖片描述
      二次項函數本質上就是一個橢圓函數,橢圓的扁平率和尺寸是由矩陣M的兩個特徵值決定的。
        在這裏插入圖片描述
      在這裏插入圖片描述
      矩陣M的兩個特徵值與圖像中的角點,邊緣,平坦區域的關係。
      Harris定義角點響應函數即:
      在這裏插入圖片描述
      即R=Det(M)-k*trace(M)*trace(M),k爲經驗常數0.04~0.06 。
      定義當R>threshold時且爲局部極大值的點時,定義爲角點。

Harris函數原型

void cornerHarris(InputArray src,
                  OutputArray dst,
                  int blockSize,
                  int ksize,
                  double k,
                  intborderType=BORDER DEFAULT );
  • 參數一:InputArray類型的src,輸入圖像,即源圖像,填Mat類的對象 便可,且須爲單通道8位或者浮點型圖像;
  • 參數二:OutputArray類型的dst,函數調用後的運算結果存在這裏,即這個參數用於存放Harris角點檢測的輸出結果,和源圖片有同樣的尺寸,特別注意輸出類型是CV_32F;
  • 參數三:int類型的blockSize,表示鄰域的大小;
  • 參數四:int類型的ksize,表示Sobel()算子的孔徑大小;
  • 參數五:double類型的k,Harris角點響應函數,通常爲0.04~0.06;
  • 參數六:int類型的borderType,圖像像素的邊界模式:
      在這裏插入圖片描述

歸一化概述

  歸一化是指對矩陣cv::Mat進行歸一化操做。
  歸一化是一種無量綱處理手段,使物理系統數值的絕對值變成某種相對值關係。簡化計算,縮小量值的有效辦法。例如,濾波器中各個頻率值以截止頻率做歸一化後,頻率都是截止頻率的相對值,沒有了量綱。阻抗以電源內阻做歸一化後,各個阻抗都成了一種相對阻抗值,「歐姆」這個量綱也沒有了。等各類運算都結束後,反歸一化一切都復原了。信號處理工具箱中常常使用的是nyquist頻率,它被定義爲採樣頻率的二分之一,在濾波器的階數選擇和設計中的截止頻率均使用nyquist頻率進行歸一化處理。例如對於一個採樣頻率爲500hz的系統,400hz的歸一化頻率就爲400/500=0.8,歸一化頻率範圍在[0,1]之間。
  .net

歸一化函數原型

void normalize( InputArray src,
                InputOutputArray dst,
                double alpha = 1,
                double beta = 0,
                int norm_type = NORM_L2,
                int dtype = -1,
                InputArray mask = noArray());
  • 參數一:InputArray類型的src,通常爲mat;
  • 參數二:InputOutputArray類型的dst,通常爲mat,大小與src同樣;
  • 參數三:double類型的alpha,歸一化的最小值,默認值1;
  • 參數四:double類型的beta,歸一化的最大值,默認值0;
  • 參數五:int類型的norm_type,歸一化類型,具體查看cv::NormTypes,默認爲;
  • 參數六:int類型的dtype,默認值-1,負數時,其輸出矩陣與src類型相同,不然它和src有一樣的通道數,且此時圖像深度爲CV_MAT_DEPTH。
  • 參數七:InputArray類型的mask,可選的操做掩膜,默認值爲noArray();

加強圖像函數原型

void convertScaleAbs(InputArray src,
                     OutputArray dst,
                     double alpha = 1,
                     double beta = 0);
  • 參數一:InputArray類型的src,通常爲mat;
  • 參數二:OutputArray類型的dst,通常爲mat,大小與src同樣;
  • 參數三:double類型的alpha,歸一化的最大值,默認值1;
  • 參數四:double類型的beta,歸一化的最大值,默認值0;
 

Demo源碼

void OpenCVManager::testHarris()
{
    QString fileName1 =
            "E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/16.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 threshold1 = 200;
    int threshold2 = 100;
    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);
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),
                            cv::Range(srcMat.cols * 0, srcMat.cols * 1));
            cv::Mat grayMat2;
            cv::cvtColor(grayMat, grayMat2, cv::COLOR_GRAY2BGR);
            cv::addWeighted(mat, 0.0f, grayMat2, 1.0f, 0.0f, mat);

            // 均值濾波
            cv::blur(grayMat, tempMat, cv::Size(3, 3));

            cvui::printf(windowMat, width * 1 + 20, height * 0 + 20, "threshold1");
            cvui::trackbar(windowMat, width * 1 + 20, height * 0 + 40, 200, &threshold1, 0, 255);
            cvui::printf(windowMat, width * 1 + 20, height * 0 + 100, "threshold2");
            cvui::trackbar(windowMat, width * 1 + 20, height * 0 + 120, 200, &threshold2, 0, 255);

            // canny邊緣檢測
            cv::Canny(tempMat, tempMat, threshold1, threshold2);
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),
                            cv::Range(srcMat.cols * 1, srcMat.cols * 2));
            cv::cvtColor(tempMat, grayMat2, cv::COLOR_GRAY2BGR);
            cv::addWeighted(mat, 0.0f, grayMat2, 1.0f, 0.0f, mat);

            // harris角點檢測
            cv::cornerHarris(grayMat, grayMat2, 2, 3, 0.01);
            // 歸一化與轉換
            cv::normalize(grayMat2, grayMat2, 0, 255, cv::NORM_MINMAX, CV_32FC1, cv::Mat());
            cv::convertScaleAbs(grayMat2 , grayMat2); //將歸一化後的圖線性變換成 8U位元符號整
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),
                            cv::Range(srcMat.cols * 0, srcMat.cols * 1));
            cv::cvtColor(grayMat2, grayMat2, cv::COLOR_GRAY2BGR);

            cv::addWeighted(mat, 0.0f, grayMat2, 1.0f, 0.0f, mat);

            // harris角點檢測
            cv::cornerHarris(tempMat, tempMat, 2, 3, 0.01);
            // 歸一化與轉換
            cv::normalize(tempMat, tempMat, 0, 255, cv::NORM_MINMAX, CV_32FC1, cv::Mat());
            cv::convertScaleAbs(tempMat , tempMat); //將歸一化後的圖線性變換成 8U位元符號整
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),
                            cv::Range(srcMat.cols * 1, srcMat.cols * 2));
            cv::cvtColor(tempMat, tempMat, cv::COLOR_GRAY2BGR);
            cv::addWeighted(mat, 0.0f, tempMat, 1.0f, 0.0f, mat);
        }
        // 更新
        cvui::update();
        // 顯示
        cv::imshow(windowName, windowMat);
        // esc鍵退出
        if(cv::waitKey(25) == 27)
        {
            break;
        }
    }
}
 

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

  對應版本號v1.54.0設計

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