matplotlib——2. 形状和路径(Shape and Collection)底纹(hatch)

1. 形状和路径

先去看这个CSDN博客:matplotlib高级教程之形状与路径——patches和path

参考:


1.1 PatchCollection替换热力图数字

1.1.1原始的数字代码

import numpy as np
import matplotlib
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib import colormaps as cm
from matplotlib.collections import PatchCollection
import matplotlib.patches as mpatches
# %matplotlib inline
%matplotlib ipympl

vegetables = ["cucumber", "tomato", "lettuce", "asparagus",
              "potato", "wheat", "barley"]
farmers = ["Farmer Joe", "Upland Bros.", "Smith Gardening",
           "Agrifun", "Organiculture", "BioGoods Ltd.", "Cornylee Corp."]


harvest = np.array([[0.8, 2.4, 2.5, 3.9, 0.0, 4.0, 0.0],
                    [2.4, 0.0, 4.0, 1.0, 2.7, 0.0, 0.0],
                    [1.1, 2.4, 0.8, 4.3, 1.9, 4.4, 0.0],
                    [0.6, 0.0, 0.3, 0.0, 3.1, 0.0, 0.0],
                    [0.7, 1.7, 0.6, 2.6, 2.2, 6.2, 0.0],
                    [1.3, 1.2, 0.0, 0.0, 0.0, 3.2, 5.1],
                    [0.1, 2.0, 0.0, 1.4, 0.0, 1.9, 6.3]])


fig, ax = plt.subplots()

cb = plt.colorbar(matplotlib.cm.ScalarMappable(cmap = "RdBu_r"),location= "right")
cb.set_label('Y',loc='top')

# 1. 数字显示
# 默认以图像方式显示其实就和热力图效果差不多。。
im = ax.imshow(harvest,cmap='RdBu_r')
# imshow和matshow,对于热力图显示来说,是差不多的,x轴一个在上,一个在下
# https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.matshow.html#matplotlib.pyplot.matshow
# im = ax.matshow(harvest,cmap='RdBu_r')

# 为每个格子设置数字label
for i in range(len(farmers)):
    for j in range(len(vegetables)):
        text = ax.text(j, i, harvest[i, j],
                       ha="center", va="center", color="w",fontsize=10)
 # 设置x轴和y轴刻度是上面的类别
ax.set_xticks(np.arange(len(farmers)), labels=farmers,fontsize=10)
ax.set_yticks(np.arange(len(vegetables)), labels=vegetables,fontsize=10)
# ax.set_yticks(np.arange(len(vegetables)), np.arange(len(vegetables)),fontsize=10)

# 旋转x轴刻度,保证显示和对齐
plt.setp(ax.get_xticklabels(), rotation=15, ha="right",
         rotation_mode="anchor")
plt.autoscale(enable=True, axis='both', tight=True)
ax.set_xlabel('X')
ax.set_ylabel('y')
# 这个label设置参考:
# <https://matplotlib.org/stable/gallery/shapes_and_collections/ellipse_collection.html#sphx-glr-gallery-shapes-and-collections-ellipse-collection-py>

plt.show()
# plt.close("all")

在这里插入图片描述

参考: https://matplotlib.org/stable/gallery/images_contours_and_fields/image_annotated_heatmap.html

1.1.2 替换为PatchCollection的代码

import numpy as np
import matplotlib
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib import colormaps as cm
from matplotlib.collections import PatchCollection
import matplotlib.patches as mpatches
# %matplotlib inline
%matplotlib ipympl

vegetables = ["cucumber", "tomato", "lettuce", "asparagus","potato", "wheat", "barley"]
farmers = ["Farmer Joe", "Upland Bros.", "Smith Gardening",
           "Agrifun", "Organiculture", "BioGoods Ltd.", "Cornylee Corp."]


harvest = np.array([[0.8, 2.4, 2.5, 3.9, 0.0, 4.0, 0.0],
                    [2.4, 0.0, 4.0, 1.0, 2.7, 0.0, 0.0],
                    [1.1, 2.4, 0.8, 4.3, 1.9, 4.4, 0.0],
                    [0.6, 0.0, 0.3, 0.0, 3.1, 0.0, 0.0],
                    [0.7, 1.7, 0.6, 2.6, 2.2, 6.2, 0.0],
                    [1.3, 1.2, 0.0, 0.0, 0.0, 3.2, 5.1],
                    [0.1, 2.0, 0.0, 1.4, 0.0, 1.9, 6.3]])

