2017-11-14 12 views
1

Basierend auf einer Lösung, die ich unter How to define the markers for Watershed in OpenCV? gelesen habe, versuche ich anzuwenden Wasserscheide grayscale data (not very visible but not all black), extrahiert aus netcdf (Niederschlagsdaten).Wie Watershed auf Graustufenbild mit Opencv und Python anwenden?

Hier ist ein black and white version of the data (Schwelle bei 0), so dass Sie einfacher sehen können, und die markers Ich möchte verwenden, um die verschiedenen Becken zu definieren (im Grunde nur eine Schwelle, wo Niederschlag stärker ist).

Der Code, den ich läuft wie folgt:

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 

Ich habe folgende Fehler für den Wendepunkt in der opencv-2.4.11/modules/imgproc/src/segmentation.cpp:

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

Für was ich im Internet gesehen habe, ist dies aufgrund der Tatsache, dass die Graustufen Daten ein 2D-Bild und Wasserscheide ein 3D-Bild (von RGB) benötigt. In der Tat habe ich das Skript mit einem JPG-Bild ausprobiert und ich habe perfekt gearbeitet. Dieses Problem wird here erwähnt, aber die gegebene Antwort wurde schließlich zurückgewiesen. Und ich kann keinen kürzlichen Link finden, der die Frage beantwortet.

Um zu versuchen, dieses Problem zu lösen, habe ich ein 3D-Array aus dem 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) 

Aber, wie erwartet, es hat das Problem (gleiche Fehlermeldung) nicht lösen.

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,)) 

Aber die Größe des test_data erstellt unterscheidet sich von ma_data (+ ich nicht loswerden der Etiketten bekommen können): RGB-Daten zu erhalten

Ich habe auch versucht, die Handlung von matplotlib zu speichern.

Also, ich bin hier fest. Im Idealfall möchte ich das Wassereinzugsgebiet direkt auf das 2D-Graustufenbild anwenden und/oder die Anzahl der Vorgänge so weit wie möglich begrenzen.

+0

[Werfen Sie einen Blick] (https://www.pyimagesearch.com/2015/11/02/watershed-opencv/) – Link

Antwort

1

Wie yapws87 erwähnt vorbei, gab es in der Tat ein Problem mit dem Format Ich stellte mich der Wasserscheide-Funktion vor. Doing try_data=ma_data.astype(np.uint8) entfernt die Fehlermeldung.

ist hier ein minimales Beispiel, das jetzt funktioniert:

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

können Sie versuchen, Ihr Bild Fram grau zu einem BGR-Farbraum zu ändern

cv2.cvtColor(frame, cv2.COLOR_GRAY2BGR)

verwenden, bevor Ihr Bild Wasserscheide Algorithmus

+0

Vielen Dank für die Suggestion, aber dies ist der gleiche Effekt wie beim Erstellen des 3D-Arrays aus dem 2D-Test (die erstellte Testvariable), vielleicht weil Sie nicht genug Informationen haben, um wieder zu RGB zu gelangen. – dcoppin

+0

Sie brauchen nicht mehr Informationen, um zu RGB zu wechseln, es wird nur die Werte zu jedem der RGB-Kanäle duplizieren. Meine Vermutung ist, dass das Format, das Sie der Wasserscheide-Funktion präsentieren, nicht korrekt ist. – yapws87

+0

Ihre Vermutung war richtig. Das erste Argument im Wassereinzugsgebiet hatte nicht das richtige Format. Der Fehler hatte nichts mit der Dimension des Graustufenbildes zu tun. – dcoppin