1. 程式人生 > 程式設計 >opencv python如何實現影象二值化

opencv python如何實現影象二值化

這篇文章主要介紹了opencv python如何實現影象二值化,文中通過示例程式碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

程式碼如下

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

# 二值影象就是將灰度圖轉化成黑白圖,沒有灰,在一個值之前為黑,之後為白
# 有全域性和區域性兩種
# 在使用全域性閾值時,我們就是隨便給了一個數來做閾值,那我們怎麼知道我們選取的這個數的好壞呢?答案就是不停的嘗試。
# 如果是一副雙峰影象(簡 單來說雙峰影象是指影象直方圖中存在兩個峰)呢?
# 我們豈不是應該在兩個峰之間的峰谷選一個值作為閾值?這就是 Otsu 二值化要做的。
# 簡單來說就是對 一副雙峰影象自動根據其直方圖計算出一個閾值。
# (對於非雙峰影象,這種方法 得到的結果可能會不理想)。


def threshold_demo(image):
  gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)

  # 這個函式的第一個引數就是原影象,原影象應該是灰度圖。
  # 第二個引數就是用來對畫素值進行分類的閾值。
  # 第三個引數就是當畫素值高於(有時是小於)閾值時應該被賦予的新的畫素值
  # 第四個引數來決定閾值方法,見threshold_simple()
  # ret,binary = cv.threshold(gray,127,255,cv.THRESH_BINARY)
  ret,cv.THRESH_BINARY | cv.THRESH_OTSU)
  print("threshold value: %s"%ret)
  cv.imshow("threshold_demo",binary)


def threshold_simple(image):
  img = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
  ret,thresh1 = cv.threshold(img,thresh2 = cv.threshold(img,cv.THRESH_BINARY_INV)
  ret,thresh3 = cv.threshold(img,cv.THRESH_TRUNC)
  ret,thresh4 = cv.threshold(img,cv.THRESH_TOZERO)
  ret,thresh5 = cv.threshold(img,cv.THRESH_TOZERO_INV)
  titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
  images = [img,thresh1,thresh2,thresh3,thresh4,thresh5]

  for i in range(6):
    plt.subplot(2,3,i + 1),plt.imshow(images[i],'gray') # 將影象按2x3鋪開
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])

  plt.show()


# 在前面的部分我們使用是全域性閾值,整幅影象採用同一個數作為閾值。
# 當時這種方法並不適應與所有情況,尤其是當同一幅影象上的不同部分的具有不同亮度時。
# 這種情況下我們需要採用自適應閾值。此時的閾值是根據影象上的 每一個小區域計算與其對應的閾值。
# 因此在同一幅影象上的不同區域採用的是不同的閾值,從而使我們能在亮度不同的情況下得到更好的結果。
# 這種方法需要我們指定三個引數,返回值只有一個
# _MEAN_C:閾值取自相鄰區域的平均值,_GAUSSIAN_C:閾值取值相鄰區域 的加權和,權重為一個高斯視窗。
# Block Size - 鄰域大小(用來計算閾值的區域大小)。
# C - 這就是是一個常數,閾值就等於的平均值或者加權平均值減去這個常數。

def threshold_adaptive(image):
  img = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
  # 中值濾波
  img = cv.medianBlur(img,5)

  ret,th1 = cv.threshold(img,cv.THRESH_BINARY)
  # 11 為 Block size,2 為 C 值
  th2 = cv.adaptiveThreshold(img,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,11,2)
  th3 = cv.adaptiveThreshold(img,cv.ADAPTIVE_THRESH_GAUSSIAN_C,2)

  titles = ['Original Image','Global Threshold (v = 127)','Adaptive Mean Threshold','Adaptive Gaussian Threshold']
  images = [img,th1,th2,th3]

  for i in range(4):
    plt.subplot(2,2,'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])

  plt.show()


def threshold_custom(image):
  gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
  h,w = gray.shape[:2]
  m = np.reshape(gray,[1,w*h])
  mean = m.sum() / (w*h) # 求出整個灰度影象的平均值
  print("mean:",mean)
  ret,mean,cv.THRESH_BINARY)
  cv.imshow("threshold_custom",binary)


# 將大圖片拆分成小圖片後再用自適應區域性閾值比較好
def big_image_demo(image):
  print(image.shape)
  cw = 200
  ch = 200
  h,w = image.shape[:2]
  gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
  cv.imshow("big_image_demo_gray",gray)

  # 將一張圖片每隔ch * cw分成一份
  for row in range(0,h,ch):
    for col in range(0,w,cw):
      roi = gray[row:row+ch,col:col+cw]
      dst = cv.adaptiveThreshold(roi,2)
      gray[row:row + ch,col:col + cw] = dst
      print(np.std(dst),np.mean(dst))

  cv.imwrite("../images/result_big_image.png",gray)


def main():
  img = cv.imread("../images/02.jpg")
  # threshold_demo(img)
  # threshold_simple(img)
  # threshold_adaptive(img)
  # threshold_custom(img)
  src = cv.imread("../images/big_image.jpg")
  big_image_demo(src)
  cv.waitKey(0) # 等有鍵輸入或者1000ms後自動將視窗消除,0表示只用鍵輸入結束視窗
  cv.destroyAllWindows() # 關閉所有視窗


if __name__ == '__main__':
  main()

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。