1. 程式人生 > >opencv-python函式(三)影象處理

opencv-python函式(三)影象處理

1.顏色空間轉換

常用到的就兩種:BGR↔Gray 和 BGR↔HSV

要用到的函式是:cv2.cvtColor(input_image ,flag),其中 flag就是轉換型別。

對於 BGR↔Gray 的轉換,我們要使用的 flag 就是 cv2.COLOR_BGR2GRAY。
同樣對於 BGR↔HSV 的轉換,我們用的 flag 就是 cv2.COLOR_BGR2HSV。

mask = cv2.inRange(hsv, lower_red, upper_red)函式設閾值,去除背景部分

引數有三個

第一個引數:hsv指的是原圖

第二個引數:lower_red指的是影象中低於這個lower_red的值,影象值變為0

第三個引數:upper_red指的是影象中高於這個upper_red的值,影象值變為0

而在lower_red~upper_red之間的值變成255

2.擴充套件縮放

 cv2.resize()可以實現這個功能。影象的尺寸可以自己手動設定,你也可以指定縮放因子。我們可以選擇使用不同的插值方法。

cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) -> dst

引數:

src是原圖

dsize是目標影象大小

fx - 水平軸上的比例因子

fy - 垂直軸上的比例因子

interpolation - 插值方法。共有5種:

1)INTER_NEAREST - 最近鄰插值法

2)INTER_LINEAR - 雙線性插值法(預設)

3)INTER_AREA - 基於區域性畫素的重取樣(resampling using pixel area relation)。對於影象抽取(image decimation)來說,這可能是一個更好的方法。但如果是放大影象時,它和最近鄰法的效果類似。

4)INTER_CUBIC - 基於4x4畫素鄰域的3次插值法

5)INTER_LANCZOS4 - 基於8x8畫素鄰域的Lanczos插值

如果想要收縮影象,那麼使用重取樣差值法效果最好;如果想要放大影象,那麼最好使用3次差值法

或者線性差值法

例:

# 下面的 None 本應該是輸出影象的尺寸,但是因為後邊我們設定了縮放因子
# 因此這裡為 None
res=cv2.resize(img,None,fx=2,fy=2,interpolation=cv2.INTER_CUBIC)
# 這裡呢,我們直接設定輸出影象的尺寸,所以不用設定縮放因子
height,width=img.shape[:2]
res=cv2.resize(img,(2*width,2*height),interpolation=cv2.INTER_CUBIC)

3.平移

平移就是將物件換一個位置。如果你要沿(x,y)方向移動,移動的距離是(t x ,t y ),你可以以下面的方式構建移動矩陣:

      M = \begin{bmatrix} 1 & 0 & t_x \\ 0 & 1 & t_y  \end{bmatrix}

可使用 Numpy 陣列構建這個矩陣(資料型別是 np.float32),然後把它傳給函式 cv2.warpAffine()。看看下面這個例子吧,它被移動了(100,50)個畫素。

import cv2
import numpy as np

img = cv2.imread('messi5.jpg',0)
rows,cols = img.shape

M = np.float32([[1,0,100],[0,1,50]])         #x移動100,y移動50
dst = cv2.warpAffine(img,M,(cols,rows))      #進行變換,img是原影象,M變換矩陣,(cols,rows)是輸出影象大小

cv2.imshow('img',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

4. 旋轉

構建旋轉矩陣,OpenCV 提供了一個函式:cv2.getRotationMatrix2D。這個函式需要三個引數,旋轉中心,旋轉角度,旋轉後圖像的縮放比例。

例:

import cv2
import numpy as np
img=cv2.imread('messi5.jpg',0)
rows,cols=img.shape
# 這裡的第一個引數為旋轉中心,第二個為旋轉角度,第三個為旋轉後的縮放因子
# 可以通過設定旋轉中心,縮放因子,以及視窗大小來防止旋轉後超出邊界的問題
M=cv2.getRotationMatrix2D((cols/2,rows/2),45,0.6)#旋轉中心為影象的中間位置,旋轉45度,縮放比例0.6,返回一個2x3的矩陣
# 第三個引數是輸出影象的尺寸中心
dst=cv2.warpAffine(img,M,(2*cols,2*rows))
cv2.imshow('img',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()   

5.影象閾值

簡單閾值
  這種方法非常簡單。但畫素值高於閾值時,我們給這個畫素賦予一個新值(可能是白色),否則我們給它賦予另外一種顏色(也許是黑色)。這個函式就是 cv2.threshhold()。這個函式的第一個引數就是原影象,原影象應該是灰度圖。第二個引數就是用來對畫素值進行分類的閾值。第三個引數就是當畫素值高於(有時是小於)閾值時應該被賦予的新的畫素值。OpenCV提供了多種不同的閾值方法,這是有第四個引數來決定的。這些方法包括:
  • cv2.THRESH_BINARY
  • cv2.THRESH_BINARY_INV
  • cv2.THRESH_TRUNC
  • cv2.THRESH_TOZERO
  • cv2.THRESH_TOZERO_INV

自適應閾值
  在前面的部分我們使用是全域性閾值,整幅影象採用同一個數作為閾值。當時這種方法並不適應與所有情況,尤其是當同一幅影象上的不同部分的具有不同亮度時。這種情況下我們需要採用自適應閾值。此時的閾值是根據影象上的每一個小區域計算與其對應的閾值。因此在同一幅影象上的不同區域採用的是不同的閾值,從而使我們能在亮度不同的情況下得到更好的結果。

函式為:cv2.adaptiveThreshold() 
該函式需要填6個引數:

  • 第一個原始影象
  • 第二個畫素值上限
  • 第三個自適應方法Adaptive Method: 
    — cv2.ADAPTIVE_THRESH_MEAN_C :領域內均值 
    —cv2.ADAPTIVE_THRESH_GAUSSIAN_C :領域內畫素點加權和,權重為一個高斯視窗
  • 第四個值的賦值方法:只有cv2.THRESH_BINARY(大於為畫素上限) 和cv2.THRESH_BINARY_INV(小於為畫素上限)
  • 第五個Block size:規定領域大小(一個正方形的領域)
  • 第六個常數C,閾值等於均值或者加權值減去這個常數(為0相當於閾值 就是求得領域內均值或者加權值) 
    這種方法理論上得到的效果更好,相當於在動態自適應的調整屬於自己畫素點的閾值,而不是整幅影象都用一個閾值.。

Otsu’ ’s 二值化
  在使用全域性閾值時,我們就是隨便給了一個數來做閾值,那我們怎麼知道我們選取的這個數的好壞呢?答案就是不停的嘗試。如果是一副雙峰影象(簡單來說雙峰影象是指影象直方圖中存在兩個峰)呢?我們豈不是應該在兩個峰之間的峰谷選一個值作為閾值?這就是 Otsu 二值化要做的。簡單來說就是對一副雙峰影象自動根據其直方圖計算出一個閾值。(對於非雙峰影象,這種方法得到的結果可能會不理想)。
這裡用到到的函式還是 cv2.threshold(),但是需要多傳入一個引數(flag):cv2.THRESH_OTSU。這時要把閾值設為 0。然後演算法會找到最優閾值,這個最優閾值就是返回值 retVal。如果不使用 Otsu 二值化,返回的retVal 值與設定的閾值相等。

例:

ret2,th2 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)