1. 程式人生 > >OpenCV3計算機視覺+python(三)

OpenCV3計算機視覺+python(三)

換來 key 處理圖像 opencv 使用方法 rap 能夠 先來 ont

使用OpenCV3處理圖像

下面要介紹的內容都與圖像處理有關,這時需要修改圖像,比如要使用具有藝術性的濾鏡、外插(extrapolate)某些部分、分割、粘貼或其他需要的操作。

不同色彩空間的轉換

OpenCV中有數百種關於在不同色彩空間之間轉換的方法。當前,在計算機視覺中有三種常用的色彩空間:灰度、BGR以及HSV(Hue,Saturation,Value)

1.灰度色彩空間是通過去除彩色信息來將其轉換成灰階,灰度色彩空間對中間處理特別有效,比如人臉檢測。

2.BGR,即藍-綠-紅色彩空間,每一個像素點都由一個三元數組來表示,分別代表藍、綠、紅三種顏色。網頁開發者可能熟悉另一個與之相似的顏色空間:RGB,它們只是在顏色的順序上不同。

3.HSV,H(Hue)是色調,S(Saturation)是飽和度,V(Value)表示黑暗的程度(或光譜另一端的明亮程度)

傅裏葉變換

在OpenCV中,對圖像和視頻的大多數處理都或多或少會涉及傅裏葉變換的概念。傅裏葉觀察到所有的波形都可以由一系列簡單且頻率不同的正弦曲線疊加得到。

也就是說,人們所看到的波形都是由其他波形疊加得到的。這個概念也對操作圖像非常有幫助,因為這樣我們可以區分圖像裏哪些區域的信號(比如圖像像素)變化特別強,哪些區域的信號變化不那麽強,從而可以任意地標記噪聲區域、感興趣區域、前景和背景等。原始圖像由許多頻率組成,人們能夠分離這些頻率來理解圖像和提取感興趣地數據

註意:在OpenCV環境中,有許多實現了的算法讓我們能夠處理圖像、理解圖像中所包含的意義。這些算法在Numpy中也有實現,而且更容易使用。Numpy中有快速傅裏葉變換(FFT)包,它包含了fft2()函數,該函數可以計算一幅圖像的離散傅裏葉變換(DFT)

下面通過傅裏葉變換來介紹圖像的幅度譜。圖像的幅度譜是另一種圖像,幅度譜圖像呈現了原始圖像在變化方面的一種表示:把一幅圖像中最明亮的像素放在圖像中央,然後逐漸變暗,在邊緣上的像素最暗。這樣可以發現圖像中有多少亮的像素和暗的像素,以及它們分布的百分比。

傅裏葉變換的概念是許多常見的圖像處理操作的基礎,比如邊緣檢測或線段和形狀檢測。

1.高通濾波器

高通濾波器(HPF)是檢測圖像的某個區域,然後根據像素與周圍像素的亮度差值來提升(boost)該像素的亮度的濾波器。

核是指一組權重的集合,他會應用在源圖像的一個區域,並由此生成目標圖像的一個像素。比如,大小為7的核意味著每49(7×7)個源圖像的像素會產生目標圖像的一個像素。可把核看作一塊覆蓋在源圖像上可移動的毛玻璃片,玻璃片覆蓋區域的光線會按某種方式進行擴散混合後透過去。

在計算完中央像素與周圍近鄰像素的亮度差值之和以後,如果亮度變化很大,中央像素的亮度會增加(反之則不會)。換句話說,如果一個像素比它周圍的像素更突出,就會提升它的亮度

這在邊緣檢測上尤其有效,它會采用一種稱為高頻提升濾波器的高通濾波器。

高通和低通濾波器都有一個稱為半徑的屬性,它決定了多大面積的鄰近像素參與濾波運算

2.低通濾波器

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

邊緣檢測

邊緣在人類視覺和計算機視覺中均起著重要的作用。人類能夠僅憑一張背景剪影或一個草圖就識別出物體的類型和姿態。

OpenCV提供了許多邊緣檢測濾波器,包括Laplacian()、Sobel()以及Scharr()。這些濾波函數都會將非邊緣區域轉為黑色,將邊緣區域轉為白色或其他飽和的顏色。但是,這些函數都很容易將噪聲錯誤地識別為邊緣。緩解這個問題的方法是在找到邊緣之前對圖像進行模糊處理。OpenCV也提供了許多模糊濾波函數,包括blur()(簡單的算術平均)、medianBlur()以及GaussianBlur()。邊緣檢測濾波函數和模糊濾波函數的參數有很多,但總會有一個ksize參數,它是一個奇數,表示濾波核的寬和高。

這裏使用medianBlur()作為模糊函數,它對去除數字化的視頻噪聲非常有效,特別是去除彩色圖像的噪聲;使用Laplacian()作為邊緣檢測函數,他會產生明顯的邊緣線條,灰度圖像更是如此。在使用medianBlur()函數之後,將要使用Laplacian()函數之前,需要將圖像從BGR色彩空間轉為灰度色彩空間。

