2016-03-28 7 views
6

Lassen Sie mich beginnen mit, wo ich bin:Wie kann ich beliebige geschlossene Bereiche in Matplotlib füllen?

enter image description here

Ich habe das obere Bild mit dem folgenden Code:

import matplotlib.pyplot as plt 
import numpy as np 

color_palette_name = 'gist_heat' 
cmap = plt.cm.get_cmap(color_palette_name) 
bgcolor = cmap(np.random.rand()) 

f = plt.figure(figsize=(12, 12), facecolor=bgcolor,) 
ax = f.add_subplot(111) 
ax.axis('off') 

t = np.linspace(0, 2 * np.pi, 1000) 

x = np.cos(t) + np.cos(6. * t)/2.0 + np.sin(14. * t)/3.0 
y = np.sin(t) + np.sin(6. * t)/2.0 + np.cos(14. * t)/3.0 

ax.plot(x, y, color=cmap(np.random.rand())) 
ax.fill(x, y, color=cmap(np.random.rand())) 
plt.tight_layout() 
plt.savefig("../demo/tricky.png", facecolor=bgcolor, edgecolor=cmap(np.random.rand()), dpi=350) 

Gibt es eine Möglichkeit, die Schleifen (oder das Dreieck-like zu füllen Regionen), die entstehen, wenn sich die Linie mit einer anderen Farbe kreuzt? Es muss nicht matplotlib sein, es könnte scikit-image oder eine andere Bibliothek sein.

Ich denke, einige Pseudo-Code wie:

for region in regions: 
    ax.fill(region, color=cmap(np.random.rand())) 

Aber ich habe keine Ahnung, wie die regions zu bekommen, oder wie Füllung würde es funktionieren.

Antwort

3

Das Problem zuerst schien mir einfach, meine Idee war Blob-Analyse zu verwenden, um die verschiedenen Blobs zu erkennen, sie nach Größe zu gruppieren und einen Floodfill-Algorithmus zu verwenden, um sie zu färben.

Ich habe jedoch einige Probleme mit Standardwerten für die Blob-Analyse, die ich nicht geändert hatte, einige Zeit gerissen. Außerdem habe ich keine Python-Code-Snippets zum Füllen oder Kolorieren von Blobs mit OpenCV gefunden, und es gab einige Syntaxänderungen für die Verwendung von SimpleBlobDetection im Vergleich zu älteren Versionen, für die ich nur wenig Dokumentation und Beispielcode finden konnte. Vielleicht kann der ganze Code auch für andere Benutzer nützlich sein.

Ich hoffe, dass ich die Segmente, die Sie finden wollten, richtig identifiziert habe. Wenn Sie die großen dunklen äußeren Blätter nicht einschließen möchten, gibt es eine Linie, um zu kommentieren.

Aus Gründen der Visualisierung können Sie die Größe des Bildes (zur Zeit auf Kommentar, denken Sie daran um einen Faktor Größenschwellen entsprechend von 4 * 4 = 16 anzupassen)

enter image description here

Der Code ist etwas langwierig mit all diesen Optionen, aber hoffentlich leicht zu lesen. Ich habe viel über die Blob-Analyse mit OpenCV gelernt, die an diesem Problem arbeitet, danke!

Schönes Bild, übrigens.

import numpy as np 
import cv2 

im = cv2.imread('tricky.png') 

# For better visibility, resize image to better fit screen 
#im= cv2.resize(im, dsize=(0,0),fx=0.25, fy=0.25) 

#convert to gray value for blob analysis 
imgray= cv2.cvtColor(im,cv2.COLOR_BGR2GRAY) 



#### Blob analysis to find inner white leaves 
# SimpleBlobDetector will find black blobs on white surface, this is why type=cv2.THRESH_BINARY_INV is necessary 
ret,imthresh = cv2.threshold(imgray,160, 255,type=cv2.THRESH_BINARY_INV) 

# Setup SimpleBlobDetector parameters. 
params = cv2.SimpleBlobDetector_Params() 

# Filter by Area. 
params.filterByArea = True 
params.minArea = 15000 
params.maxArea = 150000 

