成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

OpenCV成長之路:直線、輪廓的提取與描述

移動開發(fā) Android
基于內(nèi)容的圖像分析的重點是提取出圖像中具有代表性的特征,而線條、輪廓、塊往往是最能體現(xiàn)特征的幾個元素,這篇文章就針對于這幾個重要的圖像特征,研究它們在OpenCV中的用法,以及做一些簡單的基礎(chǔ)應(yīng)用。

本文是51CTO博客作者Ronny的文章,原文地址

基于內(nèi)容的圖像分析的重點是提取出圖像中具有代表性的特征,而線條、輪廓、塊往往是最能體現(xiàn)特征的幾個元素,這篇文章就針對于這幾個重要的圖像特征,研究它們在OpenCV中的用法,以及做一些簡單的基礎(chǔ)應(yīng)用。

一、Canny檢測輪廓

在 上一篇文章中有提到sobel邊緣檢測,并重寫了soble的C++代碼讓其與matlab中算法效果一致,而soble邊緣檢測是基于單一閾值的,我們 不能兼顧到低閾值的豐富邊緣和高閾值時的邊緣缺失這兩個問題。而canny算子則很好的彌補了這一不足,從目前看來,canny邊緣檢測在做圖像輪廓提取 方面是***秀的邊緣檢測算法。

canny邊緣檢測采用雙閾值值法,高閾值用來檢測圖像中重要的、顯著的線條、輪廓等,而低閾值用來保證不丟失細節(jié)部分,低閾值檢測出來的邊緣更豐富,但是很多邊緣并不是我們關(guān)心的。***采用一種查找算法,將低閾值中與高閾值的邊緣有重疊的線條保留,其他的線條都刪除。

本篇文章中不對canny的算法原理作進一步說明,稍后會在圖像處理算法相關(guān)的文章中詳細介紹。

下面我們用OpenCV中的Canny函數(shù)來檢測圖像邊緣

  1. int main() 
  2.     Mat I=imread("../cat.png"); 
  3.     cvtColor(I,I,CV_BGR2GRAY); 
  4.                                                  
  5.     Mat contours; 
  6.     Canny(I,contours,125,350); 
  7.     threshold(contours,contours,128,255,THRESH_BINARY); 
  8.     namedWindow("Canny"); 
  9.     imshow("Canny",contours); 
  10.     waitKey(); 
  11.     return 0; 

顯示效果如下:

image

二、直線檢測

直線在圖像中出現(xiàn)的頻率非常之高,而直線作為圖像的特征對于基本內(nèi)容的圖像分析有著很重要的作用,本文通過OpenCV中的hough變換來檢測圖像中的線條。

我們先看最基本的Hough變換函數(shù)HoughLines,它的原型如下:

  1. void HoughLines(InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn=0, double stn=0 ); 

它的輸入是一個二值的輪廓圖像,往往是邊緣檢測得到的結(jié)果圖像;它的輸出是一個包含多個Vec2f點的數(shù)組,數(shù)組中的每個元素是一個二元浮點數(shù)據(jù) 對<rou,theta>,rou代表直線離坐標原點的距離,theta代表角度。第3和第4個參數(shù)代表步長,因為Hough變換實際上是一 個窮舉的算法,rho表示距離的步長,theta代表角度的步長。第5個參數(shù)是一個閾值設(shè)置直接的***投票個數(shù),知道Hough原理的,這個參數(shù)應(yīng)該很容 易理解。

從 這個函數(shù)的輸出結(jié)果我們可以看出,得到的直線并沒有指定在圖像中的開始點與結(jié)束點,需要我們自己去計算,如果我們想把直接顯示在圖像中就會比較麻煩,而且 會有很多角度接近的直線,其實它們是重復(fù)的,為了解決上面這些問題,OpenCV又提供了一個函數(shù)HoughLinesP()。它的輸出是一個 Vector of Vec4i。Vector每一個元素代表一條直線,是由一個4元浮點數(shù)組構(gòu)成,前兩個點一組,后兩個點一組,代表了在圖像中直線的起始和結(jié)束點。

  1. void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta,int threshold, double minLineLength=0, double maxLineGap=0 ); 

解釋一下***兩個參數(shù),minLineLength指定了檢測直線中的最小寬度,如果低于最小寬度則舍棄掉,maxLineGap指定通過同一點的直線,如果距離小于maxLineGap就會進行合并。

