OpenCV检测带有多个边界框的单个符号 [英] OpenCV detecting a single symbol with multiple bounding boxes

查看:168
本文介绍了OpenCV检测带有多个边界框的单个符号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用OpenCV将边界框放在手写的数学方程式输入上.当前,我的代码有时会在单个图像的不同部分周围放置多个较小的边界框,而不是在图像周围创建一个较大的框.我不确定为什么会这样.我当前用于过滤图像并找到轮廓以绘制边界框的代码如下:

I am using OpenCV to put bounding boxes on handwritten math equation inputs. Currently, my code sometimes places multiple smaller bounding boxes around different parts of a singular image instead of creating one large box around the image. I'm not sure why this is happening. My current code to filter the image and find the contours to draw the bounding box is as follows:

    img = cv2.imread(imgpath)

    morph = img.copy()
    morph = cv2.fastNlMeansDenoising(img)

    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 1))
    morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel)
    morph = cv2.morphologyEx(morph, cv2.MORPH_OPEN, kernel)

    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 15))

    # take morphological gradient
    gradient_image = cv2.morphologyEx(morph, cv2.MORPH_GRADIENT, kernel)

    gray = cv2.cvtColor(gradient_image, cv2.COLOR_BGR2GRAY)

    img_grey = cv2.morphologyEx(gray, cv2.MORPH_CLOSE, kernel)

    blur = cv2.medianBlur(img_grey,3)


    ret, thing = cv2.threshold(blur, 0.0, 255.0, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

    img_dilation = cv2.dilate(thing, kernel, iterations=3)


    conturs_lst = cv2.findContours(img_dilation, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]

实际结果的示例如下:

OG图片:

推荐答案

您有正确的主意,但我认为您过度使用了cv2.morphologyEx来不断侵蚀和放大图像.您提到您的问题:

You have the right idea but I think you're overusing cv2.morphologyEx to continuously erode and dilate the image. You mention your problem:

当前,我的代码有时会在单个图像的不同部分周围放置多个较小的边界框,而不是在图像周围创建一个大框.

Currently, my code sometimes places multiple smaller bounding boxes around different parts of a singular image instead of creating one large box around the image.

使用cv2.findContours时,它可以正常工作,但是由于轮廓实际上是斑点,而不是一个互连的奇异图像,因此它会创建多个边界框.要解决此问题,您可以扩大图像以将斑点连接在一起.

When you use cv2.findContours, its working correctly but since your contours are actually blobs instead of one interconnected singular image, it creates multiple bounding boxes. To remedy this problem, you can dilate the image to connect the blobs together.

我已经重写了您的代码,没有重复的cv2.morphologyEx.主要思想如下:

I've rewrote your code without the extra cv2.morphologyEx repetitions. The main idea is as follows:

  • 将图像转换为灰度
  • 模糊图像
  • 阈值图像可将背景与所需对象分开
  • 放大图像以连接斑点以形成奇异图像
  • 使用阈值最小/最大面积查找轮廓并过滤轮廓

阈值图像可隔离所需部分.请注意,某些轮廓的连接已断开.为了解决这个问题,我们将图像放大以连接斑点.

Threshold image to isolate desired sections. Note some of the contours have broken connections. To fix this, we dilate the image to connect the blobs.

将图像放大以形成奇异对象.现在请注意,我们在底部有不需要的水平部分,我们可以找到轮廓,然后使用区域进行过滤以删除该部分.

Dilate image to form singular objects. Now note we have the unwanted horizontal section at the bottom, we can find contours and then filter using area to remove that section.

结果

import numpy as np
import cv2

original_image = cv2.imread("1.jpg")
image = original_image.copy()

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (3, 3), 0)
thresh = cv2.threshold(blurred, 160, 255, cv2.THRESH_BINARY_INV)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
dilate = cv2.dilate(thresh, kernel , iterations=4)

cv2.imshow("thresh", thresh)
cv2.imshow("dilate", dilate)

# Find contours in the image
cnts = cv2.findContours(dilate.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

contours = []

threshold_min_area = 400
threshold_max_area = 3000

for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    area = cv2.contourArea(c)
    if area > threshold_min_area and area < threshold_max_area:
        # cv2.drawContours(original_image,[c], 0, (0,255,0), 3)
        cv2.rectangle(original_image, (x,y), (x+w, y+h), (0,255,0),1)
        contours.append(c)

cv2.imshow("detected", original_image) 
print('contours detected: {}'.format(len(contours)))
cv2.waitKey(0)

这篇关于OpenCV检测带有多个边界框的单个符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