最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

OpenCV 輪廓檢測的實現(xiàn)方法

 更新時間:2019年07月03日 09:53:19   作者:alvin93  
這篇文章主要介紹了OpenCV 輪廓檢測的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

輪廓概述

  1. 輪廓可以簡單認為成將連續(xù)的點(連著邊界)連在一起的曲線,具有相同的顏色或者灰度。輪廓在形狀分析和物體的檢測和識別中很有用。 
  2. 為了更加準確,要使用二值化圖像。在尋找輪廓之前,要進行閾值化處理或者 Canny 邊界檢測。 
  3. 查找輪廓的函數(shù)會修改原始圖像。如果你在找到輪廓之后還想使用原始圖像的話,你應該將原始圖像存儲到其他變量中。 
  4. 在 OpenCV 中,查找輪廓就像在黑色背景中超白色物體,要找的物體應該是白色而背景應該是黑色。

輪廓檢測的作用:

1.可以檢測圖圖像或者視頻中物體的輪廓
2.計算多邊形邊界,形狀逼近和計算感興趣區(qū)域

先看一個較為簡單的輪廓檢測:

import cv2
import numpy as np
# 創(chuàng)建一個200*200的黑色空白圖像
img = np.zeros((200, 200), dtype=np.uint8)
# 利用numpy數(shù)組在切片上賦值的功能放置一個白色方塊
img[50:150, 50:150] = 255

# 對圖像進行二值化操作
# threshold(src, thresh, maxval, type, dst=None)
# src是輸入數(shù)組,thresh是閾值的具體值,maxval是type取THRESH_BINARY或者THRESH_BINARY_INV時的最大值
# type有5種類型,這里取0: THRESH_BINARY ,當前點值大于閾值時,取maxval,也就是前一個參數(shù),否則設為0
# 該函數(shù)第一個返回值是閾值的值,第二個是閾值化后的圖像
ret, thresh = cv2.threshold(img, 127, 255, 0)

# findContours()有三個參數(shù):輸入圖像,層次類型和輪廓逼近方法
# 該函數(shù)會修改原圖像,建議使用img.copy()作為輸入
# 由函數(shù)返回的層次樹很重要,cv2.RETR_TREE會得到圖像中輪廓的整體層次結構,以此來建立輪廓之間的‘關系'。
# 如果只想得到最外面的輪廓,可以使用cv2.RETE_EXTERNAL。這樣可以消除輪廓中其他的輪廓,也就是最大的集合
# 該函數(shù)有三個返回值:修改后的圖像,圖像的輪廓,它們的層次
image, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

color = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
img = cv2.drawContours(color, contours, -1, (0, 255, 0), 2)
cv2.imshow("contours", color)
cv2.waitKey()
cv2.destroyAllWindows()

上面是找到一個正方形的輪廓,下面看如何找到不規(guī)則的多邊形輪廓:

import cv2
import numpy as np

# pyrDown():brief Blurs an image and downsamples it.
# 將圖像高斯平滑,然后進行降采樣
img = cv2.pyrDown(cv2.imread("hammer.jpg", cv2.IMREAD_UNCHANGED))
# 依然是二值化操作
ret, thresh = cv2.threshold(cv2.cvtColor(img.copy(), cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)
# 計算圖像的輪廓
image, contours, hier = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

for c in contours:
  # find bounding box coordinates
  # 先計算出一個簡單的邊界狂,也就是一個矩形啦
  # 就是將輪廓信息轉換為(x,y)坐標,并加上矩形的高度和寬度
  x, y, w, h = cv2.boundingRect(c)
  # 畫出該矩形
  cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)

  # find minimum area
  # 然后計算包圍目標的最小矩形區(qū)域
  # 這里先計算出最小矩形區(qū)域,然后計算區(qū)域的頂點,此時頂點坐標是浮點型,但是像素坐標是整數(shù)
  # 需要將浮點型轉換成矩形
  rect = cv2.minAreaRect(c)
  box = cv2.boxPoints(rect)
  box = np.int0(box)
  # draw contours
  # 畫出最小矩形
  # drawContours()也會修改源圖像
  # 第二個參數(shù)保存輪廓的數(shù)組,也就是保存著很多輪廓
  # 第三個參數(shù)是要繪制的輪廓數(shù)組的索引:-1是繪制所有的輪廓,否則只繪制[box]中指定的輪廓
  # 顏色和thickness(密度,就是粗細)放在最后兩個參數(shù)
  cv2.drawContours(img, [box], 0, (0, 0, 255), 3)

  # calculate center and radius of minimum enclosing circle
  # 最后檢查的邊界輪廓為最小閉圓
  # minEnclosingCircle()會返回一個二元數(shù)組,第一個是圓心坐標組成的元祖,第二個元素是元的半徑
  (x, y), radius = cv2.minEnclosingCircle(c)
  # cast to integers
  center = (int(x), int(y))
  radius = int(radius)
  # draw the circle
  img = cv2.circle(img, center, radius, (255, 0, 0), 3)

