OpenCV3計算機視覺:Python實現 讀書筆記-第三章

第三章

計算機視覺三種常用色彩空間:

  • 灰度色彩空間
  • BGR
  • HSV(Hue:色調,Saturation:飽和度,Value:明亮程度)

使用函數cv2.imread(filepath,flags)讀入一圖片

  • filepath:要讀入圖片的完整路徑
  • flags:讀入圖片的標誌
    • cv2.IMREAD_COLOR:默認參數,讀入一副彩色圖片,忽略alpha通道
    • cv2.IMREAD_GRAYSCALE:讀入灰度圖片(0)
    • cv2.IMREAD_UNCHANGED:讀入完整圖片,包括alpha通道

高通濾波器

  • 根據像素與鄰近像素的亮度差值提升該像素的亮度
import cv2
import  numpy as np
from scipy import ndimage

kernal_3x3 = np.array( #卷積核(卷積矩陣,奇數行,列)
    [[-1,-1,-1],
     [-1,8,-1],
     [-1,-1,-1]
    ])

kernal_5x5 = np.array(
    [[-1,-1,-1,-1,-1],
     [-1,1,2,1,-1],
     [-1,2,4,2,-1],
     [-1,1,2,1,-1],
     [-1,-1,-1,-1,-1]
    ])

img = cv2.imread("3_1.jpg",0)

k3 = ndimage.convolve( img , kernal_3x3 ) #卷積
k5 = ndimage.convolve( img , kernal_5x5 )

#GaussianBlur:用高斯濾波器(GaussianFilter)對圖像進行平滑處理,將源圖像與指定的高斯內核進行卷積
blurred = cv2.GaussianBlur( img , (11,11) , 0 )
g_hpf = img - blurred

cv2.imshow("3x3",k3)
cv2.imshow("5x5",k5)
cv2.imshow("g_hpf",g_hpf)
cv2.waitKey()
cv2.destroyAllWindows()

低通濾波器

  • 在像素與周圍像素的亮度差值小於一個特定值時,平滑該像素的亮度
  • 主要用於去噪和模糊化(高斯模糊是最常用的模糊濾波器(平滑濾波器)之一,是一個削弱高頻信號強度的低通濾波器)

邊緣檢測

OpenCV提供的邊緣檢測濾波函數
  • Laplacian()
  • Sobel()
  • Scharr()

這些濾波函數將非邊緣區域轉爲黑色,邊緣區域轉爲白色或者其他飽和的顏色。但容易將噪聲識別爲邊緣,解決方法是在找到邊緣之前對圖像進行模糊處理

OpenCV提供的模糊濾波函數
  • blur():簡單的算術平均
  • medianBlur():去除數字化的視頻噪聲非常有效,特別是去除彩色圖像的噪聲
  • GaussianBlur()
import cv2
import  numpy
import utils

def strokeEdges( src , blurKsize = 7 , edgeKsize = 5 ):
    if blurKsize >= 3:
        blurredSrc = cv2.medianBlur(src,blurKsize)
        graySrc = cv2.cvtColor(blurredSrc,cv2.COLOR_BGR2GRAY)
    else :
        graySrc = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)
    cv2.Laplacian(graySrc,cv2.CV_8U,graySrc,ksize=edgeKsize)
    normalizedInverseAlpha = (1.0 / 255) * ( 255 - graySrc )
    channels = cv2.split(src)
    for channel in channels:
        channel[:] = channel * normalizedInverseAlpha
    cv2.merge(channels,dst)
用定製內核做卷積
  • 卷積矩陣:奇數行,奇數列的二維矩陣,中心元素對應於感興趣像素,其他元素對應於這個像素周圍鄰近像素,每個元素都有一個整數或浮點數值,就是應用在像素值上的權重
kernal_3x3 = np.array( #卷積核
    [[-1,-1,-1],
     [-1,8,-1],
     [-1,-1,-1]
    ])

此3x3卷積矩陣表示感興趣像素權重爲8,鄰近像素權重爲-1。感興趣像素的新像素是當前像素值*9,減去8個鄰近像素值。若感興趣像素與鄰近像素有一點差別,則差別增加,圖像銳化

  • OpenCV提供了通用的filter2D()函數,用戶指定任意核
    cv2.filter2D(src,-1,kernal,dst)
    第二個參數指明目標圖像每個通道的位深度(cv2.CV_8U表示每個通道爲8位),若爲負值,則表示目標圖像和源圖像位深度相同。
    • 對於彩色圖像,filter2D()對每個通道都用相同的核,若要對每個通道使用不同的核,必須用split()和merge()函數
Canny邊緣檢測

算法過程:

  • 高斯濾波器對圖像去噪
  • 計算梯度
  • 在邊緣使用非最大抑制(NMS)
  • 在檢測的邊緣上使用雙閾值去除假陽性
  • 分析所有邊緣及其之間的連接

