OpenCV 中的图像处理 004_平滑图像
本文主要內(nèi)容來自于 OpenCV-Python 教程 的 OpenCV 中的圖像處理 部分,這部分的全部主要內(nèi)容如下:
-
改變色彩空間
學(xué)習(xí)在不同色彩空間之間改變圖像。另外學(xué)習(xí)跟蹤視頻中的彩色對(duì)象。
-
圖像的幾何變換
學(xué)習(xí)對(duì)圖像應(yīng)用不同的幾何變換,比如旋轉(zhuǎn)、平移等。
-
圖像閾值
學(xué)習(xí)使用全局閾值、自適應(yīng)閾值、Otsu 的二值化等將圖像轉(zhuǎn)換為二值圖像。
-
平滑圖像
學(xué)習(xí)模糊圖像,使用自定義內(nèi)核過濾圖像等。
-
形態(tài)變換
了解形態(tài)學(xué)變換,如侵蝕、膨脹、開放、閉合等。
-
圖像漸變
學(xué)習(xí)尋找圖像漸變、邊緣等。
-
Canny 邊緣檢測(cè)
學(xué)習(xí)通過 Canny 邊緣檢測(cè)尋找邊緣。
-
圖像金字塔
學(xué)習(xí)關(guān)于圖像金字塔的內(nèi)容,以及如何使用它們進(jìn)行圖像混合。
-
OpenCV 中的輪廓
所有關(guān)于 OpenCV 中的輪廓的內(nèi)容。
-
OpenCV 中的直方圖
所有關(guān)于 OpenCV 中的直方圖的內(nèi)容。
-
OpenCV 中的圖像變換
在 OpenCV 中遇到不同的圖像變換,如傅里葉變換、余弦變換等。
-
模板匹配
學(xué)習(xí)使用模板匹配在圖像中搜索對(duì)象。
-
霍夫線變換
學(xué)習(xí)在一幅圖像中探測(cè)線。
-
霍夫圓變換
學(xué)習(xí)在一幅圖像中探測(cè)圓。
-
使用分水嶺算法的圖像分割
學(xué)習(xí)使用分水嶺分割算法分割圖像。
-
使用 GrabCut 算法的交互式前景提取
學(xué)習(xí)使用 GrabCut 算法提取前景
目標(biāo)
學(xué)習(xí):
- 使用各種低通濾波器模糊圖像
- 將定制過濾器應(yīng)用于圖像(2D 卷積)
2D卷積(圖像過濾)
與一維信號(hào)一樣,圖像也可以使用各種低通濾波器 (LPF)、高通濾波器 (HPF) 等進(jìn)行濾波。LPF 有助于消除噪聲、模糊圖像等。HPF 過濾器有助于在圖像中找到邊緣。
OpenCV 提供了一個(gè)函數(shù)?**cv.filter2D()**來將內(nèi)核與圖像進(jìn)行卷積。例如,我們將在圖像上嘗試平均濾波器。一個(gè) 5x5 平均濾波器內(nèi)核如下所示:
K=125[1111111111111111111111111]K = \frac{1}{25} \begin{bmatrix} 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \end{bmatrix}K=251????????11111?11111?11111?11111?11111????????
操作是這樣的:保持這個(gè)內(nèi)核高于一個(gè)像素,將所有低于這個(gè)內(nèi)核的 25 個(gè)像素相加,取平均值,然后用新的平均值替換中心像素。對(duì)圖像中的所有像素繼續(xù)該操作。試試這段代碼并檢查結(jié)果:
import numpy as np import cv2 as cv from matplotlib import pyplot as pltdef image_filtering():cv.samples.addSamplesDataSearchPath("/media/data/my_multimedia/opencv-4.x/samples/data")img = cv.imread(cv.samples.findFile('opencv-logo.png'))kernel = np.ones((5, 5), np.float32) / 25dst = cv.filter2D(img, -1, kernel)row, col, _ = img.shapeedge = np.full((row, 10, 3), (255, 255, 255), np.uint8);images = [img, edge, dst]dst = cv.hconcat(images)cv.imshow("Image", dst)cv.waitKey(-1)cv.destroyAllWindows()if __name__ == "__main__":image_filtering()結(jié)果如下:
圖像模糊(圖像平滑)
圖像模糊是通過將圖像與低通濾波器內(nèi)核進(jìn)行卷積來實(shí)現(xiàn)的。它對(duì)于去除噪聲很有用。它實(shí)際上從圖像中去除了高頻內(nèi)容(比如噪聲,邊緣)。所以在這個(gè)操作中邊緣有點(diǎn)模糊(也有不模糊邊緣的模糊技術(shù))。OpenCV 提供了四種主要的模糊技術(shù)類型。
1. 平均
這是通過將圖像與歸一化框?yàn)V波器進(jìn)行卷積來完成的。它只是取內(nèi)核區(qū)域下所有像素的平均值并替換中心元素。這通過函數(shù)?cv.blur()?或?cv.boxFilter() 完成。檢查關(guān)于內(nèi)核的文檔來了解更多細(xì)節(jié)。我們應(yīng)該指定內(nèi)核的寬度和高度。一個(gè) 3x3 歸一化框?yàn)V波器將看起來像下面這樣:
K=19[111111111]K = \frac{1}{9} \begin{bmatrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{bmatrix} K=91????111?111?111????
注意
如果不想使用歸一化的框?yàn)V波器,則使用 cv.boxFilter()。給函數(shù)傳遞一個(gè)參數(shù) normalize=False。
看一下下面的示例演示,它使用一個(gè) 5x5 大小的內(nèi)核:
def averaging_filter():cv.samples.addSamplesDataSearchPath("/media/data/my_multimedia/opencv-4.x/samples/data")img = cv.imread(cv.samples.findFile('opencv-logo-white.png'))blur = cv.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()if __name__ == "__main__":averaging_filter()結(jié)果如下:
高斯模糊
在這個(gè)方法中,不是使用框?yàn)V波器,而是使用一個(gè)高斯內(nèi)核。它通過函數(shù)?cv.GaussianBlur() 完成。我們應(yīng)該指定內(nèi)核的寬度和高度,它們應(yīng)該是正奇數(shù)。我們還應(yīng)該指定 X 和 Y 方向的標(biāo)準(zhǔn)差,sigmaX 和 sigmaY。如果只指定了 sigmaX,sigmaY 將取與 sigmaX 相同的值。如果兩者都為零,則它們根據(jù)內(nèi)核大小計(jì)算得出。高斯模糊在從圖像中移除高斯噪聲非常有效。
如果你想,你可以使用函數(shù) cv.getGaussianKernel() 創(chuàng)建一個(gè)高斯內(nèi)核。
上面的代碼可以修改以用于高斯模糊:
blur = cv.GaussianBlur(img, (5, 5), 0)如果使用函數(shù) cv.getGaussianKernel(),則需要如下的代碼:
kernel = cv.getGaussianKernel(5, 0)kernel_2D = kernel @ kernel.transpose()blur = cv.filter2D(img, -1, kernel_2D)結(jié)果如下:
3. 中值模糊
這里,函數(shù) cv.medianBlur() 取內(nèi)核區(qū)域下所有像素的中值,并將中心元素替換為該中值。這對(duì)圖像中的椒鹽噪聲非常有效。有趣的是,在上述濾波器中,中心元素是新計(jì)算的值,可能是圖像中的像素值或新值。但是在中值模糊中,中心元素總是被圖像中的某個(gè)像素值替換。它有效地降低了噪音。它的內(nèi)核大小應(yīng)該是一個(gè)正奇數(shù)。
在這個(gè)演示中,我為原始圖像添加了 50% 的噪點(diǎn)并應(yīng)用了中值模糊。添加噪點(diǎn),通過如下的 salt_and_pepper(image, n) 函數(shù)完成。檢查結(jié)果:
import numpy as np import cv2 as cv from matplotlib import pyplot as plt import randomdef salt_and_pepper(image, n):print(image.shape)for i in range(int(n / 2)):row = random.randint(0, image.shape[0] - 1)col = random.randint(0, image.shape[1] - 1)write_black = random.randint(0, 2)if write_black == 0:image[row][col] = (255, 255, 255)else:image[row][col] = (0, 0, 0)return imagedef median_blurring():cv.samples.addSamplesDataSearchPath("/media/data/my_multimedia/opencv-4.x/samples/data")img = cv.imread(cv.samples.findFile('opencv-logo-white.png'))img = salt_and_pepper(img, img.shape[0] * img.shape[1])median = cv.medianBlur(img, 5)plt.subplot(121), plt.imshow(img), plt.title('Original')plt.xticks([]), plt.yticks([])plt.subplot(122), plt.imshow(median), plt.title('Blurred')plt.xticks([]), plt.yticks([])plt.show()if __name__ == "__main__":median_blurring()結(jié)果如下:
4. 雙邊濾波
cv.bilateralFilter() 函數(shù)在保持邊緣銳利的同時(shí)去除噪聲非常有效。但與其它濾波器相比,這個(gè)操作速度較慢。我們已經(jīng)看到高斯濾波器采用像素周圍的鄰域,并找到其高斯加權(quán)平均值。這個(gè)高斯濾波器是一個(gè)單獨(dú)的空間函數(shù),即在濾波時(shí)考慮附近的像素。它不考慮像素是否具有幾乎相同的強(qiáng)度。它不考慮像素是否是邊緣像素。所以它也模糊了邊緣,這是我們不想做的。
雙邊濾波在空間上也采用了高斯濾波器,但多了一個(gè)高斯濾波器,它是像素差的函數(shù)。空間的高斯函數(shù)確保只考慮附近的像素進(jìn)行模糊處理,而強(qiáng)度差異的高斯函數(shù)確保只考慮那些與中心像素具有相似強(qiáng)度的像素進(jìn)行模糊處理。所以它保留了邊緣,因?yàn)檫吘壧幍南袼貢?huì)有很大的強(qiáng)度變化。
下面的示例顯示了雙邊濾波器的使用(有關(guān)參數(shù)的詳細(xì)信息,請(qǐng)?jiān)L問文檔)。
def bilateral_blurring():cv.samples.addSamplesDataSearchPath("/media/data/my_multimedia/opencv-4.x/samples/data")img = cv.imread(cv.samples.findFile('bilateral.jpg'))img = img[0:img.shape[0], 0:int(img.shape[1] / 2)]blur = cv.bilateralFilter(img, 9, 75, 75)images = [img, blur]dest = cv.hconcat(images)cv.imshow("Image", dest)cv.waitKey(-1)cv.destroyAllWindows()if __name__ == "__main__":bilateral_blurring()結(jié)果如下:
看,表面上的紋理消失了,但邊緣依然存在。
其它資源
練習(xí)
參考文檔
Smoothing Images
使用帶有高斯核的cv2.GaussianBlur和cv2.filter2D的不同結(jié)果?
利用OpenCV給彩色圖像添加椒鹽噪聲的方法
使用Python-OpenCV向圖片添加噪聲的實(shí)現(xiàn)(高斯噪聲、椒鹽噪聲)
Python 隨機(jī)數(shù)生成
Done.
總結(jié)
以上是生活随笔為你收集整理的OpenCV 中的图像处理 004_平滑图像的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 记 QT 应用开发中的一个二进制兼容性问
- 下一篇: GetModuleHandle,AfxG