opencv进阶学习笔记14:分水岭算法 实现图像分割
基礎版學習筆記目錄:
python3+opencv學習筆記匯總目錄(適合基礎入門學習)
進階版筆記目錄鏈接:
python+opencv進階版學習筆記目錄(適合有一定基礎)
分水嶺算法原理
分水嶺算法是一種圖像區(qū)域分割法,在分割的過程中,它會把跟臨近像素間的相似性作為重要的參考依據,從而將在空間位置上相近并且灰度值相近的像素點互相連接起來構成一個封閉的輪廓,封閉性是分水嶺算法的一個重要特征。
其他圖像分割方法,如閾值,邊緣檢測等都不會考慮像素在空間關系上的相似性和封閉性這一概念,彼此像素間互相獨立,沒有統(tǒng)一性。分水嶺算法較其他分割方法更具有思想性,更符合人眼對圖像的印象。
任意的灰度圖像可以被看做是地質學表面,高亮度的地方是山峰,低亮度的地方是山谷。給每個孤立的山谷(局部最小值)不同顏色的水(標簽),當水漲起來,根據周圍的山峰(梯度),不同的山谷也就是不同的顏色會開始合并,要避免這個,你可以在水要合并的地方建立障礙,直到所有山峰都被淹沒。你所創(chuàng)建的障礙就是分割結果,這個就是分水嶺的原理,但是這個方法會分割過度,因為有噪點,或者其他圖像上的錯誤。所以OpenCV實現(xiàn)了一個基于掩模的分水嶺算法,你可以指定哪些是要合并的點,哪些不是,這是一個交互式的圖像分割,我們要做的是給不同的標簽。給我們知道是前景或者是目標用一種顏色加上標簽,給我們知道是背景或者非目標加上另一個顏色,最后不知道是什么的區(qū)域標記為0. 然后使用分水嶺算法。
距離變換
先將圖像進行距離變換使出現(xiàn)山峰和山谷
API實現(xiàn)
1圖像二值化
import cv2 as cv import numpy as npdef watershed_demo():# remove noise if anyprint(src.shape)#圖像維度(348, 500, 3)blurred = cv.pyrMeanShiftFiltering(src, 10, 100)#邊緣保留濾波去噪# gray\binary imagegray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)#轉換為灰度圖ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)#二值化cv.imshow("binary-image", binary) print("--------- Python OpenCV Tutorial ---------") src = cv.imread("coins.jpg") cv.namedWindow("input image", cv.WINDOW_AUTOSIZE) cv.imshow("input image", src) watershed_demo() cv.waitKey(0) cv.destroyAllWindows()2形態(tài)學操作
import cv2 as cv import numpy as npdef watershed_demo():# remove noise if anyprint(src.shape)#圖像維度(348, 500, 3)blurred = cv.pyrMeanShiftFiltering(src, 10, 100)#均值偏移濾波去噪# gray\binary imagegray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)#轉換為灰度圖ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)#二值化#cv.imshow("binary-image", binary)# 形態(tài)學變換kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))#卷積核mb = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel, iterations=2)#開運算sure_bg = cv.dilate(mb, kernel, iterations=3)#對開運算結果膨脹cv.imshow("mor-opt", sure_bg) print("--------- Python OpenCV Tutorial ---------") src = cv.imread("coins.jpg") cv.namedWindow("input image", cv.WINDOW_AUTOSIZE) cv.imshow("input image", src) watershed_demo() cv.waitKey(0) cv.destroyAllWindows()3對開運算結果進行距離變換
先不管膨脹結果,對開運算結果進行距離計算
src:輸入的圖像,一般為二值圖像
distanceType:所用的求解距離的類型(CV_DIST_L1, CV_DIST_L2 , CV_DIST_C)
maskSize:距離變換掩模的大小
我們需要對distanceTransform返回的結果進行歸一化處理,使用normalize
import cv2 as cv import numpy as npdef watershed_demo():# remove noise if anyprint(src.shape)#圖像維度(348, 500, 3)blurred = cv.pyrMeanShiftFiltering(src, 10, 100)#均值偏移濾波去噪# gray\binary imagegray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)#轉換為灰度圖ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)#二值化#cv.imshow("binary-image", binary)# m形態(tài)學操作kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))#卷積核mb = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel, iterations=2)#開運算sure_bg = cv.dilate(mb, kernel, iterations=3)#對開運算結果膨脹#cv.imshow("mor-opt", sure_bg)# 對開運算結果距離變換dist = cv.distanceTransform(mb, cv.DIST_L2, 3)dist_output = cv.normalize(dist, 0, 1.0, cv.NORM_MINMAX)cv.imshow("distance-t", dist_output * 50)print("--------- Python OpenCV Tutorial ---------") src = cv.imread("coins.jpg") cv.namedWindow("input image", cv.WINDOW_AUTOSIZE) cv.imshow("input image", src) watershed_demo() cv.waitKey(0)cv.destroyAllWindows()4生成種子
import cv2 as cv import numpy as npdef watershed_demo():# remove noise if anyprint(src.shape)#圖像維度(348, 500, 3)blurred = cv.pyrMeanShiftFiltering(src, 10, 100)#均值偏移濾波去噪# gray\binary imagegray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)#轉換為灰度圖ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)#二值化#cv.imshow("binary-image", binary)# m形態(tài)學操作kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))#卷積核mb = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel, iterations=2)#開運算sure_bg = cv.dilate(mb, kernel, iterations=3)#對開運算結果膨脹#cv.imshow("mor-opt", sure_bg)# 對開運算結果距離變換dist = cv.distanceTransform(mb, cv.DIST_L2, 3)dist_output = cv.normalize(dist, 0, 1.0, cv.NORM_MINMAX)#cv.imshow("distance-t", dist_output * 50)ret, surface = cv.threshold(dist, dist.max()*0.6, 255, cv.THRESH_BINARY)surface_fg = np.uint8(surface)cv.imshow("surface-bin", surface_fg)#種子print("--------- Python OpenCV Tutorial ---------") src = cv.imread("coins.jpg") cv.namedWindow("input image", cv.WINDOW_AUTOSIZE) cv.imshow("input image", src) watershed_demo() cv.waitKey(0) cv.destroyAllWindows()5生成marker和分水嶺變換
import cv2 as cv import numpy as npdef watershed_demo():# remove noise if anyprint(src.shape)#圖像維度(348, 500, 3)blurred = cv.pyrMeanShiftFiltering(src, 10, 100)#均值偏移濾波去噪# gray\binary imagegray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)#轉換為灰度圖ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)#二值化#cv.imshow("binary-image", binary)# m形態(tài)學操作kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))#卷積核mb = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel, iterations=2)#開運算sure_bg = cv.dilate(mb, kernel, iterations=3)#對開運算結果膨脹#cv.imshow("mor-opt", sure_bg)# 對開運算結果距離變換dist = cv.distanceTransform(mb, cv.DIST_L2, 3)dist_output = cv.normalize(dist, 0, 1.0, cv.NORM_MINMAX)#cv.imshow("distance-t", dist_output * 50)ret, surface = cv.threshold(dist, dist.max()*0.6, 255, cv.THRESH_BINARY)surface_fg = np.uint8(surface)#cv.imshow("surface-bin", surface_fg)#種子unknown = cv.subtract(sure_bg, surface_fg)#種子區(qū)域除外的區(qū)域=膨脹結果-種子ret, markers = cv.connectedComponents(surface_fg)#聯(lián)通區(qū)域# 分水嶺變換markers = markers + 1markers[unknown == 255] = 0markers = cv.watershed(src, markers=markers)src[markers == -1] = [0, 0, 255]cv.imshow("result", src) print("--------- Python OpenCV Tutorial ---------") src = cv.imread("coins.jpg") cv.namedWindow("input image", cv.WINDOW_AUTOSIZE) cv.imshow("input image", src) watershed_demo() cv.waitKey(0) cv.destroyAllWindows()最后結果
電氣專業(yè)的計算機萌新,寫博文不容易。如果你覺得本文對你有用,請點個贊支持下,謝謝。
總結
以上是生活随笔為你收集整理的opencv进阶学习笔记14:分水岭算法 实现图像分割的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何在家中制作自己喜欢的汉堡?
- 下一篇: 36篇博文带你学完opencv :pyt