自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Otsu閾值算法實戰(zhàn)——基于Python實現(xiàn)圖像背景分割

譯文 精選
開發(fā) 前端
本文將通過一個具體的實例來展示Otsu閾值算法在圖像背景分割中的應用。

譯者 | 朱先忠

審校 | 孫淑娟

讓我們從一個非常技術性的概念開始。

將圖像作為2D信號來瀏覽、分析和處理

這里有其他一些恰當?shù)亩x:

  • 信號是一種隨空間或時間變化的量,它可以用來傳輸某種形式的信息。
  • 圖像只不過是照射到光學系統(tǒng)上的光量,也就是你用來呈現(xiàn)它的相機或畫布。

從這種意義上來說,圖像只不過是一種2D信號,這種電磁信號攜帶了物理系統(tǒng)檢索到的一些信息。

因此,當我們確定了圖像確實是一種信號時,我們可以考慮將信號處理技術應用于圖像處理任務?,F(xiàn)在,我們可以停止哲學討論,從具體的編碼部分開始。

說到哲學,不妨讓我們拍下這張照片:?

圖片來源:Tingey Injury律師事務所

圖片中的哲學家正在做他的工作:思考。雕塑后面是一片非常白的背景,當然我們并不在乎它。然而,我們能擺脫它嗎?我們能得到這樣的東西嗎?

圖片來源:本文作者

如果我這樣問你,那就意味著我們可以。

每個略懂一些Photoshop的人都可以做到這一點,但你如何使用Python自動做到這樣呢?下面我將為你展示如何做到這一點。

1.總的想法

現(xiàn)在,讓我們來舉一個簡單的例子。

一個大正方形里面裝著一個小正方形。這是一個極其簡單的案例。我們要做的是將較小正方形中的所有數(shù)值設置為1,將外部的所有數(shù)值都設置為0。

我們可以使用此代碼提取這兩個值:

然后,做諸如以下的操作:

上述代碼將圖像從兩個值轉換為1和0。

這非常簡單,對吧?下面,讓我們做一點更大的嘗試。

現(xiàn)在,我們將在較大的正方形內做一個小正方形,但兩個正方形都有一些噪音數(shù)據(jù)。

new_image = np.random.normal(loc=190.0, scale=10.0, size=(50,50)).astype(int)
new_image[0:10] = new_image[-10:]=np.random.normal(loc=20.0, scale=10.0, size=(10,50)).astype(int)
new_image[:,0:10] = new_image[:,-10:]=np.random.normal(loc=20.0, scale=10.0, size=(50,10)).astype(int)
plt.imshow(new_image)

我的意思是,我們不僅有2個值,而且理論上我們還可以有0到255之間的所有值,這是這個編碼中全部數(shù)值的范圍。

那么,我們該怎樣做呢?

我們要做的第一件事是將圖像(2D信號)扁平化,并將其更改為1D信號。

圖片來源:本文作者

這張圖片是一張50x50的圖片,我們有了一個更加“紛亂”一些的50x50=2500長的1D信號。

現(xiàn)在,如果我們研究1D信號的分布,那么,我們將會得到這樣的結果:

import seaborn as sns
sns.distplot(new_image.ravel(),bins=40)

正如我們所看到的,我們有兩個正態(tài)分布。這正是Otsu算法表現(xiàn)最好的地方。其基本思想是,圖像的背景和主題具有兩種不同的性質和兩個不同的領域。例如,在這種情況下,第一個高斯鐘形是與背景相關的鐘形(假設從0到50),而第二個高斯鐘形則是較小正方形(從150到250)中的一個。

所以,假設我們決定將大于100的所有值都設置為1,將小于0的所有值設置為0:?

new_image_copy = new_image.copy()
new_image[new_image<100]=0
new_image[new_image!=0]=1

這樣做的結果是在背景和主體之間形成了以下遮罩:?

