日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

Python 计算机视觉(十二)—— OpenCV 进行图像分割

發(fā)布時間:2025/3/19 python 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python 计算机视觉(十二)—— OpenCV 进行图像分割 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

參考的一些文章以及論文我都會給大家分享出來 —— 鏈接就貼在原文,論文我上傳到資源中去,大家可以免費下載學習,如果當天資源區(qū)找不到論文,那就等等,可能正在審核,審核完后就可以下載了。大家一起學習,一起進步!加油!!??

目錄

前言

(1)圖像分割

(2)讀取圖像信息

1. 基于閾值的圖像分割

(1)基本概念

(2)二值化操作

a. 函數(shù)

b. 代碼實現(xiàn)

2. 基于邊緣檢測的圖像分割

3. 基于 K-Means 聚類的區(qū)域分割

(1)基本概念

(2)代碼實現(xiàn)

4. 基于分水嶺算法的圖像分割

(1)基本概念

(2)代碼實現(xiàn)

5.整體代碼

結(jié)束語


前言

(1)圖像分割

? ? ? ? 圖像分割是 AI 領(lǐng)域中一個重要的分支,是機器視覺技術(shù)中的關(guān)于圖像理解的重要一環(huán)。近幾年興起的自動駕駛技術(shù)中,也需要用到這種技術(shù)。車載攝像頭探查到圖像,后臺計算機可以自動將圖像分割歸類,以避讓行人和車輛等障礙。

(2)讀取圖像信息

無需多言,直接讀取圖像信息:

""" Author:XiaoMa date:2021/11/2 """ import cv2 import numpy as np import matplotlib.pyplot as pltimg0 = cv2.imread("E:\From Zhihu\For the desk\cvtwelve3.jpg") img1 = cv2.resize(img0, dsize = None, fx = 0.5, fy = 0.5) img2 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) h, w = img1.shape[:2] print(h, w) cv2.namedWindow("W0") cv2.imshow("W0", img2) cv2.waitKey(delay = 0)

得到圖像信息如下:

540 960

1. 基于閾值的圖像分割

(1)基本概念

? ? ? ?根據(jù)圖像的整體或部分信息選擇閾值,把圖像依據(jù)灰度級別劃分,前面說過的圖像二值化就是一種基于閾值的圖像分割,當像素點的灰度值高于閾值時將其設(shè)置為1,低于閾值時將其設(shè)置為0,通過這種方法達到將感興趣的圖像和背景進行分離的操作,所以說如何選取合適的閾值對于這種方法來說比較重要,如果背景和圖像亮度區(qū)別較大我們可以使用全局閾值分割,但是背景和圖像亮度區(qū)別不大時得使用局部閾值分割

(2)二值化操作

a. 函數(shù)

ret,dst = cv2.threshold(src,thresh,maxval,type)

res:分割閾值

dst:分割后圖像

scr:輸入的原圖

thresh:分割時的像素分界點值(和閾值等值)

