Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
与Python OpenCV绑定中的copyTo等效?_Python_Image_Opencv_Image Processing - Fatal编程技术网

与Python OpenCV绑定中的copyTo等效?

与Python OpenCV绑定中的copyTo等效?,python,image,opencv,image-processing,Python,Image,Opencv,Image Processing,OpenCV具有copyTo功能,可以将遮罩区域从一个垫子复制到另一个垫子 在Python绑定中,这与什么是等价的?我想用一个二进制掩码将一个图像的一个区域复制到另一个图像 请注意,如果这正是您想要的,但对于在Python中使用掩码进行复制,我将使用cv2.bitwise new_image = cv2.bitwise_and(old_image,binary_mask) 根据输出矩阵是否已初始化,执行两项操作之一。如果输出矩阵未初始化,则使用带掩码的copyTo创建与输入类型相同的新输出矩

OpenCV具有copyTo功能,可以将遮罩区域从一个垫子复制到另一个垫子


在Python绑定中,这与什么是等价的?我想用一个二进制掩码将一个图像的一个区域复制到另一个图像

请注意,如果这正是您想要的,但对于在Python中使用掩码进行复制,我将使用
cv2.bitwise

new_image = cv2.bitwise_and(old_image,binary_mask)
根据输出矩阵是否已初始化,执行两项操作之一。如果输出矩阵未初始化,则使用带掩码的
copyTo
创建与输入类型相同的新输出矩阵,并且所有通道上的所有值都设置为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))
但上述代码假设
img
mask
共享相同数量的通道。如果像我之前假设的那样,使用彩色图像作为源,使用二维遮罩,这会变得很棘手。因此,通道的总数是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
。在这种情况下,您首先要做的是使用确定掩码中所有非零的位置,然后使用这些位置对图像进行索引或切片,以及从中进行复制。我们还必须注意两幅图像之间的通道数量,就像第一种方法一样:

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")
下面是两种方法的运行示例。我将使用摄影师图像,这是大多数图像处理算法中看到的标准测试图像

我还人为地制作了图像的颜色,尽管它被视为灰度,但强度将被复制到所有通道。我还将定义一个掩码,它只是左上角的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

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

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

# Define other image
other_image = (255*np.random.rand(*img.shape)).astype(np.uint8)
使用第二种方法运行代码后,我现在看到了以下图像:


如您所见,图像的左上角已根据设置为
True

的遮罩位置进行了更新。哦,对不起,我不确定问题是什么。实际上,在查看文档时,
cv::Mat::copyTo
会将不属于遮罩的像素归零,因此这是正确的。我会在上面留下我的答案,以防OP想要复制不受掩码影响的像素。我不是python专家。有新的答案吗?我可以用python制作一个关于copyTo的PR(opencv),但这有用吗?(link)同时还有一个,但它似乎只实现了第一种情况(目的地被初始化为零)@LBerger:第二种方法(dst已经初始化)不也应该在您的PR中考虑吗?是的。我的回答解决了这两种情况,
copyTo
就是这样做的。PR未实施完整的解决方案。