plt.subplot(1,2,2)
plt.imshow(new_image)
plt.subplot(1,2,1)
plt.imshow(new_image_copy)

這就是Otsu算法的全部思想:

  • 將圖像作為2D信號導入/讀取。
  • 將圖像展平為1D矢量。
  • 選擇一個閾值。
  • 將低于該閾值的所有內容設置為0,將高于該閾值的全部內容設置為1。很簡單,對吧?
    但是,我們如何選擇合適的閾值呢?什么是最好的?讓我們談談數(shù)學。

2.理論介紹

讓我們將這個概念形式化一點。

我們在圖像中有一個像素域。完整的域從0到255(白色到黑色),但不一定要那么寬(例如,可以從20到200)。

現(xiàn)在,多個點可以具有相同的像素強度(我們可以在同一圖像中具有兩個黑色像素)。假設在一個有100個像素的圖像中,我們有3個強度為255的像素?,F(xiàn)在,在該圖像中具有強度255的概率是3/100。

通常,我們可以說圖像中具有像素i的概率為:?

圖片來源:本文作者

現(xiàn)在,讓我們假設我們正在進行分割的像素是像素k(在我們之前的例子中,k是100)。這將對數(shù)據(jù)點進行分類。k之前的所有點屬于類別0,k之后的所有點都屬于類別1。

這意味著,從類別0中選擇一個點的概率如下:?

圖片來源:本文作者

而從類別1中選擇一個點的概率如下:?

圖片來源:本文作者

正如我們所看到的,這兩種概率顯然都依賴于k。

現(xiàn)在,我們可以計算的另一個值是每個類別的方差:?

其中:?

圖片來源:本文作者

然后這樣:

圖片來源:本文作者

西格瑪值是每個類別的方差,也就是該類別在mu_0和mu_1的平均值周圍分布的程度。

現(xiàn)在,理論上的想法是找到創(chuàng)造我們之前在這張照片中看到的那個小山谷的值:?

