1. 程式人生 > >opencv(8)-Canny邊緣檢測+直線檢測+圓檢測+輪廓發現

opencv(8)-Canny邊緣檢測+直線檢測+圓檢測+輪廓發現

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() 

結果: