github地址(更新中):https://github.com/SunnyWuYang/Paint-Bucket-with-Gaps
参考:
[1] opencv实现画板效果:
https://blog.csdn.net/qq_42191914/article/details/105035921
版本二目的与功能:
- 创建简易版的画板工具为算法提供实验图像
- 利用自己绘制的图像测试算法
算法实现
import os
import sys
import cv2
import numpy as np
"""
TODO list in future versions:
1. add button and label
2. refactor code
"""
class Painter:
"""
默认情况下,程序为绘画模式,即按下鼠标左键后并拖动可以进行绘制。
-退出按'q'
"""
def __init__(self, img_size=(600, 800, 3), circle_radius=8, win_name='my Drawing Board', save_path=None, color=(1, 1, 255)):
"""
:param img_size:画板大小,若指定background则忽略此参数
:param circle_radius:‘circle'模式下圆形的半径
:param win_name:窗口名
:param save_path:绘图结果保存地址
:param color:画笔颜色
"""
self.win_name = win_name
self.save_path = save_path
self.brush_color = color
self.circle_radius = circle_radius
self.layer_back = np.ones(
img_size, dtype=np.uint8)
self.layer_back = self.layer_back*255
# 鼠标是否产生了一次“按下—松开”的click过程
self.click = False
# 是否处于绘制状态
self.drawing = False
self.x2, self.y2 = -1, -1 # (circle模式)记录"circle"模式且未绘制状态下,鼠标上次的位置
def saveForeground(self, save_path, mode='black_mask'):
"""
当使用background时,保存前景图像
:param save_path: 前景图像保存地址
:param mode:模式,'raw'按原前景图存,'black_mask'则按黑白格式存(被画的地方为黑,其余地方为白),'white_mask'相反
:return:
"""
# TODO 实现其余的mode
if mode == 'black_mask':
# 初始化为全白
fore = np.ones(shape=self.layer_back.shape,
dtype=np.uint8)
fore = fore*255
fore[(self.layer_back[:, :] == np.array(self.brush_color)).all(
axis=2)] = np.array([0, 0, 0]) # 被画的地方设为全黑
cv2.imwrite(save_path, fore)
else:
print("模式错误!")
sys.exit(0)
def mouseEvent(self, event, x, y, flag, param):
# (1)鼠标左键按下事件——开启绘图状态
if event == cv2.EVENT_LBUTTONDOWN:
self.drawing = True
self.x2, self.y2 = -1, -1
# (2)鼠标移动事件——绘图
elif event == cv2.EVENT_MOUSEMOVE:
if self.drawing: # 点击后未抬起的移动
cv2.circle(self.layer_back, (x, y), radius=self.circle_radius,
color=self.brush_color,
thickness=-1)
# (3)鼠标左键抬起事件——结束绘图状态
elif event == cv2.EVENT_LBUTTONUP:
self.drawing = False
self.click = True
def main(self):
cv2.namedWindow(self.win_name, cv2.WINDOW_NORMAL)
cv2.setMouseCallback(self.win_name, self.mouseEvent) # 鼠标事件回调函数
while True:
cv2.imshow(self.win_name, self.layer_back)
key = cv2.waitKey(1)
if key == ord('q'):
print("The windows are destroyed")
break
if self.save_path:
self.saveForeground(self.save_path)
cv2.destroyAllWindows()
if __name__ == '__main__':
painter = Painter(img_size=(150, 200, 3),
circle_radius=4,
save_path='layer_back.png',
color=(0, 0, 255))
painter.main()
测试
if __name__ == '__main__':
img = cv2.imread(
'layer_back.png', 0)
img = np.array(img, dtype=np.uint8)
img[img > 0] = 1
seedX = 65
seedY = 83
gap = 10
result = floodfill_with_gap(img, seedX, seedY, gap)
cv2.imwrite('result.png', result*255)
左:画图效果;中:储存结果;右:算法处理结果