<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ##形態學及邊緣角點檢測 形態學濾波理論于上世紀90年代提出,目前被廣泛用于分析及處理離散圖像。其基本運算有4個: 膨脹、腐蝕、開啟和閉合, 它們在二值圖像和灰度圖像中各有特點。基于這些基本運算還可推導和組合成各種數學形態學實用算法,用它們可以進行圖像形狀和結構的分析及處理,包括圖像分割、特征抽取、邊緣檢測、 圖像濾波、圖像增強和恢復等。數學形態學方法利用一個稱作結構元素的“探針”收集圖像的信息,當探針在圖像中不斷移動時, 便可考察圖像各個部分之間的相互關系,從而了解圖像的結構特征。數學形態學基于探測的思想,與人的FOA(Focus Of Attention)的視覺特點有類似之處。其中最重要的結構元素,可直接攜帶知識(形態、大小、甚至加入灰度和色度信息)來探測、研究圖像的結構特點。鑒于研究所需,記錄一些知識點,開發平臺為OpenCV2.4.9+Qt5.3.2。 一:圖像腐蝕、膨脹和開閉運算 這些運算的基本公式和原理參考:[http://blog.csdn.net/liyuefeilong/article/details/43374777](http://blog.csdn.net/liyuefeilong/article/details/43374777)? 圖像的腐蝕:替換為當前像素位像素集合中的最小像素值,函數為cv::erode? 圖像的膨脹:替換為當前像素位像素集合中的最大像素值,函數為cv::dilate? 圖像的開運算:先腐蝕后膨脹,函數為cv::morphologyEx,對應的參數為MORPH_CLOSE? 圖像的閉運算:先膨脹后腐蝕,函數為cv::morphologyEx,對應的參數為MORPH_OPEN? 如morphologyEx(image, opened, cv::MORPH_OPEN, element2, cv::Point(-1,-1), 1); 中,輸入圖像為image,輸出圖像為opened,執行開操作,結構元素為element2,原點參數cv::Point(-1,-1)表示原點位于矩陣的中心(默認),最后的1則表示對圖像的操作次數(注:對一幅圖像多次使用開操作和閉操作時效果不會有改善,這些運算是等冪的)。形態學濾波本是基于二值圖像上,但以上這些運算同樣適用于灰度圖像。 新建一個Qt控制臺應用,創建一個類:MorphoFeatures: ~~~ #ifndef MORPHOFEATURES_H #define MORPHOFEATURES_H #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> class MorphoFeatures { public: void fourFunctions(cv::Mat &image); // 腐蝕、膨脹、開操作、閉操作 } #endif // MORPHOFEATURES_H ~~~ ~~~ void MorphoFeatures::fourFunctions(cv::Mat &image) { // 腐蝕運算,替換為當前像素位像素集合中的最小像素值 cv::Mat eroded; cv::erode(image, eroded, cv::Mat()); // 膨脹運算,替換為當前像素位像素集合中的最大像素值 cv::Mat dilated; cv::dilate(image, dilated, cv::Mat()); // 閉運算,先膨脹后腐蝕 cv::Mat closed; cv::Mat element1(3, 3, CV_8U, cv::Scalar(1)); cv::morphologyEx(image, // 輸入圖像 closed, // 輸出圖像 cv::MORPH_CLOSE, // 指定操作 element1, // 結構元素設置 cv::Point(-1,-1), // 操作的位置 1); // 操作的次數 //開運算,先腐蝕后膨脹 cv::Mat opened; cv::Mat element2(3, 3, CV_8U, cv::Scalar(1)); cv::morphologyEx(image, opened, cv::MORPH_OPEN, element2, cv::Point(-1,-1), 1); cv::namedWindow("Eroded Image"); cv::imshow("Eroded Image", eroded); cv::namedWindow("Dilated Image"); cv::imshow("Dilated Image", dilated); cv::namedWindow("Orginal Image"); cv::imshow("Orginal Image", image); cv::namedWindow("Closed Image"); cv::imshow("Closed Image", closed); cv::namedWindow("Opened Image"); cv::imshow("Opened Image", opened); } ~~~ 得出四種操作的處理效果:? ![](https://box.kancloud.cn/2015-12-30_5683a74add9c8.jpg) ![](https://box.kancloud.cn/2015-12-30_5683a74b1a1d1.jpg) 這里你會覺得腐蝕與膨脹、開操作與閉操作的效果和期望是相反的。這是因為我們認為圖像素材中黑色字體是前景,白色為背景。而一般的,形態學規定用高像素表示前景物體,用低像素表示背景,因此**使用這些基本運算之前,可以根據實際情況給原圖像取反。** 二、利用形態學濾波進行邊緣檢測 形態學濾波利用梯度進行邊緣檢測,其原理是計算膨脹后的圖像和腐蝕后的圖像的差值,由于兩個變換后的圖像不同之處主要在邊緣處,圖像邊緣將通過求差得到強化。函數為morphologyEx,參數為MORPH_GRADIENT。若架構元素尺寸越大,檢測出的邊緣越厚。最簡單的邊緣檢測運算是用原圖減去腐蝕后的圖像,或者用膨脹后的圖像減去原圖或腐蝕圖像,效果很直觀,缺點是得到的邊緣較薄。 以下給出形態學濾波進行邊緣檢測的基本方法:? 在class MorphoFeatures中添加幾個函數: ~~~ public: cv::Mat getEdges(const cv::Mat &image); void setThreshold(int gate); // 設定閾值 private: void applyThreshold(cv::Mat &result); ~~~ 在morphofeatures.cpp中添加: ~~~ void MorphoFeatures::setThreshold(int gate) { threshold = gate; } cv::Mat MorphoFeatures::getEdges(const cv::Mat &image) { // 得到梯度圖 cv::Mat result; cv::morphologyEx(image, result, cv::MORPH_GRADIENT, cv::Mat()); // 閾值化以得到二值圖像 applyThreshold(result); return result; } void MorphoFeatures::applyThreshold(cv::Mat &result) { // 使用閾值化 if(threshold > 0) { cv::threshold(result, result, threshold, 255, cv::THRESH_BINARY); } } ~~~ 簡單修改main函數: ~~~ #include <QCoreApplication> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include "morphofeatures.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); MorphoFeatures h; cv::Mat image = cv::imread("c:\\gray.jpg"); // h.fourFunctions(image); // 邊緣檢測 h.setThreshold(80); // 設定閾值 cv::Mat result = h.getEdges(image); cv::namedWindow("Input Image"); cv::imshow("Input Image",image); cv::namedWindow("Edge"); cv::imshow("Edge",result); return a.exec(); } ~~~ 效果:? ![](https://box.kancloud.cn/2015-12-30_5683a74b46d7d.jpg) ![](https://box.kancloud.cn/2015-12-30_5683a74b5ee7e.jpg) 效果差強人意……除此之外,還可以用sobel算子、Canny算子等對圖像進行邊緣檢測,這些方法都可以通過改變結構元素來實現,如下圖所示為幾種3*3的Sobel算子。基于Sobel算子的邊緣檢測見:[http://blog.csdn.net/liyuefeilong/article/details/43452711](http://blog.csdn.net/liyuefeilong/article/details/43452711)? ![](https://box.kancloud.cn/2015-12-30_5683a74b7ed27.jpg) 另外一個應用是對圖像進行形態學tophat變換,用h表示,定義為:? ![](https://box.kancloud.cn/2015-12-30_5683a74b925f8.jpg)? 其中,f是輸入圖像,B是結構元素函數。tophat變換對于增強灰度圖像的陰影細節很有用處。 三、利用形態學濾波進行圖像角點檢測 這里使用四種不同的結構元素檢測圖像角點,分別為十字型、菱型、x型和方形元素,尺寸規定為5*5。與邊緣檢測不同,角點的檢測復雜。運算過程主要分三步: 第一步,先用十字形的結構元素膨脹原圖像,這種情況下只會在邊緣處“擴張”,角點不發生變化。接著用菱形的結構元素腐蝕原圖像,只有拐角處才會被“收縮”,而直線邊緣不發生變化。 第二步,用X型的結構元素膨脹原圖像,角點膨脹的比邊要多。這樣第二次用方塊腐蝕時,角點恢復原狀,而邊要腐蝕的更多。 第三步,將一二步的兩幅輸出圖像相減,結果只保留了各個拐角處的細節。 首先在類MorphoFeatures.h中添加: ~~~ public: cv::Mat getCorners(const cv::Mat &image); // 角點檢測函數 void drawOnImage(const cv::Mat &binary, cv::Mat &image); // 在角點處標記圓圈 // 以下構造四種不同的結構元素用來檢測灰度圖像的角點 MorphoFeatures():threshold(-1), cross(5,5,CV_8U,cv::Scalar(0)), diamond(5,5,CV_8U,cv::Scalar(1)), square(5,5,CV_8U,cv::Scalar(1)), x(5,5,CV_8U,cv::Scalar(0)) { // 5*5的十字形元素 for (int i=0; i<5; i++) { cross.at<uchar>(2,i)= 1; cross.at<uchar>(i,2)= 1; } // 5*5的菱形元素 diamond.at<uchar>(0,0)= 0; diamond.at<uchar>(0,1)= 0; diamond.at<uchar>(1,0)= 0; diamond.at<uchar>(4,4)= 0; diamond.at<uchar>(3,4)= 0; diamond.at<uchar>(4,3)= 0; diamond.at<uchar>(4,0)= 0; diamond.at<uchar>(4,1)= 0; diamond.at<uchar>(3,0)= 0; diamond.at<uchar>(0,4)= 0; diamond.at<uchar>(0,3)= 0; diamond.at<uchar>(1,4)= 0; // 5*5的x型元素 for (int i=0; i<5; i++) { x.at<uchar>(i,i)= 1; x.at<uchar>(4-i,i)= 1; } } ~~~ 接著,在morphofeatures.cpp中添加: ~~~ cv::Mat MorphoFeatures::getCorners(const cv::Mat &image) { cv::Mat result; // 十字膨脹 cv::dilate(image, result, cross); // 棱形腐蝕 形態學函數支持原地操作 cv::erode(result, result, diamond); cv::Mat result2; // x型膨脹 cv::dilate(image, result2, x); // 方形腐蝕 cv::erode(result2, result2, square); // 對result和result2這兩張圖像相減,得到焦點圖像 cv::absdiff(result2, result, result); // 閾值化,得到二值圖像 applyThreshold(result); cv::namedWindow("Corners"); cv::imshow("Corners", result); return result; } void MorphoFeatures::drawOnImage(const cv::Mat &binary, cv::Mat &image) { cv::Mat_<uchar>::const_iterator it = binary.begin<uchar>(); cv::Mat_<uchar>::const_iterator itend = binary.end<uchar>(); for(int i=0; it!=itend; ++it, ++i) { if(*it) // 若該像素被標定為角點則畫白色圈圈 { cv::circle(image, cv::Point(i%image.step, i/image.step), 5, cv::Scalar(255, 255, 255)); } } } ~~~ 在main.cpp中簡單添加: ~~~ cv::Mat corners; corners = h.getCorners(image); h.drawOnImage(corners, image); cv::namedWindow("Corners On Image"); cv::imshow("Corners On Image", image); ~~~ 效果: ![](https://box.kancloud.cn/2015-12-30_5683a74ba1911.jpg) ![](https://box.kancloud.cn/2015-12-30_5683a74bb6f78.jpg) 在這里,需要把輸入圖像轉化為二值圖像,因此閾值的選擇會影響角點檢測效果,如下圖所示: ![](https://box.kancloud.cn/2015-12-30_5683a74be8087.jpg) ![](https://box.kancloud.cn/2015-12-30_5683a74c22e82.jpg) 盡管角點檢測效果有好有壞,不過實現該方法,對于理解腐蝕、膨脹、開操作、閉操作有很好的幫助。 歡迎轉載或分享,但請務必聲明文章出處~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看