提问者:小点点

如何使用opencv和python在灰度图像上应用分水岭?


根据我在如何在OpenCV中定义分水岭的标记?中阅读的解决方案,我正在尝试将分水岭应用于从netcdf(降水数据)提取的灰度数据(不是很明显,但不是全部黑色)。

这是一个黑白版本的数据(阈值为0),这样你可以更容易地看到,以及我想用来定义不同盆地的标记(基本上只是另一个降水更强烈的阈值)。

我正在运行的代码如下:

import os,sys,string
from netCDF4 import Dataset as nc
import cv2
import numpy as np
import matplotlib.pyplot as mpl
import scipy.ndimage as ndimage
import scipy.spatial as spatial
from skimage import filter
from skimage.morphology import watershed
from scipy import ndimage

filename=["Cmorph-1999_01_03.nc"]

nc_data=nc(filename[0])
data=nc_data.variables["CMORPH"][23,0:250,250:750]
new_data=np.flipud(data)
ma_data=np.ma.masked_where(new_data<=0,new_data)
ma_conv=np.ma.masked_where(new_data<=2,new_data)

## Borders
tmp_data=ma_data.filled(0)
tmp_data[np.where(tmp_data!=0)]=255
bw_data=tmp_data.astype(np.uint8)
border = cv2.dilate(bw_data, None, iterations=5)
border = border - cv2.erode(border, None)

## Markers
tmp_conv=ma_conv.filled(0)
tmp_conv[np.where(tmp_conv!=0)]=255
bw_conv=tmp_conv.astype(np.uint8)
lbl, ncc = ndimage.label(bw_conv)
lbl = lbl * (255/ncc)
lbl[border == 255] = 255
lbl = lbl.astype(np.int32)

## Apply watershed
cv2.watershed(ma_data, lbl)

lbl[lbl == -1] = 0
lbl = lbl.astype(np.uint8)
result = 255 - lbl

我有以下错误的分水岭在opencv-2.4.11/模块/imgproc/src/分段. cpp:

error: (-210) Only 8-bit, 3-channel input images are supported in function cvWatershed

对于我在网上看到的,这是由于灰度数据是2D图像,分水岭需要3D图像(来自RGB)。事实上,我用jpg图像尝试了脚本,我工作得很好。这里提到了这个问题,但给出的答案最终被拒绝了。我找不到任何最近的链接来回答这个问题。

为了解决这个问题,我从2Dnew_data创建了一个3D数组:

new_data = new_data[..., np.newaxis]
test=np.append(new_data, new_data, axis=2)
test=np.append(new_data, test, axis=2)

但是,正如预期的那样,它没有解决问题(相同的错误消息)。

我还试图从matplotlib保存情节以获取RGB数据:

fig = mpl.figure()
fig.add_subplot(111)
fig.tight_layout(pad=0)
mpl.contourf(ma_data,levels=np.arange(0,255.1,0.1))
fig.canvas.draw()
test_data = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='')
test_data = test_data.reshape(fig.canvas.get_width_height()[::-1] + (3,))

但是创建的test_data的大小不同于ma_data(我无法摆脱标签)。

所以,我就卡在这里了,理想情况下,我想直接在2D灰度图像上应用分水岭和/或尽可能限制操作次数。


共2个答案

匿名用户

正如yapws87提到的,我呈现给分水岭函数的格式确实有问题。执行try_data=ma_data. astype(np.uint8)删除了错误消息。

这是一个现在有效的最小示例:

import os,sys
from netCDF4 import Dataset as nc
import cv2
import numpy as np
import scipy.ndimage as ndimage
from skimage.morphology import watershed
from scipy import ndimage

basename="/home/dcop696/Data/CMORPH/precip/CMORPH_V1.0/CRT/8km-30min/1999/"
filename=["Cmorph-1999_01_03.nc"]
fileslm=["/home/dcop696/Data/LSM/Cmorph_slm_8km.nc"]

nc_data=nc(basename+filename[0])
data=nc_data.variables["CMORPH"][23,0:250,250:750]
new_data=np.flipud(data)
ma_data=np.ma.masked_where(new_data<=0,new_data)
try_data=ma_data.astype(np.uint8)  

## Building threshold
tmp_data=ma_data.filled(0)
tmp_data[np.where(tmp_data!=0)]=255
bw_data=tmp_data.astype(np.uint8)

## Building markers
ma_conv=np.ma.masked_where(new_data<=2,new_data)
tmp_conv=ma_conv.filled(0)
tmp_conv[np.where(tmp_conv!=0)]=255
bw_conv=tmp_conv.astype(np.uint8)
markers = ndimage.label(bw_conv)[0]

## Watershed
labels = watershed(-try_data, markers, mask=bw_data)

匿名用户

您可以尝试使用以下方法将图像帧灰更改为BGR颜色空间

cv2. cvtColor(frame,cv2.COLOR_GRAY2BGR)

在将图像传递给分水岭算法之前