2016-03-28 351 views
6

让我开始与我所在的地方:如何在Matplotlib中填充任意封闭区域?

enter image description here

我用下面的代码创建的上述图像:

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) 

有没有办法填补回路(或三角形类地区)是否在线与其他颜色交叉时创建?它不一定是matplotlib,它可以是scikit-image或其他库。

我想一些伪代码,如:

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

但我不知道如何获得regions,或如何填补这是可行的。

回答

3

这个问题对我来说似乎很简单,我的想法是使用blob分析来检测不同的blob,按大小对它们进行分组,并使用floodfill算法对它们进行着色。

但是,我遇到了一些问题,我没有修改缺省值的blob分析,这花费了一些时间。此外,我还没有发现用OpenCV填充或着色Blob的任何python代码片段,并且与使用SimpleBlobDetection的旧版本相比,我已经发现了一些语法变化,我只能找到一些文档和示例代码。所以也许所有这些代码也可以对其他用户有用。

希望我已经正确识别出您想要查找的细分受众群。如果你不想包含大的黑色外层叶子,那么有一条评论。

对于可视化的缘故,可以调整图像的大小(在此刻注释,记得由4×4 = 16个的系数相应地调整大小阈值)

enter image description here

的代码是所有这些选项有点冗长,但希望容易阅读。我已经从OpenCV的blob分析中学到了很多有关这个问题的知识,谢谢!顺便说一下,好的形象。

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