用定制內核做卷積

OpenCV預定義的許多濾波器(濾波函數)都會使用核。其實核是一組權重,它決定如何通過鄰近像素點來計算新的像素點。核也稱為卷積矩陣,它對一個區域的像素做調和(mix up)或卷積運算。通常基於核的濾波器(濾波函數)也被稱為卷積濾波器(濾波函數)。

OpenCV提供了一個非常通用的filter2D()函數,它運用由用戶指定的任意核或卷積矩陣。為了理解這個函數的使用方法,首先來了解卷積矩陣的格式。卷積矩陣是一個二維數組,有奇數行、奇數列,中心的元素對應於感興趣的像素,其他的元素對應於這個像素周圍的鄰近像素,每個元素都有一個整數或浮點數的值,這些值就是應用在像素值上的權重。

cv2.filter2D(src,-1,kernel,dst)

第二個參數指定了目標圖像每個通道的位深度(比如,位深度cv2.CV_8U表示每個通道為8位),如果為負值,則表示目標圖像和源圖像有同樣的位深度。

註意:對彩色圖像來說,filter2D()會對每個通道都用同樣的核。如果要對每個通道使用不同的核,就必須用split()函數和merge()函數。

銳化、邊緣檢測以及模糊等濾波器都使用了高度對稱的核。但是有時不對稱的核也會得到一些有趣的效果。

Canny邊緣檢測

OpenCV還提供了一個非常方便的Canny函數,該算法非常流行,不僅是因為它的效果,還因為在OpenCV程序中實現時非常簡單。

import cv2
import numpy as np

img=cv2.imread("1.jpg",0)
cv2.imwrite("canny.jpg",cv2.Canny(img,200,300))
cv2.imshow("canny",cv2.imread("canny.jpg"))
cv2.waitKey()
cv2.destroyAllWindows()

Canny邊緣檢測算法非常復雜,但也很有趣:它有5個步驟,即使用高斯濾波器對圖像進行去噪、計算梯度、在邊緣上使用非最大抑制(NMS)、在檢測到的邊緣上使用雙閾值去除假陽性,最後還會分析所有的邊緣及其之間的連接,以保留真正的邊緣並消除不明顯的邊緣。

輪廓檢測

在計算機視覺中,輪廓檢測是另一個比較重要的任務,不單是用來檢測圖像或者視頻幀中物體的輪廓,而且還有其他操作與輪廓檢測有關。這些操作有:計算多邊形邊界、形狀逼近核計算感興趣區域。這是與圖像數據交互時的簡單操作,因為Numpy中的矩形區域可以使用數組切片(slice)來定義。在介紹物體檢測(包括人臉)和物體跟蹤的概念時會大量使用這種技術。

邊界框、最小矩形區域和最小閉圓的輪廓

找到一個正方形輪廓很簡單,要找到不規則、歪斜的以及旋轉的形狀可用OpenCV的cv2.findContours函數,它能得到最好的結果。

現實的應用會對目標的邊界框、最小矩形面積、最小閉圓特別感興趣。將cv2.findContours函數與少量的OpenCV的功能相結合就能非常容易地實現這些功能:

import cv2
import numpy as np
img=cv2.pyrDown(cv2.imread("1.jpg",cv2.IMREAD_UNCHANGED))
ret,thresh=cv2.threshold(cv2.cvtColor(img.copy(),cv2.COLOR_BGR2GRAY),127,255,cv2.THRESH_BINARY)
img,contours,hier=cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

for c in contours:
    x,y,w,h=cv2.boundingRect(c)#計算出一個簡單地邊界框
    #這個操作很簡單,它將輪廓信息轉換成(x,y)坐標,並加上矩形地高度和寬度。
    cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)#畫出該矩形

    rect=cv2.minAreaRect(c)#計算出包圍目標地最小矩形區域
    box=cv2.boxPoints(rect)
    box=np.int0(box)
    #這裏用到一種非常有趣的機制:Opencv沒有函數能直接從輪廓信息中計算出最小矩形頂點的坐標。所以需要計算出最小矩形區域,然後計算這個矩形的頂點。註意計算出來的頂點坐標是浮點型,但是所得像素的坐標值是整數(不能獲取像素的一部分),所以需要做一個轉換。然後畫出這個矩形,可由cv2.drawContours函數來實現
    cv2.drawContours(img,[box],0,(0,0,255),3)

    (x,y),radius=cv2.minEnclosingCircle(c)#返回一個二元組,第一個元素為圓心的坐標組成的元祖,第二個元素為圓的半徑值

    center=(int(x),int(y))

    radius=int(radius)

    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()
cv2.destroyAllWindows()

OpenCV3計算機視覺+python(三)