opencv(8)-Canny邊緣檢測+直線檢測+圓檢測+輪廓發現
阿新 • • 發佈:2019-01-02
Canny邊緣檢測
程式碼:
# -*- coding=GBK -*- import cv2 import numpy as np # 1.高斯模糊- GaussianBlur # 2.灰度轉換一cvtColor # 3.計算梯度- Sobel/ Scharr # 4.非最大訊號抑制 # 5.高低閾值輸出二值影象 # Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]]) -> edges # 高低閾值比常為 3:1 或 2:1 def edge_demo(image): gaussian_blur = cv2.GaussianBlur(image,(3,3),0) # 該演算法對噪聲敏感,必須降噪 gray = cv2.cvtColor(gaussian_blur,cv2.COLOR_BGR2GRAY) # x_gradient x_gradient = cv2.Sobel(gray,cv2.CV_16SC1,1,0) # CV_16SC1是必須的 y_gradient = cv2.Sobel(gray,cv2.CV_16SC1,0,1) # CV_16SC1是必須的 # edge edge_output = cv2.Canny(x_gradient,y_gradient,50,150) # 高低閾值三倍 cv2.imshow('Canny Edge',edge_output) # 顯示彩色 dst = cv2.bitwise_and(image,image,mask=edge_output) cv2.imshow('Color Edge',dst) img = cv2.imread('dog.jpg',1) cv2.imshow('src',img) edge_demo(img) cv2.waitKey(0) cv2.destroyAllWindows()
結果:
直線檢測
程式碼:
# -*- coding=GBK -*- import cv2 import numpy as np # 前提是已經進行了邊緣提取 # HoughLines(image, rho, theta, threshold[, lines[, srn[, stn[, min_theta[, max_theta]]]]]) -> lines(rho,theta) # 1 data 2 半徑/步長 3 角度 4 低值(邊緣提取時的低值),高值自己會搞定 def line_dection(image): gray = cv2.cvtColor(image, cv.COLOR_BGR2GRAY) edges = cv2.Canny(gray, 50, 150, apertureSize=3) lines = cv2.HoughLines(edges, 1, np.pi/180, 200) # line是多維陣列,line【0】返回的是(r,theta) for line in lines: rho, theta = line[0] a = np.cos(theta) b = np.sin(theta) x0 = a * rho y0 = b * rho # (x0,y0) x1 = int(x0+1000*(-b)) y1 = int(y0+1000*(a)) x2 = int(x0-1000*(-b)) y2 = int(y0-1000*(a)) cv2.line(image, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.imshow("直線", image) # HoughLinesP(image, rho, theta, threshold[, lines[, minLineLength[, maxLineGap]]]) -> lines 直接返回四個點 def line_dection(img): gray = cv2.cvtColor(image, cv.COLOR_BGR2GRAY) edges = cv2.Canny(gray, 50, 150, apertureSize=3) lines = cv2.HoughLinesP(edges, 1, np.pi/180, 100, minLineLength=50,maxLineGap=10) # line是多維陣列,line【0】返回的是四個點 for line in lines: x1,y1,x2,y2 = line[0] cv2.line(image,(x1,y1),(x2,y2),(0,0,255),2) cv2.imshow('直線',image) img = cv2.imread('dog.jpg',1) cv2.imshow('src',img) line_dection(img) cv2.waitKey(0) cv2.destroyAllWindows()
結果:
圓檢測
程式碼:
# -*- coding=GBK -*- import cv2 as cv import numpy as np #圓檢測 # HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) -> circles # 1 data 2 method:cv2.HOUGH_GRADIENT,基於梯度來做 3 步長 4 最小距離(比如同心圓,但是半徑相差不大,設定半徑之間的最小距離可以防止多個小圓出現) # 6 param1 邊緣提取低值 def circles_image(image): # 由於霍夫圓檢測對噪聲敏感,這裡用 均值偏移濾波 移除噪聲 # pyrMeanShiftFiltering(src, sp, sr[, dst[, maxLevel[, termcrit]]]) -> dst # 1 data 2 空間窗半徑 3 色彩窗半徑 dst = cv.pyrMeanShiftFiltering(image, 10, 100) cimage = cv.cvtColor(dst, cv.COLOR_BGR2GRAY) circles = cv.HoughCircles(cimage, cv.HOUGH_GRADIENT, 1, 20, param1=50, param2=30, minRadius=0, maxRadius=0) circles = np.uint16(np.around(circles)) # 把型別換成整數 for i in circles[0, :]: # return (a,b,r) cv.circle(image, (i[0], i[1]), i[2], (0, 0, 255), 2) cv.circle(image, (i[0], i[1]), 2, (255, 0, 255), 2) # 畫出小圓心 cv.imshow("圓形", image) src = cv.imread("C://04.jpg") cv.imshow("原來", src) circles_image(src) cv.waitKey(0) cv.destroyAllWindows()
結果:
輪廓發現
程式碼:
# -*- coding=GBK -*-
import cv2 as cv
import numpy as np
#輪廓發現
def contous_image(image):
# 影象二值化
dst = cv.GaussianBlur(image, (3, 3), 0)
gray = cv.cvtColor(dst, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
cv.imshow("二值化", binary)
# findContours(image, mode, method[, contours[, hierarchy[, offset]]]) -> image, contours, hierarchy
# 1 二值影象 2 輪廓方法,cv2.RETR_TREE/cv2.RETR_LIST,cv2.RETR_EXTERNAL:只找外部的輪廓 3 method
# return 1 image 2 輪廓資訊 3 層次資訊
cloneImage, contous, heriachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
for i,contou in enumerate(contous):
# drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]]) -> image
cv.drawContours(image, contous, i, (0, 0, 255), 1)
cv.imshow("輪廓", image)
for i,contou in enumerate(contous):
cv.drawContours(image, contous, i, (0, 0, 255), -1)# -1是填充輪廓
cv.imshow("輪廓覆蓋", image)
src = cv.imread("D://1.jpg")
cv.imshow("原來", src)
contous_image(src)
cv.waitKey(0)
cv.destroyAllWindows()
結果: