gpt4 book ai didi

python - 开放式 CV 轮廓面积计算错误

转载 作者:行者123 更新时间:2023-12-02 15:35:10 27 4
gpt4 key购买 nike

我刚刚开始使用 OpenCV,我发现了 contourArea 函数的一些非常奇怪的行为。

看到这张图片。

Original

它有三个不相连的区域,左侧是一组长笔划,顶部中心有一个点,最后是右侧的一个大方块。

当我运行我的函数时,我得到了这个结果

Contours detected

Contour[0] Area: 221, Length: 70, Colour: Red 
Contour[1] Area: 13772, Length: 480, Colour: Green
Contour[2] Area: 150, Length: 2370, Colour: Blue

虽然我还没有实际计算左侧部分的面积,但它似乎包含超过 150 个像素并且肯定比顶部中心的点具有更高的值,我会说该点应该能够适应左侧部分至少 10 次。广场的面积确实有效。
Square Area
width = 118
height = 116
118 * 116 = 13,688

13,688 与 opencv 给出的面积(13,772)非常接近,差异可能代表我的测量误差。
我手动计算了点的面积
Dot Area
width = 27
height = 6
27*6 = 162

与 opencv 所说的相差不远 (221)

阅读自 OpenCV docs page on contourArea它说它会为具有自相交的轮廓提供错误的结果。不太明白什么是自相交,我做了一个测试图像。

ORIGINAL PIC HERE

如您所见,左侧有一个矩形,中间有一个十字,另一个旋转了 45 度的十字。
由于中心重叠,我希望十字架的面积略小于矩形面积的两倍。

CONTOURED PIC HERE
Contour[0] Area: 1805, Length: 423, Colour: Red 
Contour[1] Area: 947, Length: 227, Colour: Green
Contour[2] Area: 1825, Length: 415, Colour: Blue

如您所见,两个十字架的面积略小于矩形面积的两倍。正如预期的那样。

我对捕获正方形的内部或在左侧的形状和点周围绘制一个框不感兴趣(尽管它会切向有趣)这不是我在这个问题中特别要问的。

所以我的问题:
为什么我的不规则形状的面积被严重低估了?
  • 我是否使用了错误的功能?
  • 我是否错误地使用了正确的功能?
  • 我在 opencv 中发现了一个错误吗?
  • 自相交是否具有我的测试中未证明的含义?

  • 我从 this tutorial 复制了大部分代码

    我已经将我的代码简化为下面这个自包含的示例。
    def contour_test(name):
    import cv2 as cv
    colours = [{'name': 'Red ', 'bgr': (0, 0, 255)},
    {'name': 'Green ', 'bgr': (0, 255, 0)},
    {'name': 'Blue ', 'bgr': (255, 0, 0)}]
    src = cv.imread(cv.samples.findFile(name))
    src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
    src_gray = cv.blur(src_gray, (3,3))
    threshold = 100
    canny_output = cv.Canny(src_gray, threshold, threshold * 2)
    contours, _ = cv.findContours(canny_output, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    # Get the moments
    mu = [None for i in contours]
    for i in range(len(contours)):
    mu[i] = cv.moments(contours[i])
    # Get the mass centers
    mc = [None for i in contours]
    for i in range(len(contours)):
    mc[i] = (mu[i]['m10'] / (mu[i]['m00'] + 1e-5), mu[i]['m01'] / (mu[i]['m00'] + 1e-5))
    # Draw contours
    drawing = np.zeros((canny_output.shape[0], canny_output.shape[1], 3), dtype=np.uint8)
    for i, j in enumerate(contours):
    colour = colours[i]['bgr']
    cv.drawContours(drawing, contours, i, colour, 2)
    area = int(cv.contourArea(contours[i]))
    length = int(cv.arcLength(contours[i], True))
    print('Contour[{0}] Area: {1}, Length: {2}, Colour: {3}'.format(i, area, length, colours[i]['name']))

    最佳答案

    内部轮廓findContours发现应该充满 白色颜色。

  • 不要使用 cv.Canny之前 findContours ( cv.blur 也不是必需的)。
  • 确保轮廓是白色而不是黑色。
    您可以使用 cv.thresholdcv.THRESH_BINARY_INV用于反转极性的选项。
    建议添加cv.THRESH_OTSU自动阈值选项。

  • 您可以更换 cv.blurcv.Cannycv.findContours(canny_output...和:
    _, src_thresh = cv.threshold(src_gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)
    contours, _ = cv.findContours(src_thresh, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

    结果(上图):

    enter image description here
    Contour[0] Area: 13531, Length: 476, Colour: Red
    Contour[1] Area: 184, Length: 71, Colour: Green
    Contour[2] Area: 4321, Length: 1202, Colour: Blue

    这是完整的(更新的)代码:
    import numpy as np

    def contour_test(name):
    import cv2 as cv
    colours = [{'name': 'Red ', 'bgr': (0, 0, 255)},
    {'name': 'Green ', 'bgr': (0, 255, 0)},
    {'name': 'Blue ', 'bgr': (255, 0, 0)}]
    src = cv.imread(cv.samples.findFile(name))
    src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
    #src_gray = cv.blur(src_gray, (3,3))
    #threshold = 100
    #canny_output = cv.Canny(src_gray, threshold, threshold * 2)
    #contours, _ = cv.findContours(canny_output, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

    _, src_thresh = cv.threshold(src_gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)
    cv.imshow('src_thresh', src_thresh);cv.waitKey(0);cv.destroyAllWindows() # Show src_thresh for testing
    contours, _ = cv.findContours(src_thresh, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

    # Get the moments
    mu = [None for i in contours]
    for i in range(len(contours)):
    mu[i] = cv.moments(contours[i])
    # Get the mass centers
    mc = [None for i in contours]
    for i in range(len(contours)):
    mc[i] = (mu[i]['m10'] / (mu[i]['m00'] + 1e-5), mu[i]['m01'] / (mu[i]['m00'] + 1e-5))
    # Draw contours
    drawing = np.zeros((src_thresh.shape[0], src_thresh.shape[1], 3), dtype=np.uint8)
    for i, j in enumerate(contours):
    colour = colours[i]['bgr']
    cv.drawContours(drawing, contours, i, colour, 2)
    area = int(cv.contourArea(contours[i]))
    length = int(cv.arcLength(contours[i], True))
    print('Contour[{0}] Area: {1}, Length: {2}, Colour: {3}'.format(i, area, length, colours[i]['name']))

    cv.imshow('drawing', drawing);cv.waitKey(0);cv.destroyAllWindows() # Show drawing for testing

    contour_test('img.jpg')

    我加了 cv.imshow在两个地方进行测试。

    关于python - 开放式 CV 轮廓面积计算错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61074714/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com