切换填充颜色(黑色或白色取决于所选像素颜色)

Toggling of floodfill colors (either black or white depending on the pixel color selected)

我正在编写一个简单的程序,通过单击图像的不同区域逐渐填充(使用 floodfill)图像(带有随机白色矩形的黑色背景)变成全白。顺利完成。

所以我想通过在填充白色和黑色之间切换来让它更有趣。比如,如果我点击的像素是白色区域的一部分,则将其填充为黑色。否则,如果它是黑色区域的一部分,则将其填充为白色。

然而,当我将一些框变成白色后,在随后的点击后它拒绝变成黑色(无法切换回颜色)。此外,因为我的矩形是使用 3 或 4 像素粗的线条绘制的,所以在将所有线条更改为黑色之后,这些线条似乎仍然 'remember' 存在,这样当我点击某些黑暗区域时,偶尔会出现该区域(被那些不可见的 'previous' 线包围)会变成白色。

我已经尝试打印像素颜色以确认拾取的颜色确实是白色或黑色,但 floodfill 没有用正确的替代颜色填充它(由我的 if/else 循环编写)

import numpy as np
import cv2 as cv
import random

width = 800
height = 500
img = np.zeros((height, width), np.uint8)
mask = np.zeros((height+2, width+2), np.uint8)


def click_event(event, x, y, flags, param):
    if event == cv.EVENT_LBUTTONDOWN:
        font = cv.FONT_HERSHEY_PLAIN
        strxy = "X: {0}  Y: {1}".format(x,y)
        print(strxy)
        fillmeup(x, y)
        cv.imshow("test", img)

def fillmeup(x, y):
    print(img[y,x])
    if img[y,x] == 0:
        cv.floodFill(img, mask, (x, y), 255)

    elif img[y,x] == 255:
        cv.floodFill(img, mask, (x, y), 0)

def drawboxes(qty):
    global img
    for _ in range(qty):
        w = int(random.random()*width)
        h = int(random.random()*height)
        x = random.randrange(0, width-w)
        y = random.randrange(0, height-h)
        img = cv.rectangle(img, (x, y), (x+w, y+h), 255, 2)

drawboxes(7)

cv.imshow("test", img)
cv.setMouseCallback("test", click_event)

cv.waitKey(0)
cv.destroyAllWindows() 

好吧,我希望随后每次点击黑色区域都会产生白色,反之亦然,但它并没有发生。 当它确实切换回白色时,它似乎被已经变成黑色的不可见线条所包围。

下面是附加的示例结果。 01_start

02_selecting 2 boxes

03_selecting one of the thin white lines changes them to black: correct outcome

04_selecting some random random black space, but yet bounded white rectangles appear. the boundaries were the original white lines. weird outcome

floodFill() 不仅更新图像,还更新 mask

On output, pixels in the mask corresponding to filled pixels in the image are set to 1 or to the a value specified in flags as described below. It is therefore possible to use the same mask in multiple calls to the function to make sure the filled areas do not overlap.

def fillmeup(x, y):
    print(img[y,x])
    mask = np.zeros((height+2, width+2), np.uint8)
    if img[y,x] == 0:
       cv.floodFill(img, mask, (x, y), 255)
    else:
       cv.floodFill(img, mask, (x, y), 0)

如您所述,这对我有用。如果你根本不需要掩码,你可以写

cv.floodFill(img, None, (x, y), ...)

这对我也适用,但我没有找到任何证据表明 None 掩码参数对 floodFill() 是合法的。如果您在任何权威来源中发现它是否合法,请通知我更新答案。