fig2, ax2 = plt.subplots()

allCircles=[]
R = harvest/harvest.max()/2
xLen = len(farmers)
yLen= len(vegetables)
for i in range(xLen):
    for j in range(yLen):
        allCircles.append(mpatches.Circle((j,i),R[j][i]))
                          
col = PatchCollection(allCircles, array =R.flat, cmap="RdBu_r")

ax2.add_collection(col)
colorbar = plt.colorbar(col)
colorbar.set_label('y', rotation=360,loc="top")

# 这里默认设置主要刻度
ax2.set_xticks(np.arange(len(farmers)), labels=farmers,fontsize=10)
ax2.set_yticks(np.arange(len(vegetables)), labels=vegetables,fontsize=10)
# ax.set_yticks(np.arange(len(vegetables)), np.arange(len(vegetables)),fontsize=10)

# 关键是这里的这个minor参数,负责设置主要刻度还是次要刻度。
# If ``False``, set the major ticks; if ``True``, the minor ticks.
# 这里设置次要刻度,有了次要刻度后,每个圆心都对应次要刻度
ax2.set_xticks(np.arange(7+1)-0.5,minor=True)
ax2.set_yticks(np.arange(7+1)-0.5,minor=True)
ax2.grid(which='minor')

# 旋转x轴刻度,保证显示和对齐
plt.setp(ax2.get_xticklabels(), rotation=15, ha="right",
         rotation_mode="anchor")
plt.autoscale(enable=True, axis='both', tight=True)
ax2.set_xlabel('X')
ax2.set_ylabel('Y')
plt.imshow()

在这里插入图片描述

参考:


1.2 PatchCollection绘制目标检测(COCO)标签

这是基于coco标记格式进行的,代码如下:

from pycocotools.coco import COCO
import numpy as np
from PIL import Image,ImageOps
from matplotlib.collections import PatchCollection
from matplotlib.patches import Polygon

def show_box_only(coco,anns,show_label_bbox=True,is_filling=True):
    """
    coco:定义的coco对象
    anns:coco对象里得到的标注对象
    show_label_bbox:是否显示标签
    is_filling:是否对box进行填充
    """
    ax = plt.gca()
    ax.set_autoscale_on(False)
    polygons = []
    color = []
    
    image2color = dict()
    image2color[0]="orchid"
    image2color[1]="tab:blue"
    image2color[2]="pink"
    
    for ann in anns:
        # 随机生成一个0~1之间的数,作为box颜色
        c = (np.random.random((1, 3))*0.6+0.4).tolist()[0]
        # 获取bbox坐标
        [bbox_x, bbox_y, bbox_w, bbox_h] = ann['bbox']
        # Polygon需要接受四个点的坐标,顺时针或者逆时针都行
        poly = [[bbox_x, bbox_y], [bbox_x, bbox_y+bbox_h], [bbox_x+bbox_w, bbox_y+bbox_h], [bbox_x+bbox_w, bbox_y]]
        np_poly = np.array(poly).reshape((4,2))
        polygons.append(Polygon(np_poly))
        color.append(c)
        
        # 显示label文字
        if show_label_bbox:
            label_box = dict(facecolor =image2color[ann['category_id']], boxstyle="Round")
            # print(image2color[ann['category_id']])
            ax.text(bbox_x, bbox_y, f"{coco.loadCats(ann['category_id'])[0]['name']}", color="white",fontsize=10,bbox=label_box)
        else:
            pass
    if is_filling:
        # 显示前景色
        p = PatchCollection(polygons, facecolor=color, linewidths=0, alpha=0.4)
        ax.add_collection(p)
    # 只画框
    p = PatchCollection(polygons, facecolor='none', edgecolors=color, linewidths=2)
    ax.add_collection(p)


# 调用上面的函数
import os

dataDir= "datasets/cat_dataset/images"
annFile='datasets/cat_dataset/annotations/annotations_all.json'

