python - 多个矩形的Python OpenCv交集
问题描述
我目前正在开展一个项目来识别图像中的文本部分。我在它们周围画了矩形,如下所示:
我不想要的是,如图 2 所示,让一个矩形的一部分成为另一个矩形的一部分,例如。pic3 是 pic2 的一部分。这意味着这些部分应该被剪掉或变成白色,我不知道该怎么做。对于这些矩形的绘制,我使用以下代码部分:
image = cv2.imread(Photopath)
CopyImg = np.copy(image)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, ((1, 1)), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# Create rectangular structuring element and dilate
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (6, 9))
dilate = cv2.dilate(thresh, kernel, iterations=4)
# Find contours and draw rectangle
cnts = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
x,y,w,h = cv2.boundingRect(c)
cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 2)
paragraph = CopyImg[y:y+h,x:x+w]
cv2.imwrite(outpath, paragraph)
我想我需要以某种方式将它们相交并从一个矩形中切出与所有其他触摸它的坐标的矩形?
解决方案
这是一种可能的方法。首先,我将尝试检测每个文本块。块(或边界框)是否重叠并不重要。在获取图像上所有 blob 的所有边界框后,我将检测边界框重叠。如果边界框与其他边界框重叠,这意味着相同的文本块将在两个或多个图像之间共享。我将裁剪该部分并用白色矩形填充重叠区域,这样内容将仅显示在一张图像上。
这些是重要的步骤:
使用形态来获得漂亮的文本块。
检测这些块上的轮廓并将这些轮廓转换为 边界框。
遍历所有边界框并:
裁剪每个边界框
检查可能的重叠。如果发现重叠(或相交),请使用边界框信息在该区域上绘制一个白色矩形。
这是代码,首先我们需要得到那些漂亮的文本块:
import numpy as np
import cv2
# image path
path = "C:/opencvImages/"
fileName = "sheet05.png"
# Reading an image in default mode:
inputImage = cv2.imread(path + fileName)
# Some deep copies of the input mat:
inputCopy = inputImage.copy()
cleanInputCopy = inputCopy.copy()
# Grayscale conversion:
grayscaleImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY)
# Thresholding:
threshValue, binaryImage = cv2.threshold(grayscaleImage, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
binaryImage = 255 - binaryImage
很标准的东西。只是read
图像,将其转换为grayscale
并通过Otsu
. 您会注意到我创建了一些输入的深层副本。这些主要用于可视化结果,因为我最初绘制了每个bounding box
找到的和每个重叠的区域。
应用一些非常强烈的形态来获得最好的文本块。我在这里应用扩张 + 侵蚀,每个操作有 10 次迭代:
# Dilate and Erode with a big Structuring Element:
kernelSize = 5
structuringElement = cv2.getStructuringElement(cv2.MORPH_RECT, (kernelSize, kernelSize))
iterations = 10
dilatedImage = cv2.morphologyEx(binaryImage, cv2.MORPH_DILATE, structuringElement, None, None, iterations,
cv2.BORDER_REFLECT101)
erodedImage = cv2.morphologyEx(dilatedImage, cv2.MORPH_ERODE, structuringElement, None, None, iterations,
cv2.BORDER_REFLECT101)
最后一个片段为您提供此图像:
现在,获取该图像的外轮廓并计算边界框:
# Find the big contours/blobs on the filtered image:
contours, hierarchy = cv2.findContours(erodedImage, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
contours_poly = [None] * len(contours)
boundRect = []
# Alright, just look for the outer bounding boxes:
for i, c in enumerate(contours):
if hierarchy[0][i][3] == -1:
contours_poly[i] = cv2.approxPolyDP(c, 3, True)
boundRect.append(cv2.boundingRect(contours_poly[i]))
现在,重要的部分来了。我们将遍历每个bounding box
. 裁剪图像,并检查最近bounding box
用于裁剪图像的图像是否在另一个内部bounding box
(重叠)。如果是这种情况,只需在该区域内绘制一个大的白色矩形并继续进行新的裁剪:
# Loop thru all bounding boxes:
for i in range(len(boundRect)):
# Get current boundRect:
sourceRect = boundRect[i]
# Crop the roi:
croppedImg = cleanInputCopy[sourceRect[1]:sourceRect[1] + sourceRect[3],
sourceRect[0]:sourceRect[0] + sourceRect[2]]
# Check against other bounded rects:
for j in range(len(boundRect)):
# Get target boundRect:
targetRect = boundRect[j]
# Check for intersections:
if i != j:
foundIntersect, overlappedRect = checkIntersection(sourceRect, targetRect)
if foundIntersect:
# Found some overlapped rects, draw white rectangle at this location:
cv2.rectangle(cleanInputCopy, (int(overlappedRect[0]), int(overlappedRect[1])),
(int(overlappedRect[0] + overlappedRect[2]), int(overlappedRect[1] + overlappedRect[3])),
(255, 255, 2550), -1)
cv2.rectangle(inputCopy, (int(boundRect[i][0]), int(boundRect[i][1])),
(int(boundRect[i][0] + boundRect[i][2]), int(boundRect[i][1] + boundRect[i][3])), color, 5)
这些是为每个二进制 blob 检测到的边界框:
代码检测重叠区域并在交叉点上绘制一个白色矩形,这样它将不再显示在以下裁剪上:
这些是作物(请注意,这些是单独的图像):
现在,检测边界框相交的辅助函数是这样的:
# Check for boxA and boxB intersection
def checkIntersection(boxA, boxB):
x = max(boxA[0], boxB[0])
y = max(boxA[1], boxB[1])
w = min(boxA[0] + boxA[2], boxB[0] + boxB[2]) - x
h = min(boxA[1] + boxA[3], boxB[1] + boxB[3]) - y
foundIntersect = True
if w < 0 or h < 0:
foundIntersect = False
return(foundIntersect, [x, y, w, h])
这非常简单。它只是获取两个边界矩形的坐标并计算相交区域。如果width
orheight
小于零,则不存在交集。
推荐阅读
- r - 匹配来自 R 中两个不同数据帧的数据,如 Excel VLOOKUP
- r - 运行所有测试 R 包的测试?
- node.js - 如何强制我的函数在继续之前等待承诺?
- javascript - 如何检查用户是否具有来自另一个 Discord 服务器的角色
- html - 页面中心的 4 个响应式按钮
- python - 'int' 对象不可下标 PYTHON
- c++ - 创建一个包含指向数组的指针的结构
- javascript - 如何在 JavaScript 中的 Quiz App 中提问 5 次?
- reactjs - 尝试在 gh-pages 中部署时反应与 Babel 相关的抛出错误
- c - 如何检查用户在 InsertList() 中输入的名称是否不等于数组等待列表中已经存在的名称?