需求说明
有时候,我们需要对一张图片进行坐标轴绘制,直观观察图片的长宽分布,并根据坐标轴中心点的选取来实现不同位置的坐标轴。
常见需求:
- 中心点自定义
- 坐标间隔自定义
- 坐标轴颜色自定义
- 透明度自定义
- 间隔值大小自定义以及颜色自定义
- 图片自定义
因此,本博客就以上需求进行代码实现,具体效果如下:
原图:
绘制坐标轴后的图:
实现代码
主要操作讲解都在代码中注释了,可以边看边食用!
依赖的库
from matplotlib import pyplot as plt
import os
# 设置图片保存的分辨率
plt.rcParams['savefig.dpi'] = 200
主要函数
def patch_arrow(img_path, center, limits=None, interval=6, color='r', width=2, fontsize=7, fontcolor='black', alpha=0.5):
'''
img_path: 图片路径
center: 中心坐标
limits: 坐标轴间隔大小——默认为None, 表示自动求取间隔
interval: 间隔标记的长度
color: 坐标轴颜色
width: 线条宽度
fontsize: 坐标间隔的字体大小
fontcolor: 间隔字体颜色
alpha: 透明度--值越大,透明度越小
'''
# 判断输入条件是否满足基本要求
assert os.path.isfile(img_path), \
'please enter a truthful img_path, now it dosen`t exist.'
assert len(center)==2, \
'please enter center like (x, y).'
assert alpha <= 1.0 and alpha >= 0., \
'please enter alpha like (from 0. to 1.).'
img = plt.imread(img_path) # 读取图像
h,w,_ = img.shape # 获取高宽
# 自动确定间隔
auto_limit_numbers = 12 # 自动间隔点
if limits is None:
limits = max((h, w))
limits = limits // auto_limit_numbers
fig = plt.figure(figsize=(w/100,h/100))
x, y = center[0], center[1]
# 判断输入的中心点坐标是否超出图片区域
assert x < w and y < h, \
'please enter a truethful center position, which must limit in (x < w, y < h).'
# 计算中心的点到图像左右两边的距离——即中心点左右两边允许的绘图区域
to_w_left = x
to_w_right = (w-1) - x # (w-1):图片布局是从0到w-1,所以x最大值为w-1
# 计算中心的点到图像上下两边的距离——即中心点左右两边允许的绘图区域
to_h_up = y
to_h_down = (h-1) - y
# 计算绘制图像时的偏移值--受限于width
x_offset = width / 2 # 用于绘制x轴等图像时的一个偏移值,用于修正绘图
y_offset = width / 2 # 用于修正y轴相关绘图
# 展示图片
plt.imshow(img)
plt.axis('off') # 关闭坐标轴
# 绘制x, y轴
# 绘制x轴,保持y不变
# 绘制y轴,保持x不变
# head_width: 箭头大小
# width: 线宽
plt.arrow(x=0, y=y-y_offset, dy=0, dx=w-1, color=color, width=width, alpha=alpha, length_includes_head=True, head_width=5*width) # x 轴
plt.arrow(x=x-x_offset, y=h-1, dy=-h+1, dx=0, color=color, width=width, alpha=alpha, length_includes_head=True, head_width=5*width) # y 轴
# 制作x轴坐标间隔--根据limit去求解存在的间隔
to_w_left_star = [] # 制作x轴的左轴--包含0值--即原点信息
for i in range(0, to_w_left+1, limits):
to_w_left_star.append(i)
to_w_right_star = [] # 制作x轴的右轴--包含0值--即原点信息
for i in range(0, to_w_right+1, limits):
to_w_right_star.append(i)
# 制作y轴坐标间隔
to_h_up_star = [] # 上轴--包含0值--即原点信息
for i in range(0, to_h_up+1, limits):
to_h_up_star.append(i)
to_h_down_star = [] # 下轴--包含0值--即原点信息
for i in range(0, to_h_down+1, limits):
to_h_down_star.append(i)
# 绘制各轴的间隔
# 之所以每一个遍历都带入一个0值判断,是为了保证循环结构的一致性,因为如果从索引1开始,当某一个轴一边不满足间隔,就会导致遍历无法进行
for i in to_w_left_star[:]: # x 左轴
if i == 0: # 跳过零点
continue
# 绘制坐标轴间隔线条
plt.plot((x-i, x-i), (y-y_offset, y-y_offset-interval), color=color, alpha=alpha, linewidth=width-2 if width-2>0 else 1)
# 绘制坐标轴间隔的值
# x, y经过调整,默认参数下显示较为良好
# 如果自定义字体过大,可能存在一定的偏移,不会很影响显示效果
plt.text(x=x-i-0.1*limits, y=y+0.35*limits, s='{0:d}'.format(-i), fontsize=fontsize, color=fontcolor)
for i in to_w_right_star[:]: # x 右轴
if i == 0:
continue
plt.plot((x+i, x+i), (y-y_offset, y-y_offset-interval), color=color, alpha=alpha, linewidth=width-2 if width-2>0 else 1)
plt.text(x=x+i-0.1*limits, y=y+0.35*limits, s='{0:d}'.format(i), fontsize=fontsize, color=fontcolor)
for i in to_h_up_star[:]: # y 上轴
if i == 0:
continue
plt.plot((x-x_offset, x-x_offset+interval), (y-i, y-i), color=color, alpha=alpha, linewidth=width-2 if width-2>0 else 1)
plt.text(x=x+0.15*limits, y=y-i+0.1*limits, s='{0:d}'.format(i), fontsize=fontsize, color=fontcolor)
for i in to_h_down_star[:]: # y 下轴
if i == 0:
continue
plt.plot((x-x_offset, x-x_offset+interval), (y+i, y+i), color=color, alpha=alpha, linewidth=width-2 if width-2>0 else 1)
plt.text(x=x+0.15*limits, y=y+i+0.1*limits, s='{0:d}'.format(-i), fontsize=fontsize, color=fontcolor)
plt.text(x=x+0.1*limits, y=y+0.35*limits, s='0', fontsize=fontsize,color=fontcolor) # 原点标定绘制
# 保存修改后的图片
# bbox_inches='tight': 去掉白边——原坐标轴的占位
fig.savefig('test.png',bbox_inches='tight')
示例
img_path = 'fst.jpg' # 自行修改
# img_path: 图片路径
# center:坐标轴中心点
# limits:是否自定设置间隔--None为自动,可以自行调节大小(int/float)
# limits——设置不恰当可能出现坐标轴间隔值的重叠情况
# interval:间隔直线的高度
# color:坐标轴颜色
# width:坐标轴粗细
# fontsize:坐标轴间隔值的大小
# fontcolor:坐标轴字体颜色
# alpha:透明度
patch_arrow(img_path, center=[200, 200], limits=None, interval=12, color='r', width=3, fontsize=20, fontcolor='r', alpha=0.6)
result:
如果对你有帮助,不妨点赞关注一下吧!(●’◡’●)