主頁 >  其他 > 2021-09-23 opencv學習筆記(影像變換,二值化,濾波器介紹及python實作)

2021-09-23 opencv學習筆記(影像變換,二值化,濾波器介紹及python實作)

2021-09-25 15:24:23 其他

在這里插入圖片描述

opencv學習筆記

  • 顏色空間
    • 改變顏色空間(cv2.cvtColor())
    • 目標追蹤
    • 如何查找某個顏色的HSV值
  • 圖形變換
    • 縮放(cv2.resize())
    • 平移
    • 旋轉
    • 仿射變換
    • 透視變換
  • 二值化
    • 簡單閾值法
    • 自適應閾值
    • Otsu二值化(俗稱大津法)
    • Otsu 二值化原理
  • 濾波
    • 二維卷積(影像濾波)
    • 影像模糊(影像平滑)
      • 均值濾波
      • 高斯濾波
      • 中值濾波
      • 雙邊濾波

顏色空間

改變顏色空間(cv2.cvtColor())

在 OpenCV 中有超過 150 種顏色空間轉換的方法,但我們僅需要研究兩個最常使用的方法,他們是 BGR 到 GRAY,BGR 到 HSV,

我們使用 cv.cvtColor(input_image, flag)函式進行顏色轉換,其中 flag 決定了轉換的型別,

對于 BGR 到 Gray 轉換我們令 flag 為 cv2.COLOR_BGR2GRAY, 同樣,對于 BGR 到 HSV, 我們令 flag 為 cv2.COLOR_BGR2HSV

代碼:

import cv2

BGR = cv2.imread("C:/Users/Zhang-Lei/Desktop/snack.png")
GRAY = cv2.cvtColor(BGR, cv2.COLOR_BGR2GRAY)
HSV = cv2.cvtColor(BGR, cv2.COLOR_BGR2HSV)

cv2.imshow('BGR', BGR)
cv2.imshow('GRAY', GRAY)
cv2.imshow('HSV', HSV)
cv2.resizeWindow('BGR', 500, 800)
cv2.resizeWindow('GRAY', 500, 800)
cv2.resizeWindow('HSV', 500, 800)
cv2.waitKey()
cv2.destroyAllWindows()

結果:
在這里插入圖片描述
如想得到其他 flag 值,我們只需要輸入代碼查看:

代碼:

flags = [i for i in dir(cv2) if i.startswith('COLOR_')]
print(flags)

種類過多,這里就不展示結果了,

注意: 對于 HSV, 色調(Hue)范圍為 [0,179], 飽和度(Saturation)范圍為 [0,255] ,明亮度(Value)為 [0,255]. 不同的軟體使用不同的比例. 所以如果你想用 OpenCV 的值與別的軟體的值作對比,你需要歸一化這些范圍,

目標追蹤

現在我們知道了如何將 BGR 圖片轉化為 HSV 圖片,我們可以使用它去提取彩色物件,HSV 比 BGR 在顏色空間上更容易表示顏色,在我們的應用中,我們會嘗試提取一個藍色的彩色物件,方法為:

  1. 提取每一視頻幀,
  2. 將 BGR 轉化為 HSV 顏色空間,
  3. 我們用藍色像素的范圍對該 HSV 圖片做閾值,
  4. 現在提取出了藍色物件,我們可以隨意處理圖片了 ,

代碼:

import cv2
import numpy as np

cap = cv2.VideoCapture(0)  # 讀取攝像頭影像
while 1:
    _, frame = cap.read()
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)  # 轉為HSV圖
    lower_blue = np.array([110, 50, 50])  # 限定藍色范圍下限
    upper_blue = np.array([130, 255, 255])  # 限定藍色范圍上限
    mask = cv2.inRange(hsv, lower_blue, upper_blue)  # 限定HSV影像范圍
    res = cv2.bitwise_and(frame, frame, mask=mask)  # 按位與
    cv2.imshow('frame', frame)
    cv2.imshow('mask', mask)
    cv2.imshow('res', res)
    k = cv2.waitKey(5) & 0xFF  # 檢測是否按下Esc 參考&0xff,
    # 正是為了只取按鍵對應的ASCII值后8位來排除不同按鍵的干擾進行判斷按鍵是什么,
    if k == 27:
        break
cv2.destroyAllWindows()

結果:
在這里插入圖片描述

可以看到這本書的藍色物件被我們提取了出來,

如何查找某個顏色的HSV值

你可以使用相同的函式:cv2.cvtColor(), 不需要輸入圖片,你只需要輸入你需要的 BGR 值即可. 例如, 為了找到綠色的 HSV 值,

代碼:

green = np.uint8([[[0, 255, 0]]])
hsv_green = cv2.cvtColor(green, cv2.COLOR_BGR2HSV)
print(hsv_green)

結果:
在這里插入圖片描述

圖形變換

縮放(cv2.resize())

縮放是調整圖片的大小, OpenCV 使用 cv2.resize() 函式進行調整,可以手動指定影像的大小,也可以指定比例因子,可以使用不同的插值方法,對于下采樣(影像上縮小),最合適的插值方法是 cv2.INTER_AREA 對于上采樣(放大),最好的方法是 cv2.INTER_CUBIC (速度較慢)和 cv2.INTER_LINEAR (速度較快),默認情況下,所使用的插值方法都是 cv2.INTER_AREA ,你可以使用如下方法調整輸入圖片大小:

代碼:

import cv2

img = cv2.imread("C:/Users/Zhang-Lei/Desktop/snack.png")
res1 = cv2.resize(img, None, fx=1/2, fy=1/2, interpolation=cv2.INTER_CUBIC) # fx和fy分別對應橫縱軸影像放大倍數