下面是一個用HoughLinesP檢測直線的例子:

  1. int main() 
  2.     Mat image=imread("../car.png"); 
  3.     Mat I; 
  4.     cvtColor(image,I,CV_BGR2GRAY); 
  5.                              
  6.     Mat contours; 
  7.     Canny(I,contours,125,350); 
  8.     threshold(contours,contours,128,255,THRESH_BINARY); 
  9.     vector<Vec4i> lines; 
  10.     // 檢測直線,最小投票為90,線條不短于50,間隙不小于10 
  11.     HoughLinesP(contours,lines,1,CV_PI/180,80,50,10); 
  12.     drawDetectLines(image,lines,Scalar(0,255,0)); 
  13.     namedWindow("Lines"); 
  14.     imshow("Lines",image); 
  15.     waitKey(); 
  16.     return 0; 

上面程序?qū)z測到的線條保存在lines變量內(nèi),我們需要進一步將它們畫在圖像上:

  1. void drawDetectLines(Mat& image,const vector<Vec4i>& lines,Scalar & color) 
  2.     // 將檢測到的直線在圖上畫出來 
  3.     vector<Vec4i>::const_iterator it=lines.begin(); 
  4.     while(it!=lines.end()) 
  5.     { 
  6.         Point pt1((*it)[0],(*it)[1]); 
  7.         Point pt2((*it)[2],(*it)[3]); 
  8.         line(image,pt1,pt2,color,2); //  線條寬度設(shè)置為2 
  9.         ++it; 
  10.     } 

image

實 際上Hough變換可以檢測很多固定的形狀,比如:圓、正方形等。它們的原理基本相同,都是構(gòu)造一個投票矩陣。OpenCV里提供了檢測圓的函數(shù) HoughCircles,它的輸出是一個Vector of Vec3i,Vector的每個元素包含了3個浮點數(shù),前2個是圓的中心坐標,***一個是半徑。

三、輪廓的提取與描述

在目標識別中我們首先要把感興趣的目標提取出來,而一般常見的步驟都是通過顏色或紋理提取出目標的前景圖(一幅黑白圖像,目標以白色顯示在圖像中),接下來我們要對前景圖進行分析進一步地把目標提取出來,而這里常常用到的就是提取目標的輪廓。

