Python經(jīng)典案例之圖像漫水填充分割詳解
一.圖像漫水填充
圖像漫水填充(FloodFill)是指用一種特定的顏色填充聯(lián)通區(qū)域,通過(guò)設(shè)置可連通像素的上下限以及連通方式來(lái)達(dá)到不同的填充效果。漫水填充通常被用來(lái)標(biāo)記或分離圖像的一部分以便對(duì)其進(jìn)行深入的處理或分析。
圖像漫水填充主要是遴選出與種子點(diǎn)聯(lián)通且顏色相近的像素點(diǎn),接著對(duì)像素點(diǎn)的值進(jìn)行處理。如果遇到掩碼,則根據(jù)掩碼進(jìn)行處理。其原理類似Photoshop的魔術(shù)棒選擇工具,漫水填充將查找和種子點(diǎn)聯(lián)通的顏色相同的點(diǎn),而魔術(shù)棒選擇工具是查找和種子點(diǎn)聯(lián)通的顏色相近的點(diǎn),將和初始種子像素顏色相近的點(diǎn)壓進(jìn)棧作為新種子?;竟ぷ鞑襟E如下:
- 選定種子點(diǎn)(x,y);
- 檢查種子點(diǎn)的顏色,如果該點(diǎn)顏色與周圍連接點(diǎn)的顏色不相同,則將周圍點(diǎn)顏色設(shè)置為該點(diǎn)顏色;如果相同則不做處理。但是周圍點(diǎn)不一定都會(huì)變成和種子點(diǎn)的顏色相同,如果周圍連接點(diǎn)在給定的范圍(從loDiff到upDiff)內(nèi)或在種子點(diǎn)的像素范圍內(nèi)才會(huì)改變顏色;
- 檢測(cè)其他連接點(diǎn),進(jìn)行第2個(gè)步驟的處理,直到?jīng)]有連接點(diǎn),即到達(dá)檢測(cè)區(qū)域邊界停止。
二.圖像漫水填充分割實(shí)現(xiàn)
在OpenCV中,主要通過(guò)floodFill()函數(shù)實(shí)現(xiàn)漫水填充分割,它將用指定的顏色從種子點(diǎn)開(kāi)始填充一個(gè)連接域。其函數(shù)原型如下所示:
floodFill(image, mask, seedPoint, newVal[, loDiff[, upDiff[, flags]]])
– image表示輸入/輸出1通道或3通道,6位或浮點(diǎn)圖像
– mask表示操作掩碼,必須為8位單通道圖像,其長(zhǎng)寬都比輸入圖像大兩個(gè)像素點(diǎn)。注意,漫水填充不會(huì)填充掩膜mask的非零像素區(qū)域,mask中與輸入圖像(x,y)像素點(diǎn)相對(duì)應(yīng)的點(diǎn)的坐標(biāo)為(x+1,y+1)。
– seedPoint為Point類型,表示漫水填充算法的起始點(diǎn)
– newVal表示像素點(diǎn)被染色的值,即在重繪區(qū)域像素的新值
– loDiff表示當(dāng)前觀察像素值與其部件鄰域像素值或待加入該部件的種子像素之間的亮度或顏色之負(fù)差的最大值,默認(rèn)值為Scalar( )
– upDiff表示當(dāng)前觀察像素值與其部件鄰域像素值或待加入該部件的種子像素之間的亮度或顏色之正差的最大值,默認(rèn)值為Scalar( )
– flags表示操作標(biāo)識(shí)符,此參數(shù)包括三個(gè)部分:低八位0-7bit表示鄰接性(4鄰接或8鄰接);中間八位8-15bit表示掩碼的填充顏色,如果中間八位為0則掩碼用1來(lái)填充;高八位16-31bit表示填充模式,可以為0或者以下兩種標(biāo)志符的組合,F(xiàn)LOODFILL_FIXED_RANGE表示此標(biāo)志會(huì)考慮當(dāng)前像素與種子像素之間的差,否則就考慮當(dāng)前像素與相鄰像素的差。FLOODFILL_MASK_ONLY表示函數(shù)不會(huì)去填充改變?cè)紙D像,而是去填充掩碼圖像mask,mask指定的位置為零時(shí)才填充,不為零不填充。
在Python和OpenCV實(shí)現(xiàn)代碼中,它設(shè)置種子點(diǎn)位置為(10,200);設(shè)置顏色為黃色(0,255,255);連通區(qū)范圍設(shè)定為loDiff和upDiff;標(biāo)記參數(shù)設(shè)置為CV_FLOODFILL_FIXED_RANGE ,它表示待處理的像素點(diǎn)與種子點(diǎn)作比較,在范圍之內(nèi),則填充此像素,即種子漫水填充滿足:
src(seed.x, seed.y) - loDiff <= src(x, y) <= src(seed.x, seed.y) +upDiff
完整代碼如下:
# -*- coding: utf-8 -*-
# By: Eastmount
import cv2
import numpy as np
#讀取原始圖像
img = cv2.imread('windows.png')
#獲取圖像行和列
rows, cols = img.shape[:2]
#目標(biāo)圖像
dst = img.copy()
#mask必須行和列都加2且必須為uint8單通道陣列
#mask多出來(lái)的2可以保證掃描的邊界上的像素都會(huì)被處理
mask = np.zeros([rows+2, cols+2], np.uint8)
#圖像漫水填充處理
#種子點(diǎn)位置(30,30) 設(shè)置顏色(0,255,255) 連通區(qū)范圍設(shè)定loDiff upDiff
#src(seed.x, seed.y) - loDiff <= src(x, y) <= src(seed.x, seed.y) +upDiff
cv2.floodFill(dst, mask, (30, 30), (0, 255, 255),
(100, 100, 100), (50, 50, 50),
cv2.FLOODFILL_FIXED_RANGE)
#顯示圖像
cv2.imshow('src', img)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()
輸出結(jié)果如圖1所示,左邊為原始圖像,右邊為將Windows圖標(biāo)周圍填充為黃色的圖像。

