Python 深入了解opencv圖像分割算法
本文主要是基于Python Opencv 實(shí)現(xiàn)的圖像分割,其中使用到的opencv的函數(shù)有:
- 使用 OpenCV 函數(shù) cv::filter2D 執(zhí)行一些拉普拉斯濾波以進(jìn)行圖像銳化
- 使用 OpenCV 函數(shù) cv::distanceTransform 以獲得二值圖像的派生(derived)表示,其中每個(gè)像素的值被替換為其到最近背景像素的距離
- 使用 OpenCV 函數(shù) cv::watershed 將圖像中的對(duì)象與背景隔離

加載源圖像并檢查它是否加載沒(méi)有任何問(wèn)題,然后顯示它:
# Load the image
parser = argparse.ArgumentParser(description='Code for Image Segmentation with Distance Transform and Watershed Algorithm.\
Sample code showing how to segment overlapping objects using Laplacian filtering, \
in addition to Watershed and Distance Transformation')
parser.add_argument('--input', help='Path to input image.', default='cards.png')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
# Show source image
cv.imshow('Source Image', src)
原圖

將背景從白色更改為黑色,因?yàn)檫@將有助于稍后在使用距離變換(Distance Transform)期間提取更好的結(jié)果
src[np.all(src == 255, axis=2)] = 0
如果不太理解numpy.all的的用法,可以參考這里

之后,我們將銳化(sharpen)我們的圖像,以銳化前景對(duì)象(the foreground objects)的邊緣。 我們將應(yīng)用具有相當(dāng)強(qiáng)過(guò)濾器的拉普拉斯(laplacian)過(guò)濾器(二階導(dǎo)數(shù)的近似值):
# 創(chuàng)建一個(gè)內(nèi)核,我們將用它來(lái)銳化我們的圖像
# 一個(gè)二階導(dǎo)數(shù)的近似值,一個(gè)非常強(qiáng)大的內(nèi)核
kernel = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]], dtype=np.float32)
# do the laplacian filtering as it is
# well, we need to convert everything in something more deeper then CV_8U
# because the kernel has some negative values,
# and we can expect in general to have a Laplacian image with negative values
# BUT a 8bits unsigned int (the one we are working with) can contain values from 0 to 255
# so the possible negative number will be truncated
imgLaplacian = cv.filter2D(src, cv.CV_32F, kernel)
sharp = np.float32(src)
imgResult = sharp - imgLaplacian
# convert back to 8bits gray scale
imgResult = np.clip(imgResult, 0, 255)
imgResult = imgResult.astype('uint8')
imgLaplacian = np.clip(imgLaplacian, 0, 255)
imgLaplacian = np.uint8(imgLaplacian)
#cv.imshow('Laplace Filtered Image', imgLaplacian)
cv.imshow('New Sharped Image', imgResult)
銳化處理的主要目的是突出灰度的過(guò)度部分。由于拉普拉斯是一種微分算子,如果所使用的定義具有負(fù)的中心系數(shù),那么必須將原圖像減去經(jīng)拉普拉斯變換后的圖像,而不是加上它,從而得到銳化結(jié)果。----摘自《數(shù)字圖像處理(第三版)》


現(xiàn)在我們將新的銳化源圖像分別轉(zhuǎn)換為灰度和二值圖像(binary):
# Create binary image from source image
bw = cv.cvtColor(imgResult, cv.COLOR_BGR2GRAY)
_, bw = cv.threshold(bw, 40, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
cv.imshow('Binary Image', bw)
我們現(xiàn)在準(zhǔn)備在二值圖像(binary image)上應(yīng)用距離變換。 此外,我們對(duì)輸出圖像進(jìn)行歸一化,以便能夠?qū)Y(jié)果進(jìn)行可視化和閾值處理:
# Perform the distance transform algorithm
dist = cv.distanceTransform(bw, cv.DIST_L2, 3)
# 對(duì)范圍 = {0.0, 1.0} 的距離圖像(the distance image)進(jìn)行歸一化(Normalize),
# 以便我們可以對(duì)其進(jìn)行可視化和閾值處理
cv.normalize(dist, dist, 0, 1.0, cv.NORM_MINMAX)
cv.imshow('Distance Transform Image', dist)
distanceTransform用法
cv.distanceTransform( src, distanceType, maskSize[, dst[, dstType]] )
src:輸入圖像,數(shù)據(jù)類型為CV_8U的單通道圖像
dst: 輸出圖像,與輸入圖像具有相同的尺寸,數(shù)據(jù)類型為CV_8U或者CV_32F的單通道圖像。
distanceType:選擇計(jì)算兩個(gè)像素之間距離方法的標(biāo)志,其常用的距離度量方法, DIST_L1(distance = |x1-x2| + |y1-y2| 街區(qū)距離), DIST_L2 (Euclidean distance 歐幾里得距離,歐式距離) 。
maskSize:距離變換掩碼矩陣的大小,參數(shù)可以選擇的尺寸為DIST_MASK_3(3×3)和DIST_MASK_5(5×5).

我們對(duì) dist 圖像進(jìn)行閾值處理,然后執(zhí)行一些形態(tài)學(xué)操作(即膨脹)以從上述圖像中提取峰值:
# Threshold to obtain the peaks
# This will be the markers for the foreground objects
_, dist = cv.threshold(dist, 0.4, 1.0, cv.THRESH_BINARY)
# Dilate a bit the dist image
kernel1 = np.ones((3,3), dtype=np.uint8)
dist = cv.dilate(dist, kernel1)
cv.imshow('Peaks', dist)

