Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在opencv中合并轮廓?_Python_Opencv_Artificial Intelligence - Fatal编程技术网

Python 如何在opencv中合并轮廓?

Python 如何在opencv中合并轮廓?,python,opencv,artificial-intelligence,Python,Opencv,Artificial Intelligence,好了,伙计们,我已经在这个项目上工作了很长时间了 我正在建造一个玩chrome恐龙游戏的机器人。因此,我尝试了其他方法来检测字符,比如matchTemplate,甚至还制定了自己的算法来定位对象,但我最喜欢这个(FindOntours) 以下是我所拥有的: 有人能帮我找出我应该如何合并仙人掌的两个矩形吗 img = screen_cap() roi = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(roi,1

好了,伙计们,我已经在这个项目上工作了很长时间了

我正在建造一个玩chrome恐龙游戏的机器人。因此,我尝试了其他方法来检测字符,比如matchTemplate,甚至还制定了自己的算法来定位对象,但我最喜欢这个(FindOntours)

以下是我所拥有的:

有人能帮我找出我应该如何合并仙人掌的两个矩形吗

img = screen_cap()
roi = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(roi,127, 255, 0)
im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
first = True
for cnt in contours:
    area = cv2.contourArea(cnt)
    if area > 200: #filtering contours
        x,y,w,h = cv2.boundingRect(cnt)
        if w/h < 4: # filtering even more
            cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
img=screen\u cap()
roi=cv2.CVT颜色(img,cv2.COLOR\u bgr2灰色)
阈值(roi,127255,0)
im2,轮廓,层次=cv2.findContours(阈值,cv2.RETR\u树,cv2.CHAIN\u近似值\u简单)
第一个=正确
对于轮廓中的cnt:
面积=cv2。轮廓面积(cnt)
如果面积>200:#过滤轮廓
x、 y,w,h=cv2.boundingRect(cnt)
如果w/h<4:#过滤更多
cv2.矩形(img,(x,y),(x+w,y+h),(255,0,0),2)

这是一个老问题,似乎还没有得到正确的回答(但在评论中对部分回答的SOER同事表示歉意)。在我看来,提问者似乎有一个由两部分组成的问题:

  • 是否有合并两个矩形的opencv函数
  • 这个问题的答案是肯定和否定的;是的,如果你使用OpenCV C++绑定。Simple&可用于取并集和|表示两个矩形的交点。但是Python绑定缺少这些函数

  • 那么如何在Python中实现呢

    def union(a,b):
        x = min(a[0], b[0])
        y = min(a[1], b[1])
        w = max(a[0]+a[2], b[0]+b[2]) - x
        h = max(a[1]+a[3], b[1]+b[3]) - y
        return (x, y, w, h)
    
    def intersection(a,b):
        x = max(a[0], b[0])
        y = max(a[1], b[1])
        w = min(a[0]+a[2], b[0]+b[2]) - x
        h = min(a[1]+a[3], b[1]+b[3]) - y
        if w<0 or h<0: return () # or (0,0,0,0) ?
        return (x, y, w, h)
        # Please remember a and b are rects.
    
    def接头(a、b):
    x=min(a[0],b[0])
    y=min(a[1],b[1])
    w=最大值(a[0]+a[2],b[0]+b[2])-x
    h=最大值(a[1]+a[3],b[1]+b[3])-y
    返回(x、y、w、h)
    def交叉口(a、b):
    x=最大值(a[0],b[0])
    y=最大值(a[1],b[1])
    w=min(a[0]+a[2],b[0]+b[2])-x
    h=min(a[1]+a[3],b[1]+b[3])-y
    
    对不起,我来晚了一点。然而,如果我在谷歌上搜索“合并opencv轮廓”,我会发现这一点;我认为应该有一个答案

    您可以通过以下方法之一合并任意两个轮廓:

    • 获取每个轮廓的点列表
    • 附加它们
    • 强制将其转换为cv2等高线格式
    • 如果你不太在意细节的话,那就让cv2.convxhull来吧
    如果您不喜欢convexHull的结果,因为轮廓的凹面部分很重要,那么请遵循以下方法:

    • 获取每个轮廓的点列表
    • 附加它们
    • 得到一个共同的中心
    • 围绕中心按顺时针顺序对所有点进行排序
    • 强制将其转换为cv2等高线格式
    如果两个轮廓中有很多凹面形状,这可能会产生一个之字形图案,因为配方会忽略其原始结构穿过两个轮廓。如果是这样,您需要遵循第三个食谱:

    • 获取每个轮廓的点列表
    • 得到一个共同的中心
    • 删除位于其他轮廓内的每个轮廓的点
    • 在每个轮廓中找到离公共中心最近的点
    • 按照列出的第一条等高线进行遍历,直到到达最近的点
    • 然后切换到另一个列表,从最近的点开始顺时针穿过另一个轮廓,直到用完为止
    • 切换回第一个轮廓并附加其余的点
    • 强制将其转换为cv2等高线格式
    下一个更复杂的情况是,如果轮廓之间有多个交点,并且希望保留两者之间的孔。然后最好通过
    cv2.fillPoly()
    制作一个黑色图像,并用白色绘制轮廓;然后通过
    cv2.findContours()

    我在这里为前两个食谱勾勒了一些步骤

    获取每个轮廓的点列表: 顺时针顺序点 我使用函数按顺时针顺序排列点

    class clockwise_angle_and_distance():
        '''
        A class to tell if point is clockwise from origin or not.
        This helps if one wants to use sorted() on a list of points.
    
        Parameters
        ----------
        point : ndarray or list, like [x, y]. The point "to where" we g0
        self.origin : ndarray or list, like [x, y]. The center around which we go
        refvec : ndarray or list, like [x, y]. The direction of reference
    
        use: 
            instantiate with an origin, then call the instance during sort
        reference: 
        https://stackoverflow.com/questions/41855695/sorting-list-of-two-dimensional-coordinates-by-clockwise-angle-using-python
    
        Returns
        -------
        angle
        
        distance
        
    
        '''
        def __init__(self, origin):
            self.origin = origin
    
        def __call__(self, point, refvec = [0, 1]):
            if self.origin is None:
                raise NameError("clockwise sorting needs an origin. Please set origin.")
            # Vector between point and the origin: v = p - o
            vector = [point[0]-self.origin[0], point[1]-self.origin[1]]
            # Length of vector: ||v||
            lenvector = np.linalg.norm(vector[0] - vector[1])
            # If length is zero there is no angle
            if lenvector == 0:
                return -pi, 0
            # Normalize vector: v/||v||
            normalized = [vector[0]/lenvector, vector[1]/lenvector]
            dotprod  = normalized[0]*refvec[0] + normalized[1]*refvec[1] # x1*x2 + y1*y2
            diffprod = refvec[1]*normalized[0] - refvec[0]*normalized[1] # x1*y2 - y1*x2
            angle = atan2(diffprod, dotprod)
            # Negative angles represent counter-clockwise angles so we need to 
            # subtract them from 2*pi (360 degrees)
            if angle < 0:
                return 2*pi+angle, lenvector
            # I return first the angle because that's the primary sorting criterium
            # but if two vectors have the same angle then the shorter distance 
            # should come first.
            return angle, lenvector
    
    center_pt = np.array(list_of_pts).mean(axis = 0) # get origin
    clock_ang_dist = clockwise_angle_and_distance(origin) # set origin
    list_of_pts = sorted(list_of_pts, key=clock_ang_dist) # use to sort
    
    将它们合并为
    cv2.convxhull
    如果使用此选项,则无需按顺时针顺序排列点。但是,凸面轮可能会丢失一些轮廓属性,因为它不会保留轮廓的凹角

    # get a list of points
    # force the list of points into cv2 format and then
    ctr = cv2.convexHull(ctr) # done.
    

    我认为合并两个轮廓的函数应该是opencv库的内容。这个方法非常简单,令人遗憾的是,许多使用opencv的程序员将不得不对其进行样板编码。

    是什么阻止你检查边界框的像素位置是否靠近其他边界框的位置,如果是,则扩展最左侧边界框的宽度和高度?@AlexanderReynolds他说,因此,如果矩形是偏移的,或者有多个轮廓,我不确定他们是否只是希望边界框或轮廓之间的实际线消失(这样它们将是任意轴对齐的多边形)@snb确实是模糊的,在标题中它要求合并轮廓,但在问题中它要求合并边界矩形。可能会使用聚类来查找近等高线。@AlexanderReynolds很抱歉,这个问题很模糊。我想做的是让计算机认为仙人掌是一个实体,在一个包围盒中,必须是一个矩形。我够清楚了吗?我也在尝试自己去实现它。只是想知道是否有本机opencv方法。@snb查找…如果是多个轮廓,并且它们彼此非常接近,有没有办法将它们合并到一个轮廓中?@abss,您只需要迭代它们就可以合并它们。或者,在找到轮廓之前,你可以对你的二值图像本身使用形态学膨胀,这取决于什么最适合你的用例。谢谢你的回答,问题是,我想合并的轮廓,它们非常接近,看起来像一个,但它们之间有一个非常小的间隙,它们周围有一点噪声,所以使用膨胀将噪声包括在轮廓中,我已经尽可能多地过滤了图像,但我无法去除它们completely@abss,那就太好了
    import numpy as np
    ctr = np.array(list_of_pts).reshape((-1,1,2)).astype(np.int32)
    
    # get a list of points
    # force the list of points into cv2 format and then
    ctr = cv2.convexHull(ctr) # done.