coco = COCO(annotation_file=annFile)
image_ids=coco.getImgIds()
np.random.shuffle(image_ids)

plt.figure(figsize=(16,5))
for i in range(8):
    image_data=coco.loadImgs(image_ids[i])[0]
    img_path = os.path.join(dataDir,image_data.get("file_name"))

    annotation_ids = coco.getAnnIds(imgIds=image_data['id'])
    annotation = coco.loadAnns(annotation_ids)

    ax=plt.subplot(2,4,i+1)
    image = Image.open(img_path)
    imageWithEXIF=ImageOps.exif_transpose(image)
    ax.imshow(imageWithEXIF)
    
    show_box_only(coco,annotation)
    plt.title(image_data["file_name"])
    plt.xticks([])
    plt.yticks([])
plt.tight_layout()

在这里插入图片描述

1.3 PatchCollection绘制分割(COCO)标签

和上面差不多,效果如下:
在这里插入图片描述

2. 底纹(hatch)

其实matplotlib里的绘制和ppt里很像,都有形状,也有底纹颜色等的设置,比如:

2.1 简单示例(add_patch)

以下是来自:Hatch demo的示例

hatch底纹的颜色默认和edgecolor(ec)一致,不设置默认就是黑色

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse, Polygon

x = np.arange(1, 5)
y1 = np.arange(1, 5)
y2 = np.ones(y1.shape) * 4

fig = plt.figure()
axs = fig.subplot_mosaic([['bar1', 'patches'], ['bar2', 'patches']])

axs['bar1'].bar(x, y1, edgecolor='black', hatch="/")
axs['bar1'].bar(x, y2, bottom=y1, edgecolor='black', hatch='//')

axs['bar2'].bar(x, y1, edgecolor='black', hatch=['--', '+', 'x', '\\'])
axs['bar2'].bar(x, y2, bottom=y1, edgecolor='black',
                hatch=['*', 'o', 'O', '.'])

x = np.arange(0, 40, 0.2)
axs['patches'].fill_between(x, np.sin(x) * 4 + 30, y2=0,
                            hatch='///', zorder=2, fc='c')
"""
1. add_patch的hatch设置
"""
axs['patches'].add_patch(Ellipse((4, 50), 10, 10, fill=True,
                                 hatch='*', facecolor='y'))
axs['patches'].add_patch(Polygon([(10, 20), (30, 50), (50, 10)],
                                 hatch='\\/...', facecolor='g'))
axs['patches'].set_xlim([0, 40])
axs['patches'].set_ylim([10, 60])
axs['patches'].set_aspect(1)
plt.show()

2.2 add_artist和add_collection(PatchCollection)中hatch设置


from matplotlib.collections import PatchCollection
import matplotlib.patches as mpatches
import matplotlib as mlp
import numpy as np

"""
2. add_artist中patches的hatch设置
"""
circle = mpatches.Circle((0, 0), 0.1, ec="yellow",hatch="+")


path = np.array([[0,0],[0.1,0.2],[0.2,0.1]])
patchWithPolygon = PatchCollection([mlp.patches.Polygon(path)], ec="white")
"""
3. add_collection的hatch设置
"""
patchWithPolygon.set(hatch="*")

fig, axs = plt.subplots(1, 2, figsize=(4, 2), layout="constrained")
axs.flat[0].add_artist(circle)
# axs.flat[0].set_axis_off()
axs.flat[0].set(title=type(circle).__name__,
           aspect=1, xlim=(-.2, .2), ylim=(-.2, .2))

axs.flat[1].add_collection(patchWithPolygon)
axs.flat[1].set(title=type(patchWithPolygon).__name__,
           aspect=1, xlim=(-.3, .3), ylim=(-.3, .3))

x = [float(i[0]) for i in path]
y = [float(i[1]) for i in path]
axs.flat[1].scatter(x,y,c='r')

plt.show()

在这里插入图片描述

参考:


2.3 底纹样式列表

常见的底纹详见:https://matplotlib.org/stable/gallery/shapes_and_collections/hatch_style_reference.html

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吨吨不打野

解决了问题,觉得还行就给点

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值