從每個(gè) blob 中,我們?cè)?cv::findContours 函數(shù)的幫助下為分水嶺算法創(chuàng)建一個(gè)種子/標(biāo)記:
# Create the CV_8U version of the distance image
# It is needed for findContours()
dist_8u = dist.astype('uint8')
# Find total markers
contours, _ = cv.findContours(dist_8u, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
# Create the marker image for the watershed algorithm
markers = np.zeros(dist.shape, dtype=np.int32)
# Draw the foreground markers
for i in range(len(contours)):
cv.drawContours(markers, contours, i, (i+1), -1)
# Draw the background marker
cv.circle(markers, (5,5), 3, (255,255,255), -1)
markers_8u = (markers * 10).astype('uint8')
cv.imshow('Markers', markers_8u)
最后,我們可以應(yīng)用分水嶺算法,并將結(jié)果可視化:
# Perform the watershed algorithm
cv.watershed(imgResult, markers)
#mark = np.zeros(markers.shape, dtype=np.uint8)
mark = markers.astype('uint8')
mark = cv.bitwise_not(mark)
# uncomment this if you want to see how the mark
# image looks like at that point
#cv.imshow('Markers_v2', mark)
# Generate random colors
colors = []
for contour in contours:
colors.append((rng.randint(0,256), rng.randint(0,256), rng.randint(0,256)))
# Create the result image
dst = np.zeros((markers.shape[0], markers.shape[1], 3), dtype=np.uint8)
# Fill labeled objects with random colors
for i in range(markers.shape[0]):
for j in range(markers.shape[1]):
index = markers[i,j]
if index > 0 and index <= len(contours):
dst[i,j,:] = colors[index-1]
# Visualize the final image
cv.imshow('Final Result', dst)

基于機(jī)器學(xué)習(xí)的圖像分割
Pixellib是一個(gè)用于對(duì)圖像和視頻中的對(duì)象進(jìn)行分割的庫(kù)。 它支持兩種主要類型的圖像分割:
1.語(yǔ)義分割
2.實(shí)例分割
PixelLib 支持兩個(gè)用于圖像分割的深度學(xué)習(xí)庫(kù),分別是 Pytorch 和 Tensorflow
以上就是Python 深入了解opencv圖像分割算法的詳細(xì)內(nèi)容,更多關(guān)于Python的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- 使用Python和OpenCV進(jìn)行視覺(jué)圖像分割的代碼示例
- OpenCV實(shí)戰(zhàn)記錄之基于分水嶺算法的圖像分割
- Tensorflow2.10實(shí)現(xiàn)圖像分割任務(wù)示例詳解
- Python基于紋理背景和聚類算法實(shí)現(xiàn)圖像分割詳解
- OpenCV利用K-means實(shí)現(xiàn)根據(jù)顏色進(jìn)行圖像分割
- 詳解Python OpenCV圖像分割算法的實(shí)現(xiàn)
- python中的opencv?圖像分割與提取
- openCV實(shí)現(xiàn)圖像分割
- 計(jì)算機(jī)視覺(jué)中圖像分割怎么學(xué)?從入門到實(shí)踐的核心技術(shù)全解析
相關(guān)文章
matplotlib實(shí)現(xiàn)熱成像圖colorbar和極坐標(biāo)圖的方法
今天小編就為大家分享一篇matplotlib實(shí)現(xiàn)熱成像圖colorbar和極坐標(biāo)圖的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-12-12
python實(shí)現(xiàn)從文件中讀取數(shù)據(jù)并繪制成 x y 軸圖形的方法
今天小編就為大家分享一篇python實(shí)現(xiàn)從文件中讀取數(shù)據(jù)并繪制成 x y 軸圖形的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-10-10
Keras搭建孿生神經(jīng)網(wǎng)絡(luò)Siamese?network比較圖片相似性
這篇文章主要為大家介紹了Keras搭建孿生神經(jīng)網(wǎng)絡(luò)Siamese?network比較圖片相似性,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
使用py2exe在Windows下將Python程序轉(zhuǎn)為exe文件
這篇文章主要介紹了Windows下用py2exe將Python程序轉(zhuǎn)為exe文件的方法,注意py2exe只是負(fù)責(zé)文件格式的轉(zhuǎn)換,并不能將Python程序編譯為機(jī)器碼,要的朋友可以參考下2016-03-03
pycharm與jupyter?lab/notebook結(jié)合使用方式
這篇文章主要介紹了pycharm與jupyter?lab/notebook結(jié)合使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
使用Python構(gòu)建智能BAT文件生成器的完美解決方案
這篇文章主要為大家詳細(xì)介紹了如何使用 wxPython 構(gòu)建一個(gè)智能的 BAT 文件生成器,它不僅能夠?yàn)?nbsp;Python 腳本生成啟動(dòng)腳本,還提供了完整的文件管理和數(shù)據(jù)庫(kù)存儲(chǔ)功能,感興趣的小伙伴可以了解下2025-07-07
解決同一目錄下python import報(bào)錯(cuò)問(wèn)題
這篇文章主要介紹了解決同一目錄下python import報(bào)錯(cuò)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
Python基于requests庫(kù)爬取網(wǎng)站信息
這篇文章主要介紹了python基于requests庫(kù)爬取網(wǎng)站信息,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03

