This repository has been archived by the owner on May 19, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathfloodfill.py
125 lines (110 loc) · 4.39 KB
/
floodfill.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
'''
@File : floodfill.py
@Time : 2020/12/05 09:07:38
@Author : Kearney
@Version : 0.0.0
@Contact : [email protected]
@License : GPL 3.0
@Desc : 种子填充算法。基于pygame
鼠标左键确定凸多边形的点,右键封闭图形开始种子填充
surface.get_at(pixel)返回点的RGBA颜色值,可直接忽略和RGB比较是否相等
种子目前的确定方法是开始三个点的中点,因此画凸多边形没毛病,凹多边形会存在bug,
可以考虑使用鼠标点种子点
ref: [python有栈吗](https://www.php.cn/python-tutorials-424395.html)
[获取pygame中图像的单个像素的颜色](http://cn.voidcc.com/question/p-nwvuldtn-bs.html)
'''
import pygame
import sys
class Stack:
'''
模拟栈
push() 把一个元素添加到栈的最顶层
pop() 删除栈最顶层的元素,并返回这个元素
peek() 返回最顶层的元素,并不删除它
isEmpty() 判断栈是否为空
size() 返回栈中元素的个数
'''
def __init__(self):
self.items = []
def isEmpty(self):
return len(self.items) == 0
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
if not self.isEmpty():
return self.items[len(self.items) - 1]
def size(self):
return len(self.items)
def FloodFill(surface, pixel, newColor, boundaryColor):
'''
种子填充,需自行确定种子,区域太大时递归十分耗时
'''
s = Stack()
s.push(pixel)
while (not s.isEmpty()):
pixel = s.pop() # 出栈
try:
if ((surface.get_at(pixel) != newColor)
and (surface.get_at(pixel) != boundaryColor)): # 颜色和边界判断
surface.set_at(pixel, newColor) # 着色
pygame.display.update() # 一个点更新一次画面,会耗费较大时间,不需要可注释掉
px = pixel[0]
py = pixel[1]
s.push((px - 1, py)) # 入栈
s.push((px, py + 1))
s.push((px + 1, py))
s.push((px, py - 1))
except Exception as e:
print("温馨提示: ", e, ", 请按照凸多边形要求取点")
sys.exit(0)
# 颜色设置
FILLCOLOR = (0, 255, 0)
BOUNDARYCOLOR = (255, 0, 0)
# 窗体大小设置
WIDTH = 920
HEIGHT = 640
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pixels = [] # 存储点的列表
isdone = False # 取点是否完成
while True:
# 内外边框的大规模递归示例,耗时有些长
# pygame.draw.rect(screen, BOUNDARYCOLOR, [60, 60, 100, 100], 1)
# pygame.draw.rect(screen, BOUNDARYCOLOR, [20, 20, WIDTH - 40,
# HEIGHT - 40], 1)
# FloodFill(screen, (270, 70), FILLCOLOR, BOUNDARYCOLOR)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit(0)
if event.type == pygame.MOUSEBUTTONDOWN:
if (pygame.mouse.get_pressed()[0]) and not isdone: # 鼠标左键按下,画点
pos = pygame.mouse.get_pos()
pixels.append(pos)
screen.set_at(pos, BOUNDARYCOLOR)
print("Left btn ", pos, len(pixels), pixels)
if (pygame.mouse.get_pressed()[2]) and not isdone: # 鼠标右键按下,重置
if len(pixels) > 2:
length = len(pixels)
pygame.draw.line(screen, BOUNDARYCOLOR, pixels[length - 1],
pixels[0], 1)
print("Right btn")
isdone = True
x = y = 0
for i in range(0, 3): # 求种子点,必需逆时针画点,求开始三个点的中点
x = x + pixels[i][0]
y = y + pixels[i][1]
FloodFill(screen, (x // 3, y // 3), FILLCOLOR,
BOUNDARYCOLOR)
else:
print("点数太少,请继续pick一个点")
if len(pixels) > 1:
length = len(pixels)
# print(length)
pygame.draw.line(screen, BOUNDARYCOLOR, pixels[length - 2],
pixels[length - 1], 1)
pygame.display.update()