首页 > 解决方案 > 更改 UIImage 中的白色像素

问题描述

我有一个 UIImage,它是一个轮廓,一个是填充的,两者都是从 OpenCV 创建的,一个来自抓取切割,另一个来自结构化元素。

我的两个图像是这样的:

在此处输入图像描述

在此处输入图像描述

我正在尝试更改轮廓图像中的所有白色像素,因为我想将两个图像合并在一起,所以我最终得到一个红色轮廓和中间的白色填充区域。我正在使用它来将两者合并在一起,并且我知道它不是红色而是粉红色和灰色而不是白色,因为我只是将它们与 alpha 混合在一起。

// Start an image context
UIGraphicsBeginImageContext(grabcutResult.size)
        
// Create rect for this draw session
let rect = CGRect(x: 0.0, y: 0.0, width: grabcutResult.size.width, height: grabcutResult.size.height)
grabcutResult.draw(in: rect)
redGrabcutOutline.draw(in: rect, blendMode: .normal, alpha: 0.5)

let finalImage = UIGraphicsGetImageFromCurrentImageContext()

这个想法是它应该看起来像这样。

在此处输入图像描述

我希望能够快速完成此操作,但我发现的唯一解决方案是针对 ImageView(它只影响内容的呈现方式而不影响底层 UIImage),或者它们涉及逐个像素地循环整个图像。

我正在尝试找到一种解决方案,它将轮廓中的所有白色像素都掩盖为红色,而不必逐个像素地循环整个图像,因为它太慢了。

理想情况下,如果我能让 openCV 只返回红色轮廓而不是白色轮廓会很好,但我认为不可能改变它(也许我错了)。

顺便说一句,使用 swift ......但任何帮助表示赞赏,在此先感谢。

标签: iosswiftopencvuiimage

解决方案


这个想法是bitwise-or将两个掩码“合并”在一起,这两个掩码。由于这个新的组合灰度图像仍然是单个(1 通道)图像,我们需要将其转换为 3 通道,以便我们可以将颜色应用于图像。最后,我们用红色为轮廓蒙版着色以获得我们的结果

在此处输入图像描述

我在 Python OpenCV 中实现了它,但你可以用 Swift 来适应同样的想法

import cv2

# Read in images as grayscale
full = cv2.imread('1.png', 0)
outline = cv2.imread('2.png', 0)

# Bitwise-or masks
combine = cv2.bitwise_or(full, outline)

# Combine to 3 color channel and color outline red
combine = cv2.merge([combine, combine, combine])
combine[outline > 120] = (57,0,204)

cv2.imshow('combine', combine)
cv2.waitKey()

使用 IPython 进行基准测试

In [3]: %timeit combine()
782 µs ± 10.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

使用 Numpy 的 Vectorized 功能,它似乎相当快


推荐阅读