# 繪制輪廓
cv2.drawContours(img, contours, -1, (255, 0, 0), 1)
cv2.imshow("contours", img)

cv2.waitKey()
cv2.destroyAllWindows()

凸輪廓與Douglas-Peucker算法

import cv2
import numpy as np

img = cv2.pyrDown(cv2.imread("hammer.jpg", cv2.IMREAD_UNCHANGED))

ret, thresh = cv2.threshold(cv2.cvtColor(img.copy(), cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)
# 創(chuàng)建與源圖像一樣大小的矩陣
black = cv2.cvtColor(np.zeros((img.shape[1], img.shape[0]), dtype=np.uint8), cv2.COLOR_GRAY2BGR)

image, contours, hier = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

for cnt in contours:
  # 得到輪廓的周長作為參考
  epsilon = 0.01 * cv2.arcLength(cnt,True)
  # approxPolyDP()用來計算近似的多邊形框。有三個參數(shù)
  # cnt為輪廓,epsilon為ε——表示源輪廓與近似多邊形的最大差值,越小越接近
  # 第三個是布爾標記,用來表示這個多邊形是否閉合
  approx = cv2.approxPolyDP(cnt,epsilon,True)
  # convexHull()可以從輪廓獲取凸形狀
  hull = cv2.convexHull(cnt)
  # 源圖像輪廓-綠色
  cv2.drawContours(black, [cnt], -1, (0, 255, 0), 2)
  # 近似多邊形-藍色
  cv2.drawContours(black, [approx], -1, (255, 0, 0), 2)
  # 凸包-紅色
  cv2.drawContours(black, [hull], -1, (0, 0, 255), 2)

cv2.imshow("hull", black)
cv2.waitKey()
cv2.destroyAllWindows()

本來也有疑問,有了一個精確的輪廓,為什么還需要一個近似的多邊形?

書中給出答案,近似多邊形是由一組直線構成,這樣可以便于后續(xù)的操作和處理。

想來也是,直線構成的區(qū)域總是比無限個曲率的曲線構成的區(qū)域方便處理。

直線和圓檢測

直線檢測可以通過HoughLinesP函數(shù)完成,HoughLinesP是標準Hough變換經過優(yōu)化,使用概率Hough變換。

import cv2
import numpy as np

img = cv2.imread('lines.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,120)
# 最小直線長度,小于該長度會被消除
minLineLength = 20
# 最大線段間隙,一條直線的間隙長度大于這個值會被認為是兩條直線
maxLineGap = 5
# HoughLinesP()會接受一個由Canny邊緣檢測濾波器處理過的單通道二值圖像
# 不一定需要Canny濾波器,但是輸入是去噪且只有邊緣的圖像,效果會很好
# 第一個參數(shù)是輸入圖像
# 第二、第三個參數(shù)是線段的幾何表示rho和theta,一般取1和np.pi/180
# 第四個參數(shù)是閾值,低于該閾值的直線會被忽略
# 第五第六已經解釋
lines = cv2.HoughLinesP(edges,1,np.pi/180,20,minLineLength,maxLineGap)
for x1,y1,x2,y2 in lines[0]:
  cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2)

cv2.imshow("edges", edges)
cv2.imshow("lines", img)
cv2.waitKey()
cv2.destroyAllWindows()

圓檢測可以通過HoughCircles函數(shù)檢測。

import cv2
import numpy as np

planets = cv2.imread('planet_glow.jpg')
gray_img = cv2.cvtColor(planets, cv2.COLOR_BGR2GRAY)
img = cv2.medianBlur(gray_img, 5)
cimg = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

# 與直線檢測類似,需要圓心距的最小距離和圓的最小以及最大半徑
circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,120,param1=100,param2=30,minRadius=0,maxRadius=0)

circles = np.uint16(np.around(circles))

for i in circles[0,:]:
  # draw the outer circle
  cv2.circle(planets,(i[0],i[1]),i[2],(0,255,0),2)
  # draw the center of the circle
  cv2.circle(planets,(i[0],i[1]),2,(0,0,255),3)

cv2.imwrite("planets_circles.jpg", planets)
cv2.imshow("HoughCirlces", planets)
cv2.waitKey()
cv2.destroyAllWindows()

有一個問題,該方法檢測出來的第二行的第一個星球的圓檢測與書中不一樣。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

最新評論

龙江县| 吉林市| 靖西县| 清水河县| 营山县| 涞源县| 青龙| 青川县| 临澧县| 永济市| 富川| 黄梅县| 洪洞县| 葫芦岛市| 醴陵市| 永平县| 崇义县| 江口县| 元氏县| 孝义市| 梓潼县| 中超| 沙洋县| 南澳县| 汕头市| 盖州市| 乃东县| 庆安县| 中阳县| 凌海市| 嘉定区| 凤山市| 岱山县| 织金县| 边坝县| 麦盖提县| 辽宁省| 达孜县| 志丹县| 桃园市| 信丰县|