算法原理
采用了种子填充算法,种子填充算法的原理比较简单。
即在多边形内选取一个起始点,从这个起始点出发,可选取上下左右四个方向前进,若前进的方向不是多边形的边界,则前进到该像素点,填充上新颜色后,再以此点位起始点,不断递归上述过程,知道碰到多边形边界。(有点像深度优先算法)。
算法步骤
1)先定义一个二维矩阵,定义所有的像素的为0
a=np.zeros((450,450))
2)利用我之前做过的DDA算法,将多边形的边绘制出来。同时将边所经过的像素点都记为2(即边界点)。
draw(0, 40, 40, 0)
draw(40, 0, 80, 40)
draw(0, 40, 60, 60)
draw(60, 60, 80, 40)
a[int(round(x))][int(round(y))] = 2
得到未填充的多边形
3)编写种子填充算法,参数x,y为当前起始点,先判断当前起始点是否是边界,如果不是,则将该点记为1(即填充点),同时上下左右四个点代入递归。
# 种子填充算法
def seedFill(x, y):
if(a[x][y] == 0):
a[x][y] = 1
if(a[x+1][y] == 0):
seedFill(x+1, y)
if(a[x][y+1] == 0):
seedFill(x, y+1)
if(a[x-1][y] == 0):
seedFill(x-1, y)
if(a[x][y-1] == 0):
seedFill(x, y-1)
4)至此,我们已经在二维矩阵中有了以下信息,0表示空白区域,1表示填充点,2表示边界点。
根据矩阵值的不同,绘制出不同颜色的点,完成填充。
# 在矩阵a中,0表示空白点,1表示填充点,2表示边界点
# 根据矩阵中值的不同来填充
for i in range(0, 82):
for j in range(0, 80):
if(a[i][j] == 1):
plt.plot(i, j, 'r.', markersize = 1)
elif(a[i][j] == 2):
plt.plot(i, j, 'b.', markersize = 1)
算法结果
1.填充前
2.填充后
算法源码
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import MaxNLocator
np.set_printoptions(threshold=np.inf)
# 初始化450*450的矩阵为零
a=np.zeros((450,450))
# 种子填充算法
def seedFill(x, y):
if(a[x][y] == 0):
a[x][y] = 1
if(a[x+1][y] == 0):
seedFill(x+1, y)
if(a[x][y+1] == 0):
seedFill(x, y+1)
if(a[x-1][y] == 0):
seedFill(x-1, y)
if(a[x][y-1] == 0):
seedFill(x, y-1)
# DDA直线扫描算法,用于绘制多边形的边界
def DDA(x1, y1, x2, y2):
dx, dy = x2 - x1, y2 - y1
k = dy/dx
x, y = x1, y1
#网格线
plt.grid()
#x轴y轴数值取整
plt.gca().xaxis.set_major_locator(MaxNLocator(integer=True))
plt.gca().yaxis.set_major_locator(MaxNLocator(integer=True))
#绘点
for i in range(0, int(abs(dx)+1)):
#需要四舍五入
plt.plot(int(round(x)), int(round(y)), 'b.', markersize = 1)
a[int(round(x))][int(round(y))] = 2
x += 1
y += float(k)
# 绘制多边形的边
def draw(x, y, xEnd, yEnd):
if xEnd < x:
x,y, xEnd, yEnd = xEnd, yEnd, x, y
DDA(x, y, xEnd, yEnd)
# 绘制多边形
def drawLine():
draw(0, 40, 40, 0)
draw(40, 0, 80, 40)
draw(0, 40, 60, 60)
draw(60, 60, 80, 40)
#网格线
plt.grid()
plt.show()
if __name__ == '__main__':
a[1][1]=1
drawLine()
#网格线
plt.grid()
# 选取(40,18)作为种子起始点
seedFill(40,18)
# 在矩阵a中,0表示空白点,1表示填充点,2表示边界点
# 根据矩阵中值的不同来填充
for i in range(0, 82):
for j in range(0, 80):
if(a[i][j] == 1):
plt.plot(i, j, 'r.', markersize = 1)
elif(a[i][j] == 2):
plt.plot(i, j, 'b.', markersize = 1)