python - Python OpenCV 绑定(bind)中的 copyTo 是否等效?

标签 python image opencv image-processing

OpenCV 具有 copyTo 函数,可以将蒙版区域从一个 Mat 复制到另一个。

http://docs.opencv.org/3.1.0/d3/d63/classcv_1_1Mat.html#a4331fa88593a9a9c14c0998574695ebb

Python 绑定(bind)中的 this 等价物是什么?我想用二进制掩码将图像的一个区域复制到另一个图像。

最佳答案

cv::Mat::copyTo根据输出矩阵是否已初始化,做两件事之一。如果您的输出矩阵未初始化,则使用带有掩码的 copyTo 创建一个与输入类型相同的新输出矩阵,并且所有 channel 的所有值都设置为 0。一旦发生这种情况,由掩码定义的图像数据将被复制,矩阵的其余部分将设置为 0。如果您的输出矩阵初始化并且已经包含内容,copyTo 从源复制掩码中定义的像素,并在目标中保留不属于掩码的像素。因此,由源图像中的掩码定义的像素替换被复制到输出中。

因为 OpenCV 现在使用 numpy 与库进行交互,所以执行这两种方法都非常容易。为了与这篇文章中看到的其他答案区分开来,第一种方法可以通过简单地以元素方式将掩码与图像相乘来完成。假设您的输入称为 img 并且您的二进制掩码称为 mask 我假设掩码是 2D,只需执行以下操作:

import numpy as np
import cv2

mask = ... # define mask here
img = cv2.imread(...) # Define input image here

# Create new image
new_image = img * (mask.astype(img.dtype))

虽然以上代码假定 imgmask 共享相同数量的 channel 。如果您使用彩色图像作为源和我已经假设的 2D 蒙版,它会变得很棘手。因此, channel 总数是 2 而不是 3,所以上面的语法会给你一个错误,因为两者之间的维度不再兼容。当您使用彩色图像时,您需要适应这一点。您可以通过向掩码添加单例三维来实现此目的,以便可以利用广播。

import numpy as np
import cv2

mask = ... # define mask here
img = cv2.imread(...) # Define input image here

# Create new image
# Case #1 - Other image is grayscale and source image is colour
if len(img.shape) == 3 and len(mask.shape) != 3:
    new_image = img * (mask[:,:,None].astype(img.dtype))
# Case #2 - Both images are colour or grayscale
elif (len(img.shape) == 3 and len(mask.shape) == 3) or \
   (len(img.shape) == 1 and len(mask.shape) == 1):
    new_image = img * (mask.astype(img.dtype))
# Otherwise, we can't do this
else:
    raise Exception("Incompatible input and mask dimensions")

对于第二种方法,假设我们有另一个名为 other_image 的图像,您希望将掩码定义的该图像中的内容复制回目标图像 img。在这种情况下,您首先要做的是使用 numpy.where 确定掩码中非零的所有位置。 ,然后使用这些索引或切片到您的图像以及您要复制的位置。就像第一种方法一样,我们还必须注意两个图像之间的 channel 数:

import numpy as np
import cv2

mask = ... # define mask here
img = cv2.imread(...) # Define input image here
other_image = cv2.imread(...) # Define other image here

locs = np.where(mask != 0) # Get the non-zero mask locations

# Case #1 - Other image is grayscale and source image is colour
if len(img.shape) == 3 and len(other_image.shape) != 3:
    img[locs[0], locs[1]] = other_image[locs[0], locs[1], None]
# Case #2 - Both images are colour or grayscale
elif (len(img.shape) == 3 and len(other_image.shape) == 3) or \
   (len(img.shape) == 1 and len(other_image.shape) == 1):
    img[locs[0], locs[1]] = other_image[locs[0], locs[1]]
# Otherwise, we can't do this
else:
    raise Exception("Incompatible input and output dimensions")

下面是两种方法的运行示例。我将使用 Cameraman 图像,它是大多数图像处理算法中常见的标准测试图像。

enter image description here

我还人为地制作了图像颜色,即使它被可视化为灰度,但强度将被复制到所有 channel 。我还将定义一个掩码,它只是左上角的 100 x 100 子区域,因此我们将创建一个仅复制该子区域的输出图像:

import numpy as np
import cv2

# Define image
img = cv2.imread("cameraman.png")

# Define mask
mask = np.zeros(img.shape, dtype=np.bool)
mask[:100, :100] = True

当您使用第一种方法并且当我们显示结果时,我们得到:

enter image description here

我们可以看到我们创建了一个输出图像,其中左上角的 100 x 100 子区域包含我们的图像数据,其余像素设置为 0。这取决于设置为 True 的掩码位置。对于第二种方法,我们将创建另一张随机图像,其大小与跨越所有 channel 的 [0, 255] 的输入图像相同。

# Define other image
other_image = (255*np.random.rand(*img.shape)).astype(np.uint8)

一旦我们用第二种方法运行完代码,我现在得到这张图片:

enter image description here

如您所见,图像的左上角已根据设置为 True 的 mask 位置进行了更新。

关于python - Python OpenCV 绑定(bind)中的 copyTo 是否等效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41572887/

相关文章:

python - django redis 与 django 显示 ulimit 错误

python - 尝试使用 Python 从 excel 电子表格中删除第一行

java - 在 Java 中使用 HTMLEditorKit,如何找到 <img src=...> 标签将使用的本地文件路径?

c++ - 在 OpenCV (C++) 中打印多维垫

image - OpenCV:在图像上绘图

python - 网络抓取(获取表格时出现问题)

python - 如果所有字段均为 None,则将 Pydantic 模型返回为 None

python - PySide:将图像添加到工具提示

ios - 使用 UIGraphicsImageRenderer 绘制图像时为什么要使用大量内存?

python - 获得包含折线图的两个图像的相似性度量的好方法是什么?