请先参考此链接:
在上面链接的示例中,各个精灵的边界框不重叠,因此接受的答案中的代码运行良好,并且所有精灵都提取在单独的文件中。
但是假设精灵的包装方式不同,即使单个图像没有重叠,它们的边界框也会重叠:
那么上面的代码根本无法正常工作,并且只输出一个文件,因为边界框会相交。
有人如何使用 OpenCV 解决这个问题?
如果不使用 OpenCV,我的方法是:
除了我上面描述的方法之外,有没有一种方法可以使用 OpenCV 来做到这一点?我可以用我的方法做到这一点,但我想了解更多有关 OpenCV 及其功能的信息,但我只是一个初学者,仍在学习中。
您可以用白色填充每个轮廓,然后生成仅包含该轮廓的图像。之后,通过获取边界矩形的属性来应用常规裁剪。这是代码:
im = cv2.imread("trees.png") # read image
imGray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) # convert to gray
contours, _ = cv2.findContours(imGray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # contouring
sortedContours = sorted(contours, key=cv2.contourArea, reverse=True) # sorting, not necessary...
for contourIdx in range(0,len(sortedContours)-1): # loop with index for easier saving
contouredImage = im.copy() # copy image
contouredImage = cv2.drawContours(contouredImage, sortedContours, contourIdx, (255,255,255), -1) # fill contour with white
extractedImage = cv2.inRange(contouredImage, (254,254,254), (255,255,255)) # extract white from image
resultImage = cv2.bitwise_and(im, im, mask=extractedImage) # AND operator to get only one filled contour at a time
x, y, w, h = cv2.boundingRect(sortedContours[contourIdx]) # get bounding box
croppedImage = resultImage[y:y + h, x:x + w] # crop
cv2.imwrite("contour_"+str(contourIdx)+".png", croppedImage) # save
结果看起来也不错,我只发布最大的和最小的作为示例:
V2.0:使其适用于两个图像
由于某种原因,第一张图像的所有背景的绿色通道上都有 255。这就是为什么只检测到一个大轮廓的原因。我添加了几行代码来预处理图像并考虑 Alpha 通道。这是代码:
im = cv2.imread("trees.png", cv2.IMREAD_UNCHANGED) # read image
b, g, r, alpha = cv2.split(im.copy()) # split image
g[g==255] = 0 # for the first image where the green channel has 255 on all background pixels
imBGR = cv2.merge([b,g,r]) # recombine image in BGR format
imGray = cv2.cvtColor(imBGR, cv2.COLOR_BGR2GRAY) # convert to gray
contours, _ = cv2.findContours(imGray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # contouring
sortedContours = sorted(contours, key=cv2.contourArea, reverse=True) # sorting, not necessary...
for contourIdx in range(0,len(sortedContours)-1): # loop with index for easier saving
contouredImage = imBGR.copy() # copy BGR image
contouredImage = cv2.drawContours(contouredImage, sortedContours, contourIdx, (255,255,255), -1) # fill contour with white
extractedImage = cv2.inRange(contouredImage, (254,254,254), (255,255,255)) # extract white from image
resultImage = cv2.bitwise_and(imBGR, imBGR, mask=extractedImage) # AND operator to get only one filled contour at a time
x, y, w, h = cv2.boundingRect(sortedContours[contourIdx]) # get bounding box
croppedImage = resultImage[y:y + h, x:x + w] # crop
cv2.imwrite("trees_2_contour_"+str(contourIdx)+".png", croppedImage) # save
我不会再费心添加结果图像,因为它们和以前一样。然而,这是我正在谈论的带有绿色背景的第一个示例的图像:
代码:
im = cv2.imread("trees2.png", cv2.IMREAD_UNCHANGED) # read image
b, g, r, alpha = cv2.split(im.copy()) # split image
imBGR = cv2.merge([b,g,r]) # recombine image in BGR format
plt.imshow(imBGR)
图片:
我用
g[g==255] = 0
解决了这个问题