Python opencv 检测带交点的形状 [英] Python opencv detect shapes with intersections
问题描述
我们正在使用 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屋!