三.圖像漫水填充分割自動(dòng)軟件
下面補(bǔ)充另一段代碼,它將打開(kāi)一幅圖像,點(diǎn)擊鼠標(biāo)選擇種子節(jié)點(diǎn),移動(dòng)滾動(dòng)條設(shè)定連通區(qū)范圍的loDiff和upDiff值,并產(chǎn)生動(dòng)態(tài)的漫水填充分割。
注意,該部分代碼中涉及鼠標(biāo)、鍵盤(pán)、滾動(dòng)條等操作,希望讀者下來(lái)學(xué)習(xí)相關(guān)知識(shí),該系列文章更多是講解Python圖像處理的算法原理及代碼實(shí)現(xiàn)。
# coding:utf-8
import cv2
import random
import sys
import numpy as np
#使用說(shuō)明 點(diǎn)擊鼠標(biāo)選擇種子點(diǎn)
help_message = '''USAGE: floodfill.py [<image>]
Click on the image to set seed point
Keys:
f - toggle floating range
c - toggle 4/8 connectivity
ESC - exit
'''
if __name__ == '__main__':
#輸出提示文本
print(help_message)
#讀取原始圖像
img = cv2.imread('scenery.png')
#獲取圖像高和寬
h, w = img.shape[:2]
#設(shè)置掩碼 長(zhǎng)和寬都比輸入圖像多兩個(gè)像素點(diǎn)
mask = np.zeros((h+2, w+2), np.uint8)
#設(shè)置種子節(jié)點(diǎn)和4鄰接
seed_pt = None
fixed_range = True
connectivity = 4
#圖像漫水填充分割更新函數(shù)
def update(dummy=None):
if seed_pt is None:
cv2.imshow('floodfill', img)
return
#建立圖像副本并漫水填充
flooded = img.copy()
mask[:] = 0 #掩碼初始為全0
lo = cv2.getTrackbarPos('lo', 'floodfill') #像素鄰域負(fù)差最大值
hi = cv2.getTrackbarPos('hi', 'floodfill') #像素鄰域正差最大值
print('lo=', lo, 'hi=', hi)
#低位比特包含連通值 4 (缺省) 或 8
flags = connectivity
#考慮當(dāng)前像素與種子像素之間的差(高比特也可以為0)
if fixed_range:
flags |= cv2.FLOODFILL_FIXED_RANGE
#以白色進(jìn)行漫水填充
cv2.floodFill(flooded, mask, seed_pt,
(random.randint(0,255), random.randint(0,255),
random.randint(0,255)), (lo,)*3, (hi,)*3, flags)
#選定基準(zhǔn)點(diǎn)用紅色圓點(diǎn)標(biāo)出
cv2.circle(flooded, seed_pt, 2, (0, 0, 255), -1)
print("send_pt=", seed_pt)
#顯示圖像
cv2.imshow('floodfill', flooded)
#鼠標(biāo)響應(yīng)函數(shù)
def onmouse(event, x, y, flags, param):
global seed_pt #基準(zhǔn)點(diǎn)
#鼠標(biāo)左鍵響應(yīng)選擇漫水填充基準(zhǔn)點(diǎn)
if flags & cv2.EVENT_FLAG_LBUTTON:
seed_pt = x, y
update()
#執(zhí)行圖像漫水填充分割更新操作
update()
#鼠標(biāo)更新操作
cv2.setMouseCallback('floodfill', onmouse)
#設(shè)置進(jìn)度條
cv2.createTrackbar('lo', 'floodfill', 20, 255, update)
cv2.createTrackbar('hi', 'floodfill', 20, 255, update)
#按鍵響應(yīng)操作
while True:
ch = 0xFF & cv2.waitKey()
#退出
if ch == 27:
break
#選定時(shí)flags的高位比特位0
#鄰域的選定為當(dāng)前像素與相鄰像素的差, 聯(lián)通區(qū)域會(huì)很大
if ch == ord('f'):
fixed_range = not fixed_range
print('using %s range' % ('floating', 'fixed')[fixed_range])
update()
#選擇4方向或則8方向種子擴(kuò)散
if ch == ord('c'):
connectivity = 12-connectivity
print('connectivity =', connectivity)
update()
cv2.destroyAllWindows()
當(dāng)鼠標(biāo)選定的種子點(diǎn)為(242,96),觀察點(diǎn)像素鄰域負(fù)差最大值“lo”為138,觀察點(diǎn)像素鄰域正差最大值“hi”為147時(shí),圖像漫水填充效果如圖2所示,它將天空和中心水面填充成黃色。