maxval:給大于閾值的像素點安排的灰度值(如定為240,那么大于閾值的點都置為240

type:閾值的類型,包括四種不同的閾值類型

OpenCV 提供的幾種閾值類型:

cv2.THRESH_BINARY? ? ? ? ? ?#小于閾值的像素點置0,大于閾值的像素點置maxval;?
cv2.THRESH_BINARY_INV?? #小于閾值的像素點置maxval,大于閾值的像素點置0;
cv2.THRESH_TRUNC? ? ? ? ? ? # 小于閾值的像素點保持原數(shù)值,大于閾值的像素點置閾值;?
cv2.THRESH_TOZERO? ? ? ? ? # 小于閾值的像素點置0,大于閾值的像素點保持原數(shù)值;?
cv2.THRESH_TOZERO_INV? #小于閾值的像素點保持原數(shù)值,大于閾值的像素點置0。??

b. 代碼實現(xiàn)

本文中將閾值都設(shè)置為 127 ,對不同的閾值類型都進行嘗試:

將下面的代碼復制過去改一下圖像的讀取路徑就可以直接運行了,重要的地方都添加了注釋,應(yīng)該可以看懂。

""" Author:XiaoMa date:2021/11/2 """ import cv2 import numpy as np import matplotlib.pyplot as pltimg0 = cv2.imread("E:\From Zhihu\For the desk\cvtwelve0.jpg") img1 = cv2.resize(img0, dsize = None, fx = 0.5, fy = 0.5) img2 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) h, w = img1.shape[:2] print(h, w) cv2.namedWindow("W0") cv2.imshow("W0", img2) cv2.waitKey(delay = 0) #圖像進行二值化 ##第一種閾值類型 ret0, img3 = cv2.threshold(img2, 127, 255, cv2.THRESH_BINARY) print(ret0) ##第二種閾值類型 ret1, img4 = cv2.threshold(img2, 127, 255, cv2.THRESH_BINARY_INV) print(ret1) ##第三種閾值類型 ret2, img5 = cv2.threshold(img2, 127, 255, cv2.THRESH_TRUNC) print(ret2) ##第四種閾值類型 ret3, img6 = cv2.threshold(img2, 127, 255, cv2.THRESH_TOZERO) print(ret3) ##第五種閾值類型 ret4, img7 = cv2.threshold(img2, 127, 255, cv2.THRESH_TOZERO) print(ret4) #將所有閾值類型得到的圖像繪制到同一張圖中 plt.rcParams['font.family'] = 'SimHei' #將全局中文字體改為黑體 figure = [img2, img3, img4, img5, img6, img7] title = ["原圖", "第一種閾值類型", "第二種閾值類型", "第三種閾值類型", "第四種閾值類型", "第五種閾值類型"] for i in range(6):figure[i] = cv2.cvtColor(figure[i], cv2.COLOR_BGR2RGB) #轉(zhuǎn)化圖像通道順序,這一個步驟要記得plt.subplot(3, 2, i+1)plt.imshow(figure[i])plt.title(title[i]) #添加標題 plt.savefig("E:\From Zhihu\For the desk\cvtwelven.jpg") #保存圖像,如果不想保存也可刪去這一行 plt.show()

??

2. 基于邊緣檢測的圖像分割

這一部分在我前面的文章種已經(jīng)介紹過了:Python 計算機視覺(十)—— OpenCV 圖像銳化及邊緣檢測

這里我們就拿其中的一個算子簡單試一下:

#邊緣檢測之Sobel 算子 img8 = cv2.Sobel (img2, cv2.CV_64F, 0, 1, ksize=5) cv2.namedWindow("W1") cv2.imshow("W1", img8) cv2.waitKey(delay = 0)

得到的結(jié)果如下:

3. 基于 K-Means 聚類的區(qū)域分割

(1)基本概念

此處參考:《K-Means聚類算法研究綜述_楊俊闖》

? ? ? ? K-Means算法是一種無監(jiān)督學習,同時也是基于劃分的聚類算法,一般用歐式距離(兩點間的直線距離)作為衡量數(shù)據(jù)對象間相似度的指標,相似度與數(shù)據(jù)對象間的距離成反比,相似度越大,距離越小。算法需要預先指定初始聚類數(shù)目k (需要分割的份數(shù))以及 k 個初始聚類中心,根據(jù)數(shù)據(jù)對象與聚類中心之間的相似度,不斷更新聚類中心的位置,不斷降低類簇的誤差平方和(Sum of Squared Error,SSE),當SSE不再變化或目標函數(shù)收斂時,聚類結(jié)束,得到最終結(jié)果。

對于該算法的理解,也可以參考 OpenCV 官網(wǎng)給出的解釋:K-means聚類

(2)代碼實現(xiàn)

此處參考:OpenCV 官網(wǎng)

#K-means均值聚類 Z = img1.reshape((-1, 3)) Z = np.float32(Z) #轉(zhuǎn)化數(shù)據(jù)類型 c = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0) k = 4 #聚類中心個數(shù),一般來說也代表聚類后的圖像中的顏色的種類 ret, label, center = cv2.kmeans(Z, k, None, c, 10, cv2.KMEANS_RANDOM_CENTERS) center = np.uint8(center) res = center[label.flatten()] img9 = res.reshape((img1.shape)) cv2.namedWindow("W2") cv2.imshow("W2", img9) cv2.waitKey(delay = 0)