height, width = img.shape[:2]
res2 = cv2.resize(img, (width//2, height//2), interpolation=cv2.INTER_CUBIC)  # 第二種方法

cv2.imshow('img', img)
cv2.imshow('res1', res1)
cv2.imshow('res2', res2)
cv2.waitKey()
cv2.destroyAllWindows()

結果:
在這里插入圖片描述

可以看出兩種方法都將圖片的大小縮小為原來大小的一半,

平移

平移變換是物體位置的移動,如果知道 (x,y) 方向的偏移量,假設為 (t_x,t_y),則可以創建如下轉換矩陣 M:
在這里插入圖片描述
您可以將變換矩陣存為 np.float32 型別的 numpy 陣列,并將其作為 cv.warpAffine 的第二個引數,請參見以下轉換(100,50)的示例:

代碼:

import cv2
import numpy as np

img = cv2.imread('C:/Users/Zhang-Lei/Desktop/snack_gray.png', cv2.IMREAD_UNCHANGED)
rows, cols = img.shape
M = np.float32([[1, 0, 100], [0, 1, 50]])
res = cv2.warpAffine(img, M, (cols, rows))
cv2.imshow('img', img)
cv2.imshow('res', res)
cv2.waitKey()
cv2.destroyAllWindows()

結果:
在這里插入圖片描述
這里可以看到得到的影像相比于原影像是向右下方平移了的,

注意:cv2.warpAffine 函式的第三個引數是輸出影像的大小,其形式應為(寬度、高度),記住寬度=列數,高度=行數,

旋轉

以θ角度旋轉圖片的轉換矩陣形式為:
在這里插入圖片描述
但 Opencv 提供了可變旋轉中心的比例變換,所以你可以在任意位置旋轉圖片,修改后的轉換矩陣為:
在這里插入圖片描述
其中:
在這里插入圖片描述
為了找到這個轉換矩陣,opencv 提供了一個函式
cv2.getRotationMatrix2D ,
請查看下面的示例,它將影像相對于中心旋轉 90 度,而不進行任何縮放,

代碼:

import cv2

img = cv2.imread('C:/Users/Zhang-Lei/Desktop/snack_gray.png', cv2.IMREAD_UNCHANGED)
rows, cols = img.shape
M = cv2.getRotationMatrix2D(((cols-1)/2.0, (rows-1)/2.0), 90, 1)
res = cv2.warpAffine(img, M, (cols, rows))
cv2.imshow('img', img)
cv2.imshow('res', res)
cv2.waitKey()
cv2.destroyAllWindows()

結果:
在這里插入圖片描述
可見圖片已經發生了逆時針90°的旋轉,

仿射變換

在仿射變換中,原始影像中的所有平行線在輸出影像中仍然是平行的,為了找到變換矩陣,我們需要從輸入影像中取三個點及其在輸出影像中的對應位置,然后 cv2.getPerspectiveTransform 將創建一個 2x3 矩陣,該矩陣將傳遞給cv2.warpAffine

代碼:

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

img = cv2.imread('C:/Users/Zhang-Lei/Desktop/drawing.png')
rows, cols, ch = img.shape
pts1 = np.float32([[50, 50], [200, 50], [50, 200]])
pts2 = np.float32([[10, 100], [200, 50], [100, 250]])
M = cv2.getAffineTransform(pts1, pts2)
dst = cv2.warpAffine(img, M, (cols, rows))
plt.subplot(121), plt.imshow(img), plt.title('Input')
plt.subplot(122), plt.imshow(dst), plt.title('Output')
plt.show()

結果:
在這里插入圖片描述

透視變換

對透視轉換,你需要一個 3x3 變換矩陣,即使在轉換之后,直線也將保持直線,要找到這個變換矩陣,需要輸入影像上的 4 個點和輸出影像上的相應點,在這四點中,任意三點不應該共線,然后通過 cv2.getPerspectiveTransform 找到變換矩陣,然后對這個 3x3 變換矩陣使用 cv2.warpPerspective

代碼:

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

img = cv2.imread('C:/Users/Zhang-Lei/Desktop/sudoku.png')
rows, cols, ch = img.shape
pts1 = np.float32([[56, 65], [368, 52], [28, 387], [389, 390]])
pts2 = np.float32([[0, 0], [300, 0], [0, 300], [300, 300]])
M = cv2.getPerspectiveTransform(pts1, pts2)
dst = cv2.warpPerspective(img, M, (300, 300))
plt.subplot(121), plt.imshow(img), plt.title('Input')
plt.subplot(122), plt.imshow(dst), plt.title('Output')
plt.show()

結果:
在這里插入圖片描述

二值化

簡單閾值法

此方法是直截了當的,如果像素值大于閾值,則會被賦為一個值(可能為白色),否則會賦為另一個值(可能為黑色),使用的函式是 cv2.threshold,第一個引數是源影像,它應該是灰度影像,第二個引數是閾值,用于對像素值進行分類,第三個引數是 maxval,它表示像素值大于(有時小于)閾值時要給定的值,opencv 提供了不同型別的閾值,由函式的第四個引數決定,不同的型別有:

  • cv.THRESH_BINARY
  • cv.THRESH_BINARY_INV
  • cv.THRESH_TRUNC
  • cv.THRESH_TOZERO
  • cv.THRESH_TOZERO_INV

獲得兩個輸出,第一個是 retval,稍后將解釋,第二個輸出是我們的閾值影像,

代碼:

import cv2
import matplotlib.pyplot as plt

img = cv2.imread('C:/Users/Zhang-Lei/Desktop/snack_gray.png', cv2.IMREAD_UNCHANGED)
ret1, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
ret2, thresh2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
ret3, thresh3 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)
ret4, thresh4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)
ret5, thresh5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)
titles = ['Original', '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], cmap='gray')
    plt.title(titles[i])
    plt.xticks([])
    plt.yticks([])
plt.show()

結果:
在這里插入圖片描述
可以看到,其他五幅影像都以不同的方式區分像素,

自適應閾值

在前一節中,我們使用一個全域變數作為閾值,但在影像在不同區域具有不同照明條件的條件下,這可能不是很好,在這種情況下,我們采用自適應閾值,在此,演算法計算影像的一個小區域的閾值,因此,我們得到了同一影像不同區域的不同閾值,對于不同光照下的影像,得到了更好的結果,

它有三個“特殊”輸入引數,只有一個輸出引數,

  • Adaptive Method :它決定如何計算閾值,

  • cv2.ADAPTIVE_THRESH_MEAN_C :閾值是指鄰近地區的平均值,

  • cv2.ADAPTIVE_THRESH_GAUSSIAN_C :閾值是權重為高斯窗的鄰域值的加權和,

  • Block Size :它決定了計算閾值的視窗區域的大小,

  • C :它只是一個常數,會從平均值或加權平均值中減去該值,

下面的代碼比較了具有不同照明的影像的全域閾值和自適應閾值:

代碼:

import cv2
import matplotlib.pyplot as plt

img = cv2.imread('C:/Users/Zhang-Lei/Desktop/snack_gray.png', 0)
img = cv2.medianBlur(img, 5)
ret, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
thresh2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY, 11, 2)
thresh3 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY, 11, 2)
titles = ['Original Image', 'Global Thresholding (v = 127)',
          'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
images = [img, thresh1, thresh2, thresh3]
for i in range(4):
    plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

結果:
在這里插入圖片描述

Otsu二值化(俗稱大津法)

在第一部分中,有一個引數 retval,當我們進行 Otsu 二值化時,它的用途就來了,那是什么?

在全域閾值化中,我們使用一個任意的閾值,對嗎?那么,我們如何知道我們選擇的值是好的還是不好的呢?答案是,試錯法,但是考慮一個雙峰影像(簡單來說,雙峰影像是一個直方圖有兩個峰值的影像),對于那個影像,我們可以近似地取這些峰值中間的一個值作為閾值,對嗎?這就是 Otsu 二值化所做的,所以簡單來說,它會自動從雙峰影像的影像直方圖中計算出閾值,(對于非雙峰影像,二值化將不準確,)

為此,我們使用了 cv2.threshold 函式,但傳遞了一個額外的符號 cv2.THRESH_OTSU ,對于閾值,只需傳入零,然后,該演算法找到最佳閾值,并作為第二個輸出回傳 retval,如果不使用 otsu 閾值,則 retval 與你使用的閾值相同,

查看下面的示例,輸入影像是噪聲影像,在第一種情況下,我應用了值為 127 的全域閾值,在第二種情況下,我直接應用 otsu 閾值,在第三種情況下,我使用 5x5 高斯核過濾影像以去除噪聲,然后應用 otsu 閾值,查看噪聲過濾如何改進結果,

代碼:

import cv2
import matplotlib.pyplot as plt

img = cv2.imread('C:/Users/Zhang-Lei/Desktop/noisy.png', 0)
# 全域閾值
ret1, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# Otsu 閾值
ret2, thresh2 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 經過高斯濾波的 Otsu 閾值
blur = cv2.GaussianBlur(img, (5, 5), 0)
ret3, thresh3 = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 畫出所有的影像和他們的直方圖
images = [img, 0, thresh1, img, 0, thresh2, blur, 0, thresh3]
titles = ['Original Noisy Image', 'Histogram', 'Global Thresholding (v=127)',
          'Original Noisy Image', 'Histogram', "Otsu's Thresholding",
          'Gaussian filtered Image', 'Histogram', "Otsu's Thresholding"]
for i in range(3):
    plt.subplot(3, 3, i * 3 + 1), plt.imshow(images[i * 3], 'gray')
    plt.title(titles[i * 3]), plt.xticks([]), plt.yticks([])
    plt.subplot(3, 3, i * 3 + 2), plt.hist(images[i * 3].ravel(), 256)
    plt.title(titles[i * 3 + 1]), plt.xticks([]), plt.yticks([])
    plt.subplot(3, 3, i * 3 + 3), plt.imshow(images[i * 3 + 2], 'gray')
    plt.title(titles[i * 3 + 2]), plt.xticks([]), plt.yticks([])
plt.show()

結果:
在這里插入圖片描述

Otsu 二值化原理

本節演示了 otsu 二值化的 python 實作,以展示它的實際作業原理,

由于我們使用的是雙峰影像,因此 Otsu 的演算法試圖找到一個閾值(t),該閾值將由下式計算得到的類內加權方差最小化:

其中:
在這里插入圖片描述
它實際上找到一個 T 值,它位于兩個峰值之間,使得兩個類的方差最小,它可以簡單地在 python 中實作,如下所示:

代碼:

import cv2
import numpy as np

img = cv2.imread('C:/Users/Zhang-Lei/Desktop/noisy.png', 0)
blur = cv2.GaussianBlur(img, (5, 5), 0)
# 找到歸一化直方圖還有累計分布函式
hist = cv2.calcHist([blur], [0], None, [256], [0, 256])
hist_norm = hist.ravel() / hist.max()
Q = hist_norm.cumsum()
bins = np.arange(256)
fn_min = np.inf
thresh = -1
for i in range(1, 256):
    p1, p2 = np.hsplit(hist_norm, [i])  # 概率
    q1, q2 = Q[i], Q[255] - Q[i]  # 類別總和
    b1, b2 = np.hsplit(bins, [i])  # 權重
    # f 找到均值與方差
    m1, m2 = np.sum(p1 * b1) / q1, np.sum(p2 * b2) / q2
    v1, v2 = np.sum(((b1 - m1) ** 2) * p1) / q1, np.sum(((b2 - m2) ** 2) * p2) / q2
    # 計算最小函式
    fn = v1 * q1 + v2 * q2
    if fn < fn_min:
        fn_min = fn
        thresh = i
# 用 Opencv2 函式的 otsu'閾值
ret, otsu = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
print("{} {}".format(thresh, ret))

結果:
在這里插入圖片描述

濾波

二維卷積(影像濾波)

與一維信號一樣,影像也可以通過各種低通濾波器(LPF)、高通濾波器(HPF)等進行過濾,LPF 有助于消除噪音、模糊影像等,HPF 濾波器有助于在影像中找到邊緣,

opencv 提供了函式 cv2.filter2D(),用于將內核與影像卷積起來,作為一個例子,我們將嘗試對影像進行均值濾波操作,5x5 均值濾波卷積核如下:
在這里插入圖片描述
操作如下:將該內核中心與一個像素對齊,然后將該內核下面的所有 25 個像素相加,取其平均值,并用新的平均值替換這個25x25視窗的中心像素,它繼續對影像中的所有像素執行此操作,試試下面這段代碼并觀察結果:

代碼:

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('C:/Users/Zhang-Lei/Desktop/noisy.png')
kernel = np.ones((5, 5), np.float32) / 25
dst = cv2.filter2D(img, -1, kernel)
plt.subplot(121), plt.imshow(img), plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(dst), plt.title('Averaging')
plt.xticks([]), plt.yticks([])
plt.show()

結果:
在這里插入圖片描述
可見影像在濾波的作用下變得模糊了,

影像模糊(影像平滑)

影像模糊是通過將影像與低通濾波核卷積來實作的,它有助于消除噪音,它實際上從影像中洗掉高頻內容(例如:噪聲、邊緣),所以在這個操作中邊緣有點模糊,(好吧,有一些模糊技術不會使邊緣太模糊),OpenCV 主要提供四種模糊技術,

均值濾波

這是通過用一個歸一化的濾波器內核與影像卷積來完成的,它只需取內核區域下所有像素的平均值并替換中心元素,這是通過函式 cv2.blur()或 cv2.boxFilter() 完成的,有關內核的更多詳細資訊,請查看檔案,我們應該指定濾波器內核的寬度和高度,3x3 標準化框濾波器如下所示:
在這里插入圖片描述
注意 :如果你不用標準化濾波,使用cv2.boxFilter(),傳入 normalize=False 引數,

5x5 核的簡單應用如下所示:

import cv2
from matplotlib import pyplot as plt

img = cv2.imread('C:/Users/Zhang-Lei/Desktop/opencv.jpg')
blur = cv2.blur(img, (5, 5))
plt.subplot(121), plt.imshow(img), plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(blur), plt.title('Blurred')
plt.xticks([]), plt.yticks([])
plt.show()

結果:
在這里插入圖片描述

高斯濾波

在這種情況下,使用高斯核代替了核濾波器,它是通過函式 **cv2.GaussianBlur()**完成的,我們應該指定內核的寬度和高度,它應該是正數并且是奇數(奇數才有一個中位數),我們還應該分別指定 x 和 y 方向的標準偏差、sigmax 和 sigmay,如果只指定 sigmax,則 sigmay 與 sigmax 相同,如果這兩個值都是 0,那么它們是根據內核大小計算出來的,高斯模糊是消除影像高斯噪聲的有效方法,

如果需要,可以使用函式 cv.getGaussianKernel() 創建高斯內核,

上述代碼可以修改為高斯濾波器:

blur = cv2.GaussianBlur(img,(5,5),0)

代碼:

import cv2
from matplotlib import pyplot as plt

img = cv2.imread('C:/Users/Zhang-Lei/Desktop/opencv.jpg')
blur = cv2.GaussianBlur(img, (5, 5), 0)
plt.subplot(121), plt.imshow(img), plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(blur), plt.title('GaussianBlurred')
plt.xticks([]), plt.yticks([])
plt.show()

結果:
在這里插入圖片描述

中值濾波

在這里,函式 cv2.medianBlur() 取內核區域下所有像素的中值,將中央元素替換為該中值,這對影像中的椒鹽噪聲非常有效,有趣的是,在上面的過濾器中,中心元素是一個新計算的值,它可能是影像中的像素值,也可能是一個新值,但在中值模糊中,中心元素總是被影像中的一些像素值所取代,可以有效降低噪音,它的內核大小應該是一個正的奇數整數,

在這個演示中,我在原始影像中添加了 5000個椒鹽噪聲,并應用了中間模糊,只需要將上面代碼改為中值濾波器:

median = cv2.medianBlur(img,5)

代碼:

import random
import cv2
from matplotlib import pyplot as plt


# 添加椒鹽噪聲
def noise(dst):
    height, width = dst.shape[:2]
    for _ in range(height*width//4):
        x = random.randint(0, height-1)
        y = random.randint(0, width-1)
        dst[x, y] = 255  # 添加鹽噪聲
        p = random.randint(0, height-1)
        q = random.randint(0, width-1)
        dst[p, q] = 0  # 添加椒噪聲


img = cv2.imread('C:/Users/Zhang-Lei/Desktop/snack_gray.png', 0)
plt.subplot(131), plt.imshow(img, cmap='gray'), plt.title('Original')
plt.xticks([]), plt.yticks([])
noise(img)
plt.subplot(132), plt.imshow(img, cmap='gray'), plt.title('Noise')
plt.xticks([]), plt.yticks([])
median = cv2.medianBlur(img, 5)
plt.subplot(133), plt.imshow(median, cmap='gray'), plt.title('MedianBlurred')
plt.xticks([]), plt.yticks([])
plt.show()

結果:
在這里插入圖片描述

可以看到,第二張照片是在原圖的基礎上添加了噪聲,第三張圖片雖然去除了噪聲,但仍然會有部分模糊,

雙邊濾波

cv2.bilateralFilter() 在保持邊緣銳利的同時,對噪聲去除非常有效,但與其他過濾器相比,操作速度較慢,我們已經看到高斯濾波器取像素周圍的鄰域并找到其高斯加權平均值,該高斯濾波器是一個空間函式,即在濾波時考慮相鄰像素,但是它不考慮像素是否具有幾乎相同的強度,也不考慮像素是否是邊緣像素,所以它也會模糊邊緣,這是我們不想做的,

雙邊濾波器在空間上也采用高斯濾波器,而另一個高斯濾波器則是像素差的函式,空間的高斯函式確保模糊只考慮鄰近像素,而強度差的高斯函式確保模糊只考慮與中心像素強度相似的像素,所以它保留了邊緣,因為邊緣的像素會有很大的強度變化,

下面的示例顯示使用雙邊濾波,同樣的,只需要將上面代碼改為雙邊濾波器:

blur = cv2.bilateralFilter(img,9,75,75)

代碼:

import cv2
from matplotlib import pyplot as plt

img = cv2.imread('C:/Users/Zhang-Lei/Desktop/snack_gray.png', 0)
plt.subplot(121), plt.imshow(img, cmap='gray'), plt.title('Original')
plt.xticks([]), plt.yticks([])
blur = cv2.bilateralFilter(img, 9, 75, 75)
plt.subplot(122), plt.imshow(blur, cmap='gray'), plt.title('BilateralBlurred')
plt.xticks([]), plt.yticks([])
plt.show()

結果:
在這里插入圖片描述

可見影像經過雙邊濾波變得模糊了一些,
在這里插入圖片描述

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/302711.html

標籤:AI

上一篇:import torchvision錯誤提示ImportError: DLL load failed: 找不到指定的模塊。

下一篇:資料倉庫之資料質量建設(深度好文)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more