我正在尝试测量轮廓的长度:

opencv - arcLength()和contourArea()返回意外值-LMLPHP

绿线是在轮廓上计算的HoughLineP。通过计算绿线上的欧几里得距离,我得到153.88。但是,轮廓上的arcLength()应当比HoughLineP长约1/8时会给出364.71arcLength()为什么返回的长度几乎是轮廓的两倍?这是我的代码:

def euclid_distance(line):
    dx = line[0] - line[2]
    dy = line[1] - line[3]
    return math.sqrt(dx*dx + dy*dy)

_, contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contour = contours[1]
cnt_perimeter = cv2.arcLength(contour, False)

lines_p = cv2.HoughLinesP(mat_cnt, 1, np.pi/180, 30, minLineLength=10, maxLineGap=5)

line_dist = 0
for lp in lines_p:
    for l in lp:
        x1,y1,x2,y2 = l
        cv2.line(mat_cnt,(x1,y1),(x2,y2),(0,200,0),2)
        line_dist += euclid_distance(l)
print cnt_perimeter, line_dist, contour.size
--
364.710676908 153.883072493 204

编辑:

这是原始轮廓:

opencv - arcLength()和contourArea()返回意外值-LMLPHP

要点如下:
[[[386, 477]], [[385, 478]], [[378, 478]], [[377, 479]], [[373, 479]], [[372, 480]], [[368, 480]], [[367, 481]], [[361, 481]], [[360, 482]], [[355, 482]], [[354, 483]], [[348, 483]], [[347, 484]], [[342, 484]], [[341, 485]], [[336, 485]], [[335, 486]], [[329, 486]], [[328, 487]], [[324, 487]], [[323, 488]], [[317, 488]], [[316, 489]], [[311, 489]], [[310, 490]], [[306, 490]], [[305, 491]], [[299, 491]], [[298, 492]], [[293, 492]], [[292, 493]], [[287, 493]], [[286, 494]], [[279, 494]], [[278, 495]], [[275, 495]], [[274, 496]], [[269, 496]], [[268, 497]], [[263, 497]], [[262, 498]], [[255, 498]], [[254, 499]], [[249, 499]], [[248, 500]], [[241, 500]], [[240, 501]], [[220, 501]], [[219, 502]], [[216, 502]], [[219, 502]], [[220, 501]], [[240, 501]], [[241, 500]], [[248, 500]], [[249, 499]], [[254, 499]], [[255, 498]], [[262, 498]], [[263, 497]], [[268, 497]], [[269, 496]], [[274, 496]], [[275, 495]], [[278, 495]], [[279, 494]], [[286, 494]], [[287, 493]], [[292, 493]], [[293, 492]], [[298, 492]], [[299, 491]], [[305, 491]], [[306, 490]], [[310, 490]], [[311, 489]], [[316, 489]], [[317, 488]], [[323, 488]], [[324, 487]], [[328, 487]], [[329, 486]], [[335, 486]], [[336, 485]], [[341, 485]], [[342, 484]], [[347, 484]], [[348, 483]], [[354, 483]], [[355, 482]], [[360, 482]], [[361, 481]], [[367, 481]], [[368, 480]], [[372, 480]], [[373, 479]], [[377, 479]], [[378, 478]], [[385, 478]], [[386, 477]], [[390, 477]]]

顺便说一句,返回的轮廓区域是0.0,使用以下代码:
approx = cv2.approxPolyDP(contour, 5, True)
print cv2.contourArea(approx)
---
0.0

轮廓面积怎么这么小?直线部分已经是154(HoughLineP的长度)。

最佳答案

首先让我们对问题进行简单的测试:

让我们创建一条线并计算欧氏距离和arcLength。

import cv2
import numpy as np

a = np.array([(1,1), (2,2), (3,3), (4,4), (5,5), (6,6), (7,7)])

cv2.arcLength(a, False) # Prints 8.485281229019165
math.sqrt((7-1) * (7-1) + (7-1) * (7-1)) # prints 8.48528137423857

它们都(几乎)相等。

那么,可能出什么问题了?我唯一的解释是,您的点不在一条直线上或几乎不在一条直线上。

例如,让我们将上一个示例中的点(0,0)添加到数组的末尾。
a = np.array([(1,1), (2,2), (3,3), (4,4), (5,5), (6,6), (7,7), (0,0)])
cv2.arcLength(a, False) # prints 18.38477635383606
math.sqrt((7-0) * (7-0) + (7-0) * (7-0)) # 9.899494936611665

如您所见,arcLength增加了两倍……发生了什么?该函数实际上会在两点之间产生最小的欧几里德距离...因此,如果您有一条完美的线并且以正确的顺序,您将获得相同的结果(或实际上是接近的),但是如果一个点不规则,则可能给出有些不同。

几句话:

您获得153的欧几里德距离...那么您的线在某些部分的厚度超过1像素以获得204点(每像素至少考虑1个点),这意味着轮廓可以像您在一条线上检测到2条线一样拥有,这意味着您将获得更多的周长。

您可以尝试进行近似多边形运算以减少点数,然后轻松地查看发生了什么,或者如果使用findCountours获得轮廓,则可以使用CV_CHAIN_APPROX_SIMPLE对其进行压缩,然后查看出现了什么问题。

我希望这能消除您的疑问,即使不是只给我发表评论。

关于opencv - arcLength()和contourArea()返回意外值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48251667/

10-12 22:43