當(dāng)鼠標(biāo)選定的種子點(diǎn)為(328, 202),觀察點(diǎn)像素鄰域負(fù)差最大值“lo”為142,觀察點(diǎn)像素鄰域正差最大值“hi”為45時(shí),圖像漫水填充效果如圖3所示,它將圖像兩旁的森林和水面填充成藍(lán)紫色。

四.總結(jié)
寫(xiě)到這里,圖像分割知識(shí)點(diǎn)就介紹完畢,包括基于閾值的圖像分割方法、基于邊緣檢測(cè)的圖像分割方法、基于紋理背景的圖像分割方法和基于特定理論的圖像分割方法。其中,基于特定理論的分割方法又分別講解了基于K-Means聚類、均值漂移、分水嶺算法的圖像分割方法。最后通過(guò)漫水填充分割案例加深了讀者的印象。希望讀者能結(jié)合本章知識(shí)點(diǎn),圍繞自己的研究領(lǐng)域或工程項(xiàng)目進(jìn)行深入的學(xué)習(xí),實(shí)現(xiàn)所需的圖像處理。
以上就是Python經(jīng)典案例之圖像漫水填充分割詳解的詳細(xì)內(nèi)容,更多關(guān)于Python圖像漫水填充分割的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Keras設(shè)定GPU使用內(nèi)存大小方式(Tensorflow backend)
這篇文章主要介紹了Keras設(shè)定GPU使用內(nèi)存大小方式(Tensorflow backend),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05
python spilt()分隔字符串的實(shí)現(xiàn)示例
split() 方法可以實(shí)現(xiàn)將一個(gè)字符串按照指定的分隔符切分成多個(gè)子串,本文介紹了spilt的具體使用,感興趣的可以了解一下2021-05-05
matlab和Excel的數(shù)據(jù)交互操作(非xlsread和xlswrite)
在使用MATLAB時(shí),可能會(huì)遇到很多表格數(shù)據(jù)的處理,有時(shí)MATLAB也需要利用現(xiàn)存的表格數(shù)據(jù)實(shí)現(xiàn)操作目的,下面這篇文章主要給大家介紹了關(guān)于matlab和Excel的交互操作的相關(guān)資料,非xlsread和xlswrite,需要的朋友可以參考下2021-08-08
Python操作mongodb數(shù)據(jù)庫(kù)進(jìn)行模糊查詢操作示例
這篇文章主要介紹了Python操作mongodb數(shù)據(jù)庫(kù)進(jìn)行模糊查詢操作,結(jié)合實(shí)例形式分析了Python連接MongoDB數(shù)據(jù)庫(kù)及使用正則表達(dá)式進(jìn)行模糊查詢的相關(guān)操作技巧,需要的朋友可以參考下2018-06-06
Python字符串特性及常用字符串方法的簡(jiǎn)單筆記
這篇文章主要介紹了Python字符串特性及常見(jiàn)字符串方法的簡(jiǎn)單筆記,為一些Pyhton入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2016-01-01
15個(gè)Python運(yùn)行速度優(yōu)化技巧分享
這篇文章主要為大家詳細(xì)介紹了15個(gè)Python運(yùn)行速度優(yōu)化技巧,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考一下2025-02-02
Django使用redis緩存服務(wù)器的實(shí)現(xiàn)代碼示例
這篇文章主要介紹了Django使用redis緩存服務(wù)器的實(shí)現(xiàn)代碼示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
Python格式化字符串f-string概覽(小結(jié))
這篇文章主要介紹了Python格式化字符串f-string概覽(小結(jié)),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06

