На основе решения, которое я прочитал в Как определить маркеры для Водораздел в 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/modules/imgproc/src/segmentation.cpp:
error: (-210) Only 8-bit, 3-channel input images are supported in function cvWatershed
То, что я видел в Интернете, связано с тем, что данные в градациях серого представляют собой 2D-изображение, а для водораздела требуется 3D-изображение (из RGB). Действительно, я попробовал скрипт с изображением в формате jpg, и он работал отлично. Эта проблема упоминается здесь, но дан ответ, наконец, отклоненный. И я не могу найти более свежую ссылку, отвечающую на вопрос.
Чтобы попытаться решить эту проблему, я создал 3D-массив из 2D-данных new_data:
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-изображению и/или максимально ограничить количество операций.