# Create a detector with the parameters 
detector = cv2.SimpleBlobDetector_create(params) 

# Detect blobs. 
keypoints = detector.detect(imthresh) 

# Draw detected blobs as red circles. 
# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures 
# the size of the circle corresponds to the size of blob 
im_with_keypoints = cv2.drawKeypoints(imthresh, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) 

# Show blobs 
cv2.imshow("Keypoints", im_with_keypoints) 




####floodfill inner white leaves with blue 
#http://docs.opencv.org/3.0-beta/modules/imgproc/doc/miscellaneous_transformations.html 

#Create a black mask for floodfill. Mask needs to be 2 pixel wider and taller 
maskborder=imgray.copy() 
maskborder[:] = 0 
bordersize=1 
maskborder=cv2.copyMakeBorder(maskborder, top=bordersize, bottom=bordersize, left=bordersize, right=bordersize, borderType= cv2.BORDER_CONSTANT, value=[255,255,255]) 
print imgray.shape[:2] 
print maskborder.shape[:2] 

#Create result image for floodfill 
result = im.copy() 

#fill white inner segments with blue color 
for k in keypoints: 
    print int(k.pt[0]),int(k.pt[1]) 
    seed_pt = int(k.pt[0]),int(k.pt[1]) 
    cv2.floodFill(result, maskborder, seed_pt, (255,0, 0)) 




#### Blob analysis to find small triangles 
# SimpleBlobDetector will find black blobs on white surface, this is why type=cv2.THRESH_BINARY_INV is necessary 
ret,imthresh2 = cv2.threshold(imgray,150, 255,type=cv2.THRESH_BINARY) 
ret,imthresh3 = cv2.threshold(imgray,140, 255,type=cv2.THRESH_BINARY_INV) 
imthresh4 = cv2.add(imthresh2,imthresh3) 

# Setup SimpleBlobDetector parameters. 
params = cv2.SimpleBlobDetector_Params() 

# Filter by Area. 
params.filterByArea = True 
params.minArea = 20 
params.maxArea = 1000 
params.maxArea = 50000 #Using this line includes the outer dark leaves. Comment out if necessary 

# Don't filter by Circularity 
params.filterByCircularity = False 

# Don't filter by Convexity 
params.filterByConvexity = False 

# Don't filter by Inertia 
params.filterByInertia = False 

# Create a detector with the parameters 
detector = cv2.SimpleBlobDetector_create(params) 

# Detect blobs. 
keypoints = detector.detect(imthresh4) 

# Draw detected blobs as red circles. 
# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures 
# the size of the circle corresponds to the size of blob 
im_with_keypoints2 = cv2.drawKeypoints(imthresh4, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) 

# Show blobs 
cv2.imshow("Keypoints2", im_with_keypoints2) 



####floodfill triangles with green 
#http://docs.opencv.org/3.0-beta/modules/imgproc/doc/miscellaneous_transformations.html 

#Create a black mask for floodfill. Mask needs to be 2 pixel wider and taller 
maskborder=imgray.copy() 
maskborder[:] = 0 
bordersize=1 
maskborder=cv2.copyMakeBorder(maskborder, top=bordersize, bottom=bordersize, left=bordersize, right=bordersize, borderType= cv2.BORDER_CONSTANT, value=[255,255,255]) 
print imgray.shape[:2] 
print maskborder.shape[:2] 

#Create result image for floodfill 
result2 = result.copy() 

#fill triangles with green color 
for k in keypoints: 
    print int(k.pt[0]),int(k.pt[1]) 
    seed_pt = int(k.pt[0]),int(k.pt[1]) 
    cv2.floodFill(result2, maskborder, seed_pt, (0,255, 0)) 



#cv2.imshow('main',im) 
#cv2.imshow('gray',imgray) 
#cv2.imshow('borders',maskborder) 
#cv2.imshow('threshold2',imthresh2) 
#cv2.imshow('threshold3',imthresh3) 
#cv2.imshow('threshold4',imthresh4) 
cv2.imshow("Result", result2) 
cv2.imwrite("result.png",result2) 

cv2.waitKey(0) 
cv2.destroyAllWindows()