我试图通过执行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方法后的结果。如您所见,提取的图像与橙色的大小相同,但它不包含橙色而不是蒙版本身。
编辑3 - @DanMašek和@lightalchemist,我终于可以提取任何前景图片了。
谢谢
答案 0 :(得分:1)
错误告诉您正在尝试对条目不是整数的矩阵执行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 < 255, :] = 0
答案 1 :(得分:1)
我使用了上面提供的代码,但只改变了使用cv2.bitwise_and()
的行:
new_image = cv2.bitwise_and(img_rgb, img_rgb, mask = equalize)
这就是我得到的和你所期望的(我猜):
修改强>
我明白了,你想要用最大面积的轮廓图像来掩盖你的图像。在下面的附加片段中,我将包含最大区域轮廓的图像二值化,以用作遮罩。
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)
这就是我得到的:
与上图相比,您没有在感兴趣的物体内看到这些洞。