在OpenCV中一行代碼就能實現:cv2.Canny(img,threshold1,threshold2)

  • threshold2用於檢測圖像中明顯的邊緣,但一般情況下檢測的效果不會那麼完美,邊緣檢測出來是斷斷續續的。所以這時候用較小的threshold1用於將這些間斷的邊緣連接起來。
  • 返回一個二值圖像,包含的是檢測出來的邊緣
import cv2
import numpy as np

img = cv2.imread("3_1.jpg",0)
cv2.imwrite("canny.jpg",cv2.Canny(img,200,300))
cv2.imshow("canny",cv2.imread("canny.jpg"))
cv2.waitKey()
cv2.destroyAllWindows()
輪廓檢測

與其相關的操作:檢測圖像視頻幀中物體輪廓,計算多邊形邊界,形狀逼近,計算感興趣區域

下例檢測出正方形輪廓,並用綠色畫出

import cv2
import numpy as np
#黑色空白圖像200*200
img = np.zeros( ( 200 , 200 ) , dtype = np.uint8 )
#中央放置一個白色方塊(np數組在切片上的賦值)
img[50:150, 50:150] = 255

"""
cv2.threshold(src, thresh, maxval, type) → retval, dst
src:表示的是圖片源
thresh:表示的是閾值(起始值)
maxval:表示的是最大值
type:表示的是這裏劃分的時候使用的是什麼類型的算法,常用值爲0(cv2.THRESH_BINARY)
返回 閾值 和 處理後圖像
"""
ret , thresh = cv2.threshold( img , 127 , 255 , 0 ) # 二值化(黑白)操作 , 0 :(cv2.THRESH_BINARY)

"""
findContours():
參數:輸入圖像,層次類型,輪廓逼近方法
"""
# 圖像的輪廓,層次
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()
邊界框,最小矩形區域,最小閉圓區域

加載圖像,在源圖像基礎上二值化操作
在灰度圖像上執行所有計算輪廓的操作,在源圖像上利用色彩信息畫這些輪廓

import cv2
import numpy as np

img = cv2.pyrDown(cv2.imread("3_3.png",cv2.IMREAD_UNCHANGED)) #圖像降採樣,對圖像縮小

ret , thresh = cv2.threshold(cv2.cvtColor(img.copy(),cv2.COLOR_BGR2GRAY),127,255,cv2.THRESH_BINARY)

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

for c in contours:
    # find bounding box coordinates
    x , y , w , h = cv2.boundingRect(c)
    cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)

    # find minimum area
    rect = cv2.minAreaRect(c)
    # calculate coordinates of the minimum area rectangle
    box = cv2.boxPoints(rect)
    # normalize coordinates to integers
    box = np.int0(box)
    # draw contours
    cv2.drawContours( img , [box] , 0 , (0,0,255) , 3 )
    # 第二個參數接收一個保存着輪廓的數組,[box]將box這組點放入數組中
	# 第三個參數是要繪製的輪廓數組的索引,-1表示繪製所有輪廓,否則只繪製輪廓數組裏的輪廓

    (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 , (0,255,0),2)

cv2.drawContours( img , contours , -1 , (255,0,0) , 1)
cv2.imshow("contours",img)
cv2.waitKey()
凸輪廓與Douglas-Peucker算法
  • 凸形狀內任意兩點的連線都在該形狀裏面

cv2.approxPolyDP 計算近似的多邊形框

  • 第一個參數爲輪廓
  • 第二個參數epsilon爲源輪廓與近似多邊形的最大差值(越小與輪廓越接近)
    • 計算輪廓周長 cv2.arclength(cnt,True) cnt爲一個輪廓
    • epsilon 可取輪廓的1%,如:
    epsilon = 0.01 * cv2.arcLength(cnt,True)
    approx = cv2.approxPolyDP(cnt,epsilon,True)
    
  • 第三個參數爲bool標記,表示多邊形是否閉合
直線檢測
import cv2
import numpy as np

img = cv2.imread('3_3.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,120) # Canny處理的單通道二值圖像

minLineLength = 20 # 最小直線長度
maxLineGap = 5     # 最大線段間隙

#需要處理的圖像,線段的幾何表示(1 , np.pi/180 , 閾值),返回numpy.ndarray(N維數組對象,用於存放同類型元素的多維數組)
lines = cv2.HoughLinesP(edges,1,np.pi/180,100,minLineLength,maxLineGap)
print(type(lines))
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()
圓檢測
import cv2
import numpy as np

planets = cv2.imread('3_3.png')
gray = cv2.cvtColor(planets,cv2.COLOR_BGR2GRAY)
img = cv2.medianBlur(gray,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,:]:
    cv2.circle(planets,(i[0],i[1]),i[2],(0,255,0),2)
    cv2.circle(planets,(i[0],i[1]),2,(0,255,0),3)
cv2.imshow("planets_circles",planets)

cv2.waitKey()
cv2.destroyAllWindows()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章