【问题标题】:How to extract a specific section of an image using OpenCV in Python?如何在 Python 中使用 OpenCV 提取图像的特定部分?
【发布时间】:2018-10-01 11:01:41
【问题描述】:

我正在尝试通过执行 Canny 边缘检测来提取图像的一部分。我已成功创建该对象的掩码。但是当我对原始图像执行bitwise_and 操作以提取前景部分时,出现以下错误。

OpenCV Error: Assertion failed ((mtype == CV_8U || mtype == CV_8S) && _mask.sameSize(*psrc1)) in cv::binary_op, file C:\projects\opencv-python\opencv\modules\core\src\arithm.cpp, line 241
    Traceback (most recent call last):
      File "C:\Users\Boudhayan Dev\Desktop\extraction.py", line 37, in <module>
        new_image = cv2.bitwise_and(img_rgb,img_rgb,mask=mask)
    cv2.error: C:\projects\opencv-python\opencv\modules\core\src\arithm.cpp:241: error: (-215) (mtype == CV_8U || mtype == CV_8S) && _mask.sameSize(*psrc1) in function cv::binary_op

我的代码如下-

import cv2
import numpy as np

img_rgb = cv2.imread("3.jpg")
cv2.namedWindow("Original Image",cv2.WINDOW_NORMAL)

img = cv2.cvtColor(img_rgb,cv2.COLOR_RGB2HSV)
img = cv2.bilateralFilter(img,9,105,105)
r,g,b=cv2.split(img)
equalize1= cv2.equalizeHist(r)
equalize2= cv2.equalizeHist(g)
equalize3= cv2.equalizeHist(b)
equalize=cv2.merge((r,g,b))

equalize = cv2.cvtColor(equalize,cv2.COLOR_RGB2GRAY)

ret,thresh_image = cv2.threshold(equalize,0,255,cv2.THRESH_OTSU+cv2.THRESH_BINARY)
equalize= cv2.equalizeHist(thresh_image)


canny_image = cv2.Canny(equalize,250,255)
canny_image = cv2.convertScaleAbs(canny_image)
kernel = np.ones((3,3), np.uint8)
dilated_image = cv2.dilate(canny_image,kernel,iterations=1)


new,contours, hierarchy = cv2.findContours(dilated_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours= sorted(contours, key = cv2.contourArea, reverse = True)[:10]
c=contours[0]
print(cv2.contourArea(c))
final = cv2.drawContours(img, [c], -1, (255,0, 0), 3)



mask = np.zeros(img_rgb.shape,np.uint8)
new_image = cv2.drawContours(mask,[c],0,255,-1,)
new_image = cv2.bitwise_and(img_rgb,img_rgb,mask=mask)


cv2.namedWindow("new",cv2.WINDOW_NORMAL)
cv2.imshow("new",new_image)

cv2.imshow("Original Image",img)
cv2.waitKey() 

注意:- 如果我尝试使用图像的灰度版本执行 bitwise_and,代码可以正常工作。但是 RGB、HSV 或任何其他颜色空间都会出现上述错误。

请帮忙。


编辑 1 - 有问题的图像是这个 -

编辑 2-

以下是使用 Numpy 方法后的结果。如您所见,提取的图像与橙色大小相同,但不包含橙色,而是包含蒙版本身。

EDIT 3- @DanMašek 和 @lightalchemist,我终于可以提取任何前景图像了。

谢谢

【问题讨论】:

  • 请提供一个示例输入图像(例如,您的代码所指的“3.jpg”)。另外,做一些调试——bitwise_and 的两个输入元素的形状和数据类型是什么?
  • 我已编辑。请检查编辑 1。
  • 你能想象你的面具吗?请注意,您可能必须将 numpy 数组的类型转换为 uint8 才能正确可视化它。
  • 问题是您的mask 有3 个通道,但cv2.bitwise_and 的文档明确指出“掩码,8 位单通道数组”...
  • @DanMašek - 谢谢。我按照您的建议添加了 [:2] 并且它起作用了。

标签: python numpy opencv opencv3.0 edge-detection


【解决方案1】:

我使用了上面提供的代码,但只更改了使用 cv2.bitwise_and() 的行:

new_image = cv2.bitwise_and(img_rgb, img_rgb, mask = equalize)

这是我得到的,也是你所期望的(我猜):

编辑

我明白了,你想用面积最大的轮廓图像来掩盖你的图像。在下面的附加 sn-p 中,我对包含最大区域轮廓的图像进行了二值化处理。

new_image = cv2.drawContours(mask,[c], -1, (255,255,255), -1)
new_image_gray = cv2.cvtColor(new_image, cv2.COLOR_BGR2GRAY)
ret, thresh1 = cv2.threshold(new_image_gray, 100, 255, cv2.THRESH_BINARY)
final = cv2.bitwise_and(img_rgb, img_rgb, mask = thresh1)

这是我得到的:

与上图相比,您看不到感兴趣对象内部的那些孔。

【讨论】:

  • 它适用于这个特定的图像。对于其他图像,到处都有不想要的背景图像的痕迹。发生这种情况是因为 `equalize` 变量还存储了对象边缘之外的边缘。只有在通过找到最大轮廓消除它们之后,我们才最终得到前景图像边缘。这就是为什么在我的代码中不使用均衡器作为掩码。不过还是谢谢。
  • @BoudhayanDev 我已经编辑了答案。希望它符合您的期望。
【解决方案2】:

错误是告诉您您正在尝试对条目不是整数的矩阵执行 bitwise_and 操作。我相信矩阵也必须具有相同数量的通道。这就是它适用于您的灰度图像但不适用于 HSV 图像的原因。

与使用 bitwise_and 相比,使用 numpy 矩阵向量化来执行掩码更容易、更灵活,如下所示:

mask = np.zeros_like(img_rgb, dtype=np.uint8)

# I believe you want to draw the filled in contour on the mask
# You code actually assigns the resulting mask to new_image
# But that does not affect things as drawContours modifies mask in place
mask = cv2.drawContours(mask, [c] ,0, 255, -1) 

new_image = img_rgb.copy()
new_image[mask < 255] = 0  # Set values not masked to be 0

请注意,如果您的掩码是单通道矩阵而不是 3 通道矩阵,则必须将代码修改为

new_image[mask &lt; 255, :] = 0

【讨论】:

  • 我认为这些值不是整数,主要是因为之前执行的均衡步骤。您的代码有效,但问题是新图像将掩码作为输出。我想要前景图像而不是蒙版。我将编辑答案以解释发生了什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-15
  • 2016-09-08
  • 1970-01-01
  • 2015-08-15
  • 1970-01-01
  • 2022-12-24
相关资源
最近更新 更多