但我們使用的方法略有不同,而且更加嚴格。通過使用線性判別分析(LDA:https://en.wikipedia.org/wiki/Linear_discriminant_analysis#Fisher's_linear_discriminant)的相同思想。在(費舍爾)LDA中,我們希望找到一個超平面,以使類別間的方差最大化(這樣兩個均值彼此相距最遠)并且類別內的方差盡可能?。ㄟ@樣我們就不會在兩個類別數(shù)據(jù)點之間有太多重疊)。

在這種情況下,我們沒有任何超平面,而我們設置的閾值(我們的k)甚至不是一條直線,但它更像是一個我們用來區(qū)分數(shù)據(jù)點并對其進行分類的概率值。

可以證明(原始論文中提供完整的證明),在假設背景域與主題域不同的情況下,背景和主題之間的最佳分割是通過最小化此量來實現(xiàn)的。

圖片來源:本文作者

這意味著,我們可以嘗試所有不同的k值,而且只選擇k值最小的那一個。

3.編程實現(xiàn)

這個理論看起來可能很復雜,很難理解,但實現(xiàn)起來非常容易,它由三個部分組成:

3.1 導入庫

我們要做的第一件事是導入我們需要的4個基本庫。

import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
import seaborn as sns

3.2 閾值函數(shù)

一旦你找到了完美的閾值,接下來就是如何將其應用于你的圖像:

def threshold_image(im,th):
thresholded_im = np.zeros(im.shape)
thresholded_im[im >= th] = 1
return thresholded_im

3.3 Otsu算法的標準

計算此數(shù)量的函數(shù)如下:

圖片來源:本文作者

相關代碼如下所示:

def compute_otsu_criteria(im, th):
thresholded_im = threshold_image(im,th)
nb_pixels = im.size
nb_pixels1 = np.count_nonzero(thresholded_im)
weight1 = nb_pixels1 / nb_pixels
weight0 = 1 - weight1
if weight1 == 0 or weight0 == 0:
return np.inf
val_pixels1 = im[thresholded_im == 1]
val_pixels0 = im[thresholded_im == 0]
var0 = np.var(val_pixels0) if len(val_pixels0) > 0 else 0
var1 = np.var(val_pixels1) if len(val_pixels1) > 0 else 0
return weight0 * var0 + weight1 * var1

3.4 最佳閾值計算

另一個函數(shù)只是在所有可能的ks上運行,并根據(jù)上面的標準找到最好的一個:

def find_best_threshold(im):
threshold_range = range(np.max(im)+1)
criterias = [compute_otsu_criteria(im, th) for th in threshold_range]
best_threshold = threshold_range[np.argmin(criterias)]
return best_threshold

3.5 完整的實現(xiàn)

因此,我們使用的是接下來的這幅圖像:

圖片來源:Ben Dumond on Unsplash

如果我們將該圖像保存在路徑中,并應用Otsu算法,我們會得到:

path_image = '/content/test_building.jpeg'
im = np.asarray(Image.open(path_image).convert('L'))
im_otsu = threshold_image(im,find_best_threshold(im))

如果我們比較im(原始圖像)和im_otsu(算法之后的圖像),我們得到:

plt.figure(figsize=(20,10))
plt.subplot(1,2,1)
plt.title('Original Image',fnotallow=20)
plt.imshow(im,cmap='gray')
plt.subplot(1,2,2)
plt.title('Otsu Method Image',fnotallow=20)
plt.imshow(im_otsu,cmap='gray')
plt.tight_layout()

正如我們所看到的,圖片右上部分的黑色部分被誤解為主題,因為它與一些主題的色調相同。人并不總是完美的,算法亦然。

4.尾聲

感謝您在Otsu算法教程的整個過程中一直陪伴在我身邊。

在這篇簡短的文章中,我們看到:

  • 圖像可以被視為2D信號,然后可以使用信號處理技術進行分析。
  • Otsu算法的假設是,圖像的背景和主題有兩個連續(xù)的、不重疊的、可區(qū)分的域。
  • 如何在給定Otsu算法的情況下找到圖像的背景和主題之間的最佳區(qū)分。我們如何將Otsu算法解釋為Fisher線性判別式。
  • 如何使用Python實現(xiàn)Otsu算法。
  • 如何在真實圖像中應用此算法。

譯者介紹

朱先忠,51CTO社區(qū)編輯,51CTO專家博客、講師,濰坊一所高校計算機教師,自由編程界老兵一枚。

原文標題:??Hands on Otsu Thresholding Algorithm for Image Background Segmentation, using Python??,作者:Piero Paialunga

責任編輯:華軒 來源: 51CTO
相關推薦

2024-05-29 11:06:10

2023-06-01 09:00:00

圖像分割模自動化

2023-06-01 08:00:00

圖像分割機器學習

2020-04-28 15:10:12

OpenCV Pyth閾值Linux

2023-11-15 13:20:14

Python圖像分割

2015-05-11 10:40:08

加密數(shù)字圖像加密加密算法

2022-09-20 14:35:59

ArkUI鴻蒙JS

2022-06-16 10:29:33

神經(jīng)網(wǎng)絡圖像分類算法

2017-05-26 11:00:38

Python算法

2024-06-28 10:16:58

2017-05-22 13:15:45

TensorFlow深度學習

2024-03-07 08:22:40

QuickShift分割算法

2020-05-21 14:50:48

代碼機器學習圖像

2022-11-11 15:07:50

深度學習函數(shù)鑒別器

2017-05-12 16:25:44

深度學習圖像補全tensorflow

2018-07-19 15:13:15

深度學習圖像

2024-10-17 16:54:47

2021-12-08 11:30:41

Python全景拼接代碼

2022-10-13 08:08:40

解釋器模式算法

2024-05-15 15:27:39

點贊
收藏

51CTO技術棧公眾號