4. 基于分水嶺算法的圖像分割

(1)基本概念

此處參考:IMAGE SEGMENTATION AND MATHEMATICAL MORPHOLOGY

? ? ? ?任何灰度圖像都可以視為地形表面,其中高強度表示山峰和丘陵,而低強度表示山谷。你開始用不同顏色的水(標簽)填充每個孤立的山谷(局部最小值)。隨著水位上升,以附近的山峰(梯度)作為基礎(chǔ),來自不同山谷的水,明顯不同顏色的水會開始融合。為了避免這種情況,你可以在水匯合的位置建立障礙。你繼續(xù)填水和建造屏障,直到所有的山峰都在水下。然后你創(chuàng)建的障礙為你提供了分割結(jié)果。這就是分水嶺背后的“哲學”。

? ? ? ? 但如果圖像中噪聲比較多,那么就會出現(xiàn)很多的“山谷”,這樣就分割出太多的區(qū)域,所以我們在進行分水嶺操作時,一般也會對圖像進行一下平滑處理或者形態(tài)學操作,來使得圖像上的噪聲點減少,使得分割效果更加明顯。圖像平滑和形態(tài)學的部分我在前面的文章中提到過:Python 計算機視覺(九)—— OpenCV進行圖像平滑

Python 計算機視覺(十一)—— OpenCV 圖像形態(tài)學處理

(2)代碼實現(xiàn)

此處參考:分水嶺算法的圖像分割(官網(wǎng))

#分水嶺算法 ret1, img10 = cv2.threshold(img2, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)#(圖像閾值分割,將背景設(shè)為黑色) cv2.namedWindow("W3") cv2.imshow("W3", img10) cv2.waitKey(delay = 0) ##noise removal(去除噪聲,使用圖像形態(tài)學的開操作,先腐蝕后膨脹) kernel = np.ones((3, 3), np.uint8) opening = cv2.morphologyEx(img10, cv2.MORPH_OPEN, kernel, iterations = 2) # sure background area(確定背景圖像,使用膨脹操作) sure_bg = cv2.dilate(opening, kernel, iterations=3) # Finding sure foreground area(確定前景圖像,也就是目標) dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5) ret2, sure_fg = cv2.threshold(dist_transform, 0.7*dist_transform.max(), 255, 0) # Finding unknown region(找到未知的區(qū)域) sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(sure_bg, sure_fg) # Marker labelling ret3, markers = cv2.connectedComponents(sure_fg) #用0標記所有背景像素點 # Add one to all labels so that sure background is not 0, but 1(將背景設(shè)為1) markers = markers+1 ##Now, mark the region of unknown with zero(將未知區(qū)域設(shè)為0) markers[unknown == 255] = 0 markers = cv2.watershed(img1, markers) #進行分水嶺操作 img1[markers == -1] = [0, 0, 255] #邊界區(qū)域設(shè)為-1,顏色設(shè)置為紅色 cv2.namedWindow("W4") cv2.imshow("W4", img1) cv2.waitKey(delay = 0)

? ? ? 效果并不是很理想,建議大家找一些亮度相差較大而且梯度明顯但種類不多的圖像進行試驗操作。

5.整體代碼

我將本篇文章中的代碼貼在下面,大家可以直接復制進行試驗,改一下圖像的讀取路徑就可以使用了:

