简体   繁体   English

Python OpenCv 多个矩形的交集

[英]Python OpenCv intersection of multiple rectangles

I am currently working on a project to recognise text sections in an image.我目前正在开展一个项目来识别图像中的文本部分。 I draw rectangles arround them as seen here:我在它们周围画了矩形,如下所示:

在此处输入图像描述

and then cut them into each rectangles to do some more stuff with them.然后将它们切成每个矩形以对它们做更多的事情。 Like this:像这样: 在此处输入图像描述

在此处输入图像描述

What i do not want is, as seen in picture 2, to have a part of a rectangle be part of another one, eg.我不想要的是,如图 2 所示,让一个矩形的一部分成为另一个矩形的一部分,例如。 pic3 beeing part of pic2. pic3 是 pic2 的一部分。 That means these part should be cut out or made white, which i don't know how to do.这意味着这些部分应该被剪掉或变成白色,我不知道该怎么做。 For the drwaing of these rectangles i use this code section:对于这些矩形的绘制,我使用以下代码部分:

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)
    

I guess i would need to somehow intersect them and cut out of one rectangle with the Coordinates of all other ones that touch it?我想我需要以某种方式将它们相交并从一个矩形中切出与所有其他触摸它的坐标的矩形?

Here is the unprocessed image:这是未处理的图像: 在此处输入图像描述

This is a possible way to do it.这是一种可能的方法。 First, I'm gonna try to detect every block of text .首先,我将尝试检测每个文本块 It doesn't matter if the blocks (or bounding boxes) overlap.块(或边界框)是否重叠并不重要。 After getting all bounding boxes for all the blobs on the image, I'll detect bounding boxes overlaps .在获取图像上所有 blob 的所有边界框后,我将检测边界框重叠 If a bounding box overlaps with other, this means that the same block of text will be shared among two or more images.如果边界框与其他边界框重叠,这意味着相同的文本块将在两个或多个图像之间共享。 I'll crop the section and fill the overlapping area with a white rectangle , that way the content will only be shown on just one image.我将裁剪该部分并用白色矩形填充重叠区域,这样内容只会显示在一张图像上。

These are the important steps:这些是重要的步骤:

  1. Use morphology to get nice blocks of texts.使用形态来获得漂亮的文本块。

  2. Detect contours on these blocks and convert those contours to bounding boxes .检测这些块上的轮廓并将这些轮廓转换为边界框

  3. Loop through all bounding boxes and:遍历所有边界框并:

    • Crop each bounding box裁剪每个边界框

    • Check for possible overlaps .检查可能的重叠 If an overlap (or intersection) is found, use the bounding box info to draw a white rectangle on this area.如果发现重叠(或相交),请使用边界框信息在该区域上绘制一个白色矩形。

This is the code, first we need to get those nice blocks of text:这是代码,首先我们需要得到那些漂亮的文本块:

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

Very standard stuff.很标准的东西。 Just read the image, convert it to grayscale and get a binary image via Otsu .只需read图像,将其转换为grayscale并通过Otsu获得二进制图像。 You'll notice I've created some deep copies of the input.您会注意到我创建了一些输入的深层副本 These are used to mainly visualize the results, as I originally drew every bounding box found and every overlapping area.这些主要用于可视化结果,因为我最初绘制了找到的每个bounding box和每个重叠区域。

Apply some very intense morphology to get the best possible blocks of text.应用一些非常强烈的形态来获得最好的文本块。 I'm applying a dilate + erode here, with 10 iterations on each operation:我在这里应用扩张 + 侵蚀,每个操作有 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)

The last snippet gets you this image:最后一个片段为您提供此图像:

Now, get the outer contours of this image and compute the bounding boxes:现在,获取该图像的外轮廓并计算边界框:

# 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]))

Now, here comes the important part.现在,重要的部分来了。 We will loop through each bounding box .我们将遍历每个bounding box Crop the image, and check if the recently bounding box used for cropping the image is found inside another bounding box (an overlap).裁剪图像,并检查最近用于裁剪图像的边界bounding box是否在另一个bounding box (重叠)。 If that's the case, just draw a big white rectangle inside that area and proceed with a new crop:如果是这种情况,只需在该区域内绘制一个大的白色矩形并继续进行新的裁剪:

# 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)

These are the bounding boxes detected for every binary blob:这些是为每个二进制 blob 检测到的边界框:

The code detects the overlapping area and draws a white rectangle on the intersections, that way it will be no longer shown on the following crop:该代码检测重叠区域并在交叉点上绘制一个白色矩形,这样它将不再显示在以下裁剪上:

These are the crops (Mind you, these are individual images):这些是作物(请注意,这些是单独的图像):

Now, the helper function to detect bounding boxes intersections is this:现在,检测边界框交叉点的助手 function 是这样的:

# 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])

It is very straightforward.这非常简单。 It just gets the coordinates of the two bounding rectangles and computes the intersection area.它只是获取两个边界矩形的坐标并计算相交区域。 If the width or height are less than zero, there was no intersection.如果widthheight小于零,则没有交集。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM