最近在学图形学绘制,想到了ImagePy框架的ROI涂抹交互很方便,于是啃起了绘制代码。
这里主要对ImagePy中一个填充工具进行难点讲解。
让我们好好学习Python中的图形学绘制吧。
例子代码来源:
# -*- coding: utf-8 -*-
"""
Created on Mon Nov 14 17:40:41 2016
@author: yxl
"""
from __future__ import absolute_import
import numpy as np
def f(p1,p2,y):
if abs(p1[1]-y) > abs(p2[1]-y):p1,p2 = p2,p1
k =1.0* (p1[1]-y)/(y-p2[1])
return round((p1[0]+k*p2[0])/(1+k),4)
def scan(polys, idx, ys, st, y, cur, buf):
while cur<len(idx) and ys[st[cur]]<=y:
c = idx[st[cur]]
poly = polys[c[0]]
for i in (c[0], (c[1]-1)%len(poly)), tuple(c):
if i in buf:buf.remove(i)
else: buf.append(i)
cur += 1
return cur
def roots(polys, buf, y):
rs = []
for i in buf:
poly = polys[i[0]]
i1,i2 = i, (i[0],(i[1]+1)%len(poly))
rs.append(f(poly[i1[1]], poly[i2[1]],y))
return np.sort(rs)
def fill(plgs, img, color = 1, o=(0,0)):
polys = [np.array(plg[:-1])-0.5 for plg in plgs]
shape = img.shape[:2]
ys = []
for i in range(len(polys)):
for j in range(len(polys[i])):
ys.append((i,j,polys[i][j][1]))
ys = np.array(ys)
st = np.argsort(ys[:,2])
buf, rst, cur = [], [], 0
bot,top = np.clip([int(ys[:,2].min()-1),int(ys[:,2].max()+2)], 0, shape[0])
idx = ys[:,:2].astype(np.int16)
for y in range(bot, top):
cur = scan(polys, idx, ys[:,2], st, y, cur, buf)
rs = roots(polys, buf, y)
for i in zip(rs[::2],rs[1::2]):
x1, x2 = int(np.ceil(i[0])), int(np.floor(i[1])+2)
x1, x2 = max(x1,0), min(x2, shape[1])
if x1 >= shape[1] or x2 < 0: continue
#rst.extend([(x,y) for x in range(max(x1,o[0]), min(x2, shape[2]))])
img[y,x1:x2] = color
return np.array(rst).T
if __name__ == '__main__':
import matplotlib.pyplot as plt
from time import time
# pg.shape = (1,4,2)
pg = np.array([[(-300,-100),(1100,100),(400,1300),(100,100)]])
# img.shape = (1000, 500)
img = np.zeros((1000, 500))
a = time()
rc= fill(pg, img)
print(time() - a)
plt.imshow(img, interpolation='nearest',cmap='gray')
plt.show()
print("Done!")
疑问:
for i in range(len(polys)): for j in range(len(polys[i])): ys.append((i,j,polys[i][j][1])) ys = np.array(ys)
转换成一维数组还是转换成适合pandas处理的数据结构?
polys[i][j][1])代表什么?
cur = scan(polys, idx, ys[:,2], st, y, cur, buf)
一列扫描吗?
ImagePy_Learn学习系列
土盐:ImagePy_Learn | 图形学绘制代码学习:core\draw\fill.py
土盐:ImagePy_Learn | 图形学绘制代码学习:paint.py
详解如下:
round((p1[0]+k*p2[0])/(1+k),4)
np.sort(rs)
plg[:-1]
X[:,0]是numpy中数组的一种写法,表示对一个二维数组,取该二维数组第一维中的所有数据,第二维中取第0个数据,直观来说,X[:,0]就是取所有行的第0个数据, X[:,-1] 就是取所有行的最后一个数据。
import numpy as np
a=np.random.rand(5)
print(a)
[ 0.64061262 0.8451399 0.965673 0.89256687 0.48518743]
print(a[-1]) ###取最后一个元素
[0.48518743]
print(a[:-1]) ### 除了最后一个取全部
[ 0.64061262 0.8451399 0.965673 0.89256687]
print(a[::-1]) ### 取从后向前(相反)的元素
[ 0.48518743 0.89256687 0.965673 0.8451399 0.64061262]
print(a[2::-1]) ### 取从下标为2的元素翻转读取
[ 0.965673 0.8451399 0.64061262]
img.shape[:2]
img.shape[:2] 取彩色图片的高、宽,如果img.shape[:3] 取彩色图片的高、宽、通道
1:一般的数组如:【22,33】 shape是(2,):他表示他是一个一维数组,数组中有两个元素;注意他和shape(2,1)的区别,他两个不一样。
2:[[22],[33]] 他的shape是(2,1),表示二维数组,每行有一个元素
3:[[22,33]] shape是(1,2) 他表示一个二维数组,每行有两个元素
image.shape[0], 图片垂直尺寸 image.shape[1], 图片水平尺寸 image.shape[2], 图片通道数
st = np.argsort(ys[:,2])
numpy.argsort(a, axis=-1, kind=’quicksort’, order=None)
功能: 将矩阵a按照axis排序,并返回排序后的下标
参数: a:输入矩阵, axis:需要排序的维度
返回值: 输出排序后的下标
bot,top = np.clip([int(ys[:,2].min()-1),int(ys[:,2].max()+2)], 0, shape[0])
将[int(ys[:,2].min()-1),int(ys[:,2].max()+2)]范围外的数强制转化为[0, shape[0]]范围内的数
- def clip(a, a_min, a_max, out=None): 将数组a中的所有数限定到范围a_min和a_max中,即az中所有比a_min小的数都会强制变为a_min,a中所有比a_max大的数都会强制变为a_max.
- 其中a_min和a_max可以为一个和a一样大小的数组(列表也可以,只要是类似数组的结构就是可行的),则数组中相应位置的元素进行比较。
- out 是可选项,表示把强制截取后的结果放到这个数组中,但是out中的数组必须和a形状一样
参考原文链接:np.clip截取函数 - cloud&ken
python中numpy模块下的np.clip()的用法 - IT届的小学生
idx = ys[:,:2].astype(np.int16)
使用方法:
- df.astype('数据类型') #改变整个df的数据类型
- df['列名'].astype('数据类型') #仅改变某一列的数据类型
num=num.astype('str')#将整个dataframe都转换为str类型
参考原文链接:python强制类型转换astype - weixin_42036641的博客
ys.append((i,j,polys[i][j][1]))
numpy.append(arr, values, axis=None):
简答来说,就是arr和values会重新组合成一个新的数组,做为返回值。而axis是一个可选的值
当axis无定义时,是横向加成,返回总是为一维数组!
Examples -------- >>> np.append([1, 2, 3], [[4, 5, 6], [7, 8, 9]]) array([1, 2, 3, 4, 5, 6, 7, 8, 9])
numpu.append(arr,values,axis=None)
将values插入到目标arr的最后。
注意,这里values跟arr应该为相同维度的向量
参考原文链接:numpy的numpy.delete()/insert()/append()函数 - 开贰锤
ys = np.array(ys)
参考原文链接:python中数组(numpy.array)的基本操作 - fu6543210的博客
np.array(rst).T
转置函数.T,将原shape为(n,m)的数组转置为(m,n),一维数组转置不变
参考原文链接:python数据分析(3)--numpy数组形状转换.T/.reshape()/.resize() - weixin_42695959的博客博客
rst.extend([(x,y) for x in range(max(x1,o[0]), min(x2, shape[2]))])
1. 列表可包含任何数据类型的元素,单个列表中的元素无须全为同一类型。
2. append() 方法向列表的尾部添加一个新的元素。只接受一个参数。
3. extend()方法只接受一个列表作为参数,并将该参数的每个元素都添加到原有的列表中。
数组拼接方法一
思路:首先将数组转成列表,然后利用列表的拼接函数append()、extend()等进行拼接处理,最后将列表转成数组。
示例1:
>>> import numpy as np
>>> a=np.array([1,2,5])
>>> b=np.array([10,12,15])
>>> a_list=list(a)
>>> b_list=list(b)
>>> a_list.extend(b_list)
>>> a_list
[1, 2, 5, 10, 12, 15]
>>> a=np.array(a_list)
>>> a
array([ 1, 2, 5, 10, 12, 15])
该方法只适用于简单的一维数组拼接,由于转换过程很耗时间,对于大量数据的拼接一般不建议使用。
参考原文链接:numpy数组拼接方法介绍 - zyl1042635242的专栏
python中的append的用法 - m0_37870649的博客
for i in zip(rs[::2],rs[1::2])
参考原文链接:Python zip() 函数 | 菜鸟教程