1. 程式人生 > >OpenCV 中影象的算術運算、平滑處理、閾值化及影象金字塔

OpenCV 中影象的算術運算、平滑處理、閾值化及影象金字塔

一、影象的算術運算

  • 影象加法:cv2.add()
# OpenCV 的加法是一種飽和操作,而 Numpy 的加法是一種模操作。
x = np.uint8([250])
y = np.uint8([10])

print cv2.add(x,y)      # 250+10 = 260 => 255
[[255]]
print x+y               # 250+10 = 260 % 256 = 4
[4]
  • 影象混合(dst=αimg1+βimg2+γ):cv2.addWeighted()
# 其實也是加法,但兩幅影象的權重不同,這就會給人一種混合或者透明的感覺
img1 = cv2.imread('ml.png'
) img2 = cv2.imread('opencv_logo.jpg') dst = cv2.addWeighted(img1, 0.8, img2, 1, 0) cv2.imshow('dst',dst) cv2.waitKey(0) cv2.destroyAllWindows()
  • 影象按位運算:cv2.bitwise_and()
def roi_mask(img, vertices):
    mask = np.zeros_like(img)

    # defining a 3 channel or 1 channel color to fill the mask with depending on the input image
if len(img.shape) > 2: channel_count = img.shape[2] # i.e. 3 or 4 depending on your image mask_color = (255,) * channel_count else: mask_color = 255 # 顯示邊緣檢測後的影象 plt.figure() plt.imshow(img, cmap='gray') plt.show() # 基於影象輪廓填充連通區內部空間 cv2.fillPoly(mask, vertices, mask_color) plt.figure() plt.imshow(mask, cmap='gray'
) plt.show() # 取出包含車道線的影象 masked_img = cv2.bitwise_and(img, mask) plt.figure() plt.imshow(masked_img, cmap='gray') plt.show() return masked_img # 影象左下方座標、滅點兩旁座標、右下方座標 roi_vtx = np.array([[(0, img.shape[0]), (460, 325), (520, 325), (img.shape[1], img.shape[0])]]) roi_edges = roi_mask(edges, roi_vtx)

結果如下所示:依次為Canny邊緣檢測後結果、fillPoly後的結果、masked_img
這裡寫圖片描述

二、影象平滑處理

Image blurring (Image Smoothing) is achieved by convolving the image with a low-pass filter kernel.
It is useful for removing noise. It actually removes high frequency content (e.g: noise, edges) from the image resulting in edges being blurred when this is filter is applied.

  • 均值濾波(Average Filtering)
    for each pixel, a 5x5 window is centered on this pixel, all pixels falling within this window are summed up, and the result is then divided by 25. This equates to computing the average of the pixel values inside that window
    K=1251111111111111111111111111
img = cv2.imread('D:/opencv_logo.jpg')
kernel = np.ones((5,5),np.float32)/25

# ddepth=-1, the output image will have the same depth as the source.
blur = cv2.filter2D(img,-1,kernel)
# or 使用下式
blur = cv2.blur(img,(5,5))  # 需傳入卷積核的長和寬
  • 高斯濾波(Gaussian Filtering)
img = cv2.imread('opencv_logo.png') 
# 與均值濾波的區別:把卷積核換成高斯核,即,原來每個方框的值是相等的,現在裡面的值是
# 符合高斯分佈的,方框中心的值最大,其餘方框根據距離中心元素的距離遞減,構成一個高斯
# 小山包。原來的求平均數現在變成求加權平均數,權就是方框裡的值

# 需傳入卷積核的長和寬(正奇數)、X和Y方向上的標準差(若給0,函式會自動根據核的大小計算)
blur = cv2.GaussianBlur(img,(5,5),0)  
  • 中值濾波(Median Filtering)
img = cv2.imread('opencv_logo.png') 

# 用與卷積框對應畫素的中值來替代中心畫素的值,這個濾波器經常用來去除椒鹽噪聲
median = cv2.medianBlur(img, 5)
  • 雙邊濾波(Bilateral Filtering)
    • 同時使用空間高斯權重灰度值相似性高斯權重,空間高斯函式確保只有鄰近區域的畫素對中心點有影響,灰度值相似性高斯函式確保只有與中心畫素灰度值相近的才會被用來做模糊運算。
    • 能在保持邊界清晰的情況下有效的去除噪音。

三、影象閾值化處理

  • 畫素值高於閾值時,我們給這個畫素賦予一個新值(eg: 白色),否則我們給它賦予另外一種顏色(eg: 黑色)
img=cv2.imread('gradient.png',0)

# 第二個引數就是用來對畫素值進行分類的閾值、第三個引數就是當畫素值高於閾值時應該被賦予的新的畫素值
# 二值化處理,函式返回值有兩個,第二個為閾值化後的結果影象,第一個暫時用不到
ret, thresh1=cv2.threshold(img,127,255,cv2.THRESH_BINARY) 
ret, thresh2=cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)

四、影象金字塔(Image Pyramids)

1. 定義

  • 影象金字塔就是同一影象的不同解析度的子圖集合{ML,ML1,...,M0},x軸和y軸依次降低一倍解析度。如果我們把最大的影象放在底部,最小的放在頂部,看起來像一座金字塔,故而得名影象金字塔。
  • 儲存所有的影象矩陣所需畫素數目:N2(1+14+116+...)1.33N2

2. OpenCV 中的兩類影象金字塔

  • 高斯金字塔
    • 首先,對底部影象的每個畫素求高斯加權平均(卷積)形成頂部影象
    • 然後,將頂部影象中的偶數行和列去除(下采樣)
    • 最後,一個MN的影象就變成了一個M/2N/2的影象,所以頂部影象的面積就變為原來底部影象面積的四分之一了。
    • 注意:PryUp和PryDown不是互逆的,即PryUp不是降取樣的逆操作。這種情況下,影象首先在每個維度上擴大為原來的兩倍,新增的行(偶數行)以0填充。然後給指定的濾波器進行卷積(實際上是一個在每個維度都擴大為原來兩倍的過濾器)去估計丟失畫素的近似值。
    • 程式碼及結果展示
src = cv2.imread('D:/messi5.jpg')
cv2.imshow('src', src)

# 每呼叫一次解析度降低為原來的1/4
dst = cv2.pyrDown(src)
cv2.imshow('dst', dst)

# 一旦使用cv2.pyrDown(),影象的解析度就會降低,資訊就會被丟失,所以上取樣後的影象會模糊許多
src1 = cv2.pyrUp(dst)
cv2.imshow('src1', src1)

cv2.waitKey()

這裡寫圖片描述

  • 拉普拉斯金字塔

    • 為了恢復原來更高的解析度的影象,我們要獲得由降取樣操作丟失的資訊,這就要由拉普拉斯金字塔來實現了。
      這裡寫圖片描述
  • 使用金字塔進行影象融合:可以實現兩幅圖的無縫連線

五、參考資料