是否有一種方法可以在OpenCV中執行一個類似于侵蝕的程序,如果任何的鄰居不為零,而不是要求所有的鄰居都不為零,則保留一個特定的像素?
在這里,我所說的鄰居是指任何具有abs(x1-x2) abs(y1-y2)==1的像素,但這很容易通過侵蝕內核進行控制。
當然,我總是可以使用for回圈并從頭開始實作這種行為,但我更喜歡OpenCV的庫所能提供的速度。
反轉影像,執行侵蝕,然后再反轉,這樣做可行嗎?
我的另一個想法是用一個中心為空的內核來進行卷積,然后將所有的值剪切到0到1的范圍內。我將使用scipy.ndimage.convolve來實作這一點。
我正在處理一個二進制的NumPy陣列,型別為np.float32(即0.0或1.0的值),形狀為(512,512)。
uj5u.com熱心網友回復:
實作你的目標的一個簡單方法是用一個正方形的3x3的1的核進行卷積。對于每個像素,你現在知道在其附近有多少個前景像素(包括它自己)。閾值為2(>=2),以獲得附近至少有兩個前景像素的所有像素。最后,與原始影像的邏輯和將得到所有至少有一個前景鄰居的前景像素。
這里有一個例子:
import scipy.ndimage
import numpy as np
img = np.array([[0., 0., 0., 0., 0. , 0., 0., 1., 1., 1.] 。
[0., 1., 0., 0., 0. , 0., 0., 1., 1., 1.] 。
[0., 0., 0., 0., 0. , 0., 0., 1., 1.] 。
[0., 0., 0., 0., 0. , 0., 1., 0., 1., 1.] 。
[0., 0., 0., 0., 0. , 0., 1., 0., 0., 0.] 。
[0., 0., 1., 0., 0. , 0., 0., 0., 0.]。
[0., 1., 1., 0., 0. , 0., 0., 0., 0.]。
[0., 1., 1., 0., 1。 , 0., 0., 0., 0.],
[0., 1., 1., 0., 0. , 0., 0., 0., 0.]。
[0., 1., 1., 0., 0. , 0., 0., 0., 0.]。
[0., 1., 1., 0., 0. , 0., 0., 0., 0.]。
[0., 0., 0., 1., 0. , 0., 0., 1., 1., 0.】。]
[0., 0., 0., 1. , 1., 0., 0., 0., 0.] 。
[0., 0., 0., 0., 0. , 0., 0., 0., 0.]。
[0., 0., 0., 0., 0. , 0., 0., 0., 0., 1.】。]
[0., 0., 0., 0., 0. , 0., 0., 1., 0., 0.] ], dtype=np.float32)
tmp = scipy.ndimage.convolve(img, np.ones((3,3), mode='constant')
out = np.logical_and(tmp >= 2, img).astype(np.float32)
輸出結果是:
[[0. 0. 0. 0. 0. 0. 1.]
[0. 0. 0. 0. 0. 0. 0. 1. 1. 1.]
[0. 0. 0. 0. 0. 0. 0. 0. 1. 1.]
[0. 0. 0. 0. 0. 0. 1. 0. 1. 1.]
[0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]
[0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]
[0. 1. 1. 0. 0. 0. 0. 0. 0. 0.]
[0. 1. 1. 0. 0. 0. 0. 0. 0. 0.]
[0. 1. 1. 0. 0. 0. 0. 0. 0. 0.]
[0. 1. 1. 0. 0. 0. 0. 0. 0. 0.]
[0. 1. 1. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 1. 0. 0. 0. 1. 1. 0.]
[0. 0. 0. 0. 1. 1. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]
當然,有些影像庫會有專門為此目的設計的函式。我不知道OpenCV或ndimage或scikit-image是否有這樣的功能,我對這些庫還不夠了解。但是DIPlib有(披露:我是作者之一):
import diplib as dip
out = img - dip.GetSinglePixels(img > 0)
img > 0部分是將浮點陣列轉換成邏輯陣列,這是DIPlib對二進制影像的期望。對于一個512x512的影像來說,這大約是其他解決方案的5倍。
uj5u.com熱心網友回復:
假設你有
src = np.uint8([
[ 0, 0, 0, 0, 0, 0, 0, 0] 。
[0, 0, 0, 0。 0, 0, 0, 0] 。
[0, 0, 255, 0, 0, 0, 0, 0] 。
[0, 0, 0, 0。 0, 0, 0, 0] 。
[0, 0, 0, 0。 0, 0, 0, 0] 。
[0, 0, 0, 0。 0, 255, 0, 0] 。
[0, 0, 0, 0。 0, 0, 255, 0] 。
[0, 0, 0, 0。 0, 0, 0, 0] ])
(你可以想辦法從你的floats中得到這個結果)
你正在尋找非零像素,其中不是所有的鄰居都是0。你可以從幾個操作中構建期望的結果。
你可以使用MORPH_HITMISS來獲得正向條件(所有鄰居為0),然后與否定條件相結合。
你會使用這個內核:
kernel = np.int8([ # 0表示 "不在乎",其他的都要匹配。
[-1, -1, -1] 。
[-1, 1, -1] 。
[-1, -1, -1] 。
])
neighbors_all_zero = cv.morphologyEx(src=src, op=cv.MORPH_HITMISS, kernel=kernel)
結果 = src & ~neighbors_all_zero
結果:
array([[ 0, 0, 0, 0, 0, 0, 0]。
[0, 0, 0, 0。 0, 0, 0, 0] 。
[0, 0, 0, 0。 0, 0, 0, 0] 。
[0, 0, 0, 0。 0, 0, 0, 0] 。
[0, 0, 0, 0。 0, 0, 0, 0] 。
[0, 0, 0, 0。 0, 255, 0, 0] 。
[0, 0, 0, 0。 0, 0, 255, 0] 。
[0, 0, 0, 0。 0, 0, 0, 0]] ,dtype=uint8)
要注意這些值本身。OpenCV有時假定掩碼為0或255,而在其他時候則假定為0和非零。當我只使用0和1而不是0和255時,我得到了一些有趣的結果。我相信這些都是可以解決的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/320328.html
標籤:
上一篇:PythonTypeError:'bytes'物件不能被解釋為整數。如何添加'byte'?
下一篇:邊緣檢測最小線長?