OpenCV 里提取目標輪廓的函數(shù)是findContours,它的輸入圖像是一幅二值圖像,輸出的是每一個連通區(qū)域的輪廓點的集 合:vector<vector<Point>>。外層vector的size代表了圖像中輪廓的個數(shù),里面vector的 size代表了輪廓上點的個數(shù)。下面我們通過實例來看函數(shù)的用法。

  1. int main() 
  2.   { 
  3.       using namespace cv; 
  4.              
  5.       Mat image=imread("../shape.png"); 
  6.       cvtColor(image,image,CV_BGR2GRAY); 
  7.      vector<vector<Point>> contours; 
  8.      // find 
  9.      findContours(image,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE); 
  10.     // draw 
  11.      Mat result(image.size(),CV_8U,Scalar(0)); 
  12.      drawContours(result,contours,-1,Scalar(255),2); 
  13.             
  14.      namedWindow("contours"); 
  15.      imshow("contours",result); 
  16.      waitKey(); 
  17.      return 0; 

image

上面程序中包含了2個函數(shù),***個是查找輪廓函數(shù),它的第三個參數(shù)說明查找輪廓的類型,這里我們使用的是外輪廓,還可以查找所有輪廓,即包括一些孔洞的部 分,像圖像人物胳膊與腰間形成的輪廓。第4個參數(shù)說明了輪廓表示的方法,程序中的參數(shù)說明輪廓包括了所有點,也可以用其他參數(shù)讓有點直線的地方,只保存直 線起始與終點的位置點,具體參數(shù)用法可以參考手冊里函數(shù)的介紹。

第二個函數(shù)drawContours是一個畫輪廓的函數(shù),它的第3個參數(shù)程序里設(shè)置-1表示所有的輪廓都畫,你也可以指定要畫的輪廓的序號。

提取到輪廓后,其實我們更關(guān)心的是如果把這些輪廓轉(zhuǎn)換為可以利用的特征,也就是涉及到輪廓的描述問題,這時就有多種方法可以選擇,比如矢量化為多邊形、矩形、橢圓等。OpenCV里提供了一些這樣的函數(shù)。

  1. // 輪廓表示為一個矩形 
  2. Rect r = boundingRect(Mat(contours[0])); 
  3. rectangle(result, r, Scalar(255), 2); 
  4. // 輪廓表示為一個圓 
  5. float radius; 
  6. Point2f center; 
  7. minEnclosingCircle(Mat(contours[1]), center, radius); 
  8. circle(result, Point(center), static_cast<int>(radius), Scalar(255), 2); 
  9. // 輪廓表示為一個多邊形 
  10. vector<Point> poly; 
  11. approxPolyDP(Mat(contours[2]), poly, 5, true); 
  12. vector<Point>::const_iterator itp = poly.begin(); 
  13. while (itp != (poly.end() - 1)) 
  14.     line(result, *itp, *(itp + 1), Scalar(255), 2); 
  15.     ++itp; 
  16. line(result, *itp, *(poly.begin()), Scalar(255), 2); 
  17. // 輪廓表示為凸多邊形 
  18. vector<Point> hull; 
  19. convexHull(Mat(contours[3]), hull); 
  20. vector<Point>::const_iterator ith = hull.begin(); 
  21. while (ith != (hull.end() - 1)) 
  22.     line(result, *ith, *(ith + 1), Scalar(255), 2); 
  23.     ++ith; 
  24. line(result, *ith, *(hull.begin()), Scalar(255), 2); 

程序中我們依次畫了矩形、圓、多邊形和凸多邊形。最終效果如下:

image

對連通區(qū)域的分析到此遠遠沒有結(jié)束,我們可以進一步計算每一個連通區(qū)域的其他屬性,比如:重心、中心矩等特征,這些內(nèi)容以后有機會展開來寫。

以 下幾個函數(shù)可以嘗試:minAreaRect:計算一個最小面積的外接矩形,contourArea可以計算輪廓內(nèi)連通區(qū)域的面 積;pointPolygenTest可以用來判斷一個點是否在一個多邊形內(nèi)。mathShapes可以比較兩個形狀的相似性,相當(dāng)有用的一個函數(shù)。

責(zé)任編輯:徐川 來源: 51CTO博客
相關(guān)推薦

2013-02-26 09:41:31

微信Line

2021-11-29 08:24:57

騰訊技術(shù)職業(yè)

2022-08-24 15:57:17

圖片輪廓

2009-12-14 15:18:38

2013-04-15 10:09:18

Web架構(gòu)師

2013-04-15 11:08:00

架構(gòu)師Web

2015-03-30 17:08:55

IT服務(wù)神州數(shù)碼華為

2009-07-08 13:08:30

JNCIEJuniper認證

2012-04-05 10:25:02

WEB架構(gòu)師

2010-07-20 13:52:27

SQL Server

2012-03-31 10:00:05

WEB架構(gòu)師

2020-12-10 06:27:19

技術(shù)人

2024-01-30 12:07:51

2012-05-23 09:32:01

2021-08-22 15:14:00

Vue開發(fā)前端

2010-08-20 15:21:11

2023-08-20 12:21:18

軟件開發(fā)架構(gòu)設(shè)計

2018-01-09 15:39:42

云計算網(wǎng)絡(luò)安全

2021-07-20 09:39:35

前端開發(fā)技術(shù)
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 国产一区免费视频 | 免费在线h视频 | 欧美一区二区在线观看 | 国产精品毛片一区二区在线看 | 国产精品入口久久 | 天天干.com | 免费在线看黄视频 | 少妇淫片aaaaa毛片叫床爽 | 九九热九九 | 国产精品入口麻豆www | 毛片一区二区三区 | 久久综合av | 欧美精品一区二区三区蜜桃视频 | 伊人网综合| a在线视频观看 | 在线免费观看黄a | 久久99精品久久久久久秒播九色 | 一区二区三区欧美 | 天堂一区二区三区 | 国产91av视频 | 成年人网站在线观看视频 | h片在线免费看 | 久久99精品久久 | 最新91在线 | 国产欧美一区二区三区在线看蜜臀 | 日韩三级在线 | 少妇淫片aaaaa毛片叫床爽 | 成人免费观看男女羞羞视频 | 91久久久久久久久久久 | 91中文字幕在线 | 成人99| 久久成人一区 | 国产欧美在线观看 | 亚洲精品久久久久久首妖 | 午夜国产在线 | 在线日韩欧美 | 99国产精品视频免费观看一公开 | 天天综合久久网 | 99精品免费在线观看 | 国产免费麻豆视频 | 91精品一区二区三区久久久久 |