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

问题描述 投票:1回答:2

根据我在How to define the markers for Watershed in OpenCV?上读到的解决方案,我正在尝试将分水岭应用于从netcdf(降水数据)中提取的grayscale data (not very visible but not all black)

这是一个black and white version of the data(阈值为0),以便您可以更容易地看到,并且我想用markers来定义不同的盆地(基本上只是降水更强烈的另一个门槛)。

我正在运行的代码如下:

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 / modules / imgproc / src / segmentation.cpp中对分水岭有以下错误:

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

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

为了解决这个问题,我从2D new_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灰度图像上应用分水岭和/或尽可能地限制操作次数。

python opencv image-segmentation grayscale watershed
2个回答
1
投票

正如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)

0
投票

您可以尝试使用将图像格式更改为BGR颜色空间

cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)

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

© www.soinside.com 2019 - 2024. All rights reserved.