""" Author:XiaoMa date:2021/11/2 """ import cv2 import numpy as np import matplotlib.pyplot as pltimg0 = cv2.imread("E:\From Zhihu\For the desk\cvtwelve0.jpg") img1 = cv2.resize(img0, dsize = None, fx = 0.5, fy = 0.5) img2 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) h, w = img1.shape[:2] print(h, w) cv2.namedWindow("W0") cv2.imshow("W0", img1) cv2.waitKey(delay = 0) #圖像進行二值化 ##第一種閾值類型 ret0, img3 = cv2.threshold(img2, 127, 255, cv2.THRESH_BINARY) print(ret0) ##第二種閾值類型 ret1, img4 = cv2.threshold(img2, 127, 255, cv2.THRESH_BINARY_INV) print(ret1) ##第三種閾值類型 ret2, img5 = cv2.threshold(img2, 127, 255, cv2.THRESH_TRUNC) print(ret2) ##第四種閾值類型 ret3, img6 = cv2.threshold(img2, 127, 255, cv2.THRESH_TOZERO) print(ret3) ##第五種閾值類型 ret4, img7 = cv2.threshold(img2, 127, 255, cv2.THRESH_TOZERO) print(ret4) #將所有閾值類型得到的圖像繪制到同一張圖中 plt.rcParams['font.family'] = 'SimHei' #將全局中文字體改為黑體 figure = [img2, img3, img4, img5, img6, img7] title = ["原圖", "第一種閾值類型", "第二種閾值類型", "第三種閾值類型", "第四種閾值類型", "第五種閾值類型"] for i in range(6):figure[i] = cv2.cvtColor(figure[i], cv2.COLOR_BGR2RGB) #轉(zhuǎn)化圖像通道順序,這一個步驟要記得plt.subplot(3, 2, i+1)plt.imshow(figure[i])plt.title(title[i]) #添加標題 plt.savefig("E:\From Zhihu\For the desk\cvtwelven.jpg") #保存圖像,如果不想保存也可刪去這一行 plt.show() #邊緣檢測之Sobel 算子 img8 = cv2.Sobel(img2, cv2.CV_64F, 0, 1, ksize = 5) cv2.namedWindow("W1") cv2.imshow("W1", img8) cv2.waitKey(delay = 0) #K-means均值聚類 Z = img1.reshape((-1, 3)) Z = np.float32(Z) #轉(zhuǎn)化數(shù)據(jù)類型 c = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0) k = 4 ret, label, center = cv2.kmeans(Z, k, None, c, 10, cv2.KMEANS_RANDOM_CENTERS) center = np.uint8(center) res = center[label.flatten()] img9 = res.reshape((img1.shape)) cv2.namedWindow("W2") cv2.imshow("W2", img9) cv2.waitKey(delay = 0)#分水嶺算法 ret1, img10 = cv2.threshold(img2, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)#(圖像閾值分割,將背景設(shè)為黑色) cv2.namedWindow("W3") cv2.imshow("W3", img10) cv2.waitKey(delay = 0) ##noise removal(去除噪聲,使用圖像形態(tài)學的開操作,先腐蝕后膨脹) kernel = np.ones((3, 3), np.uint8) opening = cv2.morphologyEx(img10, cv2.MORPH_OPEN, kernel, iterations = 2) # sure background area(確定背景圖像,使用膨脹操作) sure_bg = cv2.dilate(opening, kernel, iterations=3) # Finding sure foreground area(確定前景圖像,也就是目標) dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5) ret2, sure_fg = cv2.threshold(dist_transform, 0.7*dist_transform.max(), 255, 0) # Finding unknown region(找到未知的區(qū)域) sure_fg = np.uint8(sure_fg) unknown = cv2.subtract(sure_bg, sure_fg) # Marker labelling ret3, markers = cv2.connectedComponents(sure_fg) #用0標記所有背景像素點 # Add one to all labels so that sure background is not 0, but 1(將背景設(shè)為1) markers = markers+1 ##Now, mark the region of unknown with zero(將未知區(qū)域設(shè)為0) markers[unknown == 255] = 0 markers = cv2.watershed(img1, markers) #進行分水嶺操作 img1[markers == -1] = [0, 0, 255] #邊界區(qū)域設(shè)為-1,顏色設(shè)置為紅色 cv2.namedWindow("W4") cv2.imshow("W4", img1) cv2.waitKey(delay = 0)

結(jié)束語

? ? ? ?本文介紹了使用 OpenCV 進行圖像分割的幾種常用手段,包括閾值分割、邊緣分割、K均值聚類分割以及分水嶺分割。當然還有一些其他的比如均值漂移、基于紋理分割、文本分割、水漫分割等手段并沒有在本文中提到,小伙伴們感興趣可以去進行了解學習。

總結(jié)

以上是生活随笔為你收集整理的Python 计算机视觉(十二)—— OpenCV 进行图像分割的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。