本文共 4530 字,大约阅读时间需要 15 分钟。
•凸包:在一个平面内,我们能够找到的最小的将一组数据全部包括在内的凸集,通俗来说凸包就是包围一组散点的最小凸边形!!
•凸边形即为对外的角都不为钝角!!图二,图三都有向外的钝角即不为凸边形
•在计算机视觉技术中,我们经常需要使用凸包,以帮助
计算机识别图像的轮廓!!!•首先,需要绘制基础的散点图:
import numpy as np;np.random.seed(1) # 确定以固定的模式生成随机数 (1)中的数字可随便写import matplotlib.pyplot as pltx1, y1 = np.random.normal(loc=5 # 正态分布的均值 , scale=2 # 正态分布的方差 , size=(2, 15)) # 生成2列15行的数据 分别对应x1 y1x2, y2 = np.random.normal(loc=8 , scale=2.5 , size=(2, 13))plt.scatter(x1, y1)plt.scatter(x2, y2)plt.show()
•random.randn
取出符合标准正态分布的随机数,期望值(均值)=0 方差=1
random.normal
取出符合自定义正态分布的随机数 均值与方差均可自定义 •上述图片是我们绘制的基本散点图,下一步使用spatial给散点图添加凸包
•首先自定义绘制凸包的函数,包括各种属性,在使用该函数绘制凸包即可完成!!import numpy as np;np.random.seed(1)# 确定以固定的模式生成随机数 (1)中的数字可随便写import matplotlib.pyplot as pltfrom scipy.spatial import ConvexHullx1, y1 = np.random.normal(loc=5 # 正态分布的均值 , scale=2 # 正态分布的方差 , size=(2, 15)) # 生成2列15行的数据 分别对应x1 y1x2, y2 = np.random.normal(loc=8 , scale=2.5 , size=(2, 13))plt.scatter(x1, y1)plt.scatter(x2, y2)# 定义绘制凸包的函数def encircle(x, y, ax=None, **kw): if not ax: ax = plt.gca() p = np.c_[x, y] # c_功能类似于zip,是生成拼接起来的数组array hull = ConvexHull(p) # 将数据集输入到ConvexHull()中,自动生凸包对象 poly = plt.Polygon(p[hull.vertices, :], **kw) ax.add_patch(poly)# 调用凸包函数encircle(x1, y1, ec='k', # 线条的颜色 fc='gold', # 多边形的颜色 alpha=0.2) # 图像整体的透明度encircle(x2, y2, ec='orange', fc='none')plt.show()
代码解读:
•(1)导入我们所需的库numpy ,matplotlib ,scipy
并确定以固定的模式生成随机数 •(2)绘制基础散点图 •(3)定义绘制凸包的函数,以及其中的属性 •(4)调用凸包函数,并确定其中的属性 •(5)显示图片 •凸包的本质为:在已经绘制完成的散点图上添加凸包线条
•凸包函数中的 x y
分别为横坐标,纵坐标,ax
参数是获取绘制好的散点图, •if not ax: ax = plt.gca()
判断前面是否绘制过子图(当前散点图),gca()
的作用:有就获取当前子图,否则就创建新的子图 •p = np.c_[x, y]
c_功能类似于zip,是生成拼接起来的数据集,类型为array(数组) •hull = ConvexHull( p )
将数据集p输入到ConvexHull()中,自动生凸包对象 注意:数据集p必须为数组 •poly = plt.Polygon(p[hull.vertices, :], **kw)
,使用p[hull.vertices, :]
获取凸点的横,纵坐标,再使用Polygon
函数将所有的凸点连接起来形成多边形 kw
就是定义函数的kw,里面包含一系列绘制多边形需要调节的属性,包括边框颜色,填充颜色,透明度等等 •ax.add_patch(poly)
将生成的多边形添加到子图中(散点图) •最后调用凸包函数,确定必要的属性即可完成绘制凸包 •在上篇博客中我们已经成功绘制了气泡图:
•我们将选取美国中西部数据集的一个州,来绘制上图中的凸包
•选取IN这个州来绘制凸包 代码测试:import matplotlib.pyplot as pltimport numpy as npimport pandas as pdimport seaborn as snsfrom scipy.spatial import ConvexHull# 导入数据midwest = pd.read_csv(r'D:\9\midwest_filter.csv')# 预设图像各种信息large = 22med = 16small = 12params = { 'axes.titlesize': large, # 子图上的标题字体大小 'legend.fontsize': med, # 图例的字体大小 'figure.figsize': (med, small), # 画布大小 'axes.labelsize': med, # 标签的字体大小 'xtick.labelsize': med, # x轴标尺的字体大小 'ytick.labelsize': med, # y轴标尺的字体大小 'figure.titlesize': large} # 整个画布的标题字体大小plt.rcParams.update(params) # 设定各种默认属性plt.style.use('seaborn-whitegrid') # 设置整体风格sns.set_style('white') # 设置整体背景风格# 准备标签列表与颜色列表categories = np.unique(midwest['category'])colors = [plt.cm.tab10(i / float(len(categories) - 1)) for i in range(len(categories))]# 布置画布fig = plt.figure(figsize=(14, 8), dpi=120, facecolor='w', edgecolor='k')for i, category in enumerate(categories): plt.scatter('area', 'poptotal', data=midwest.loc[midwest.category == category, :] , s=midwest.loc[midwest.category == category, 'percasian'] * 500 # 需要对比的属性 # ,s='percasian' , c=np.array(colors[i]).reshape(1, -1) # 点的颜色 , edgecolors=np.array(colors[i]).reshape(1, -1) # 点的边缘颜色 , label=str(category) # 标签 , alpha=0.7 # 透明度 , linewidths=.5) # 点的边缘线的宽度# 绘制凸包# 定义函数def encircle(x, y, ax=None, **kw): if not ax: ax = plt.gca() p = np.c_[x, y] hull = ConvexHull(p) poly = plt.Polygon(p[hull.vertices, :], **kw) ax.add_patch(poly)# 定义需要被框起来的数据:所有在in州中的城市midwest_encircle_data = midwest.loc[midwest.state == 'IN', :]# 使用函数绘制encircle(midwest_encircle_data.area, midwest_encircle_data.poptotal, ec='k', fc='gold', alpha=0.1)# 绘制包围的淡蓝色的线encircle(midwest_encircle_data.area, midwest_encircle_data.poptotal, ec='lightblue', fc='none', linewidth=1.5)# 装饰图像plt.gca().set(xlim=(0.0, 0.12), ylim=(0, 90000), xlabel='Area', ylabel='Population')plt.xticks(fontsize=12)plt.yticks(fontsize=12)plt.title('Bubble Plot Encircling', fontsize=22)lgnd = plt.legend(fontsize=12)plt.show()
图片显示:
•上图凸包的含义为:凸包中包含IN这个州的所有城市,但是凸包中的所有城市不全是IN这个州中的转载地址:http://myrzi.baihongyu.com/