Python opencv 检测带交点的形状 [英] Python opencv detect shapes with intersections

查看:298
本文介绍了Python opencv 检测带交点的形状的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在使用 Python openCV 进行形状检测.我们找到 approx_poly_dp 然后计算顶点的数量.但是,当对象有很多交叉点时,该过程不起作用(见下图第二张).Opencv 无法检测单个对象,只能找到一个大的形状.在处理交叉点时,在给定一般图片输入的情况下,找到形状的最佳方法是什么.或者这不是 opencv 的功能,也许更适合机器学习?

We are conducting shape detection using Python openCV. We find approx_poly_dp and then count number of vertices. However, the process does not work when object has many intersections (seen in second picture below). Opencv cannot detect individual objects, and just finds one large shape. In dealing with intersections, what is best way to find shapes, given general picture inputs. Or is this not a functionality of opencv, maybe better suited with machine learning?

    image_original = cv2.imread(file_name)
    image_gray = cv2.cvtColor(image_original, cv2.COLOR_BGR2GRAY)
    image_blur = cv2.GaussianBlur(image_gray, (5, 5), 0)
    image_morph = cv2.morphologyEx(image_blur, cv2.MORPH_OPEN, kernel)
    image_canny = cv2.Canny(image_morph, 50, 50)
    image_dilate = cv2.dilate(image_canny, kernel, iterations=2)
    image_final = cv2.erode(image_dilate, kernel, iterations=1)

    contours, hierarchy = cv2.findContours(image_final, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    peri = cv2.arcLength(contours, True)
    approx = cv2.approxPolyDP(contours, 0.04 * peri, True)

    if len(approx) == 3:
        shape = "triangle"
    elif len(approx) == 4:
        (x, y, w, h) = cv2.boundingRect(approx)
        ar = w / float(h)
        shape = "square" if ar >= 0.95 and ar <= 1.05 else "rectangle"
    elif len(approx) == 5:
        shape = "pentagon"
    else:
        shape = "circle"

路口图片:

推荐答案

以下过程可能适用于简单的数字:

Following procedure might work for simple figures:

找到连通分量,忽略背景和轮廓分量,找到每个分量的相邻分量.

Find the connected components, and find neighboring components of each component ignoring the background and outline components.

尝试一个组件及其相邻组件的组合,并将其提供给您已有的形状分类器.作为预处理步骤,您可能必须使用形态学闭合将组件组合成单个 blob.

Try a component with combinations of its neighboring components and feed it to the shape classifier that you already have. As a pre-processing step, you might have to combine the components into a single blob using a morphological closing.

import cv2 as cv
import numpy as np
from itertools import combinations

im = np.zeros((512, 512), dtype=np.uint8)
im = cv.rectangle(im, (100, 200), (400, 400), 255, 2)
im = cv.circle(im, (250, 380), 100, 255, 2)
im = cv.rectangle(im, (50, 50), (250, 250), 255, 2)

ret, bw = cv.threshold(im, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
ncomp, labels, stats, centroids = cv.connectedComponentsWithStats(bw)

def getNeighbors(labels, n):
    r = 4 # you might have to change this depending on outline thickness
    se = cv.getStructuringElement(cv.MORPH_CROSS, (2*r+1, 2*r+1))
    neighbors = cv.dilate((labels==n).astype(np.uint8), se)
    # ignore background, outline and the component of interest
    return np.setdiff1d(np.unique(labels[neighbors==1]), [0, 1, n])

def shapes(arr, i):
    p = arr.tolist()
    for r in range(1, len(p)+1):
        for l in list(combinations(p, r)):
            print l + (i, )

对于下图,您将获得已连接组件的列出组合.请注意,我没有费心去删除重复项.

For the following figure, you get the listed combinations of connected components. Note that I haven't bothered to remove duplicates.

for i in range(2, ncomp):
    shapes(getNeighbors(labels, i), i)

(3, 2)
(2, 3)
(4, 3)
(2, 4, 3)
(3, 4)
(5, 4)
(3, 5, 4)
(4, 5)
(6, 5)
(4, 6, 5)
(5, 6)

我不会说这是一个有效的解决方案,因为它涉及尝试所有邻居的组合,但我发布这个只是为了以防有人发现这个基于图像处理的解决方案有用.

I wouldn't say this is an efficient solution as it involves trying out all combinations of neighbors, but I'm publishing this just in case someone finds this image processing based solution useful.

这篇关于Python opencv 检测带交点的形状的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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