首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何分割弯曲杆进行角度计算?

如何分割弯曲杆进行角度计算?
EN

Stack Overflow用户
提问于 2017-08-10 16:29:19
回答 3查看 1.6K关注 0票数 14

我试着用OpenCV从它的背景中分割出一个弯曲的杆,然后找出其中的弯曲,并计算出每个弯道之间的角度。

幸运的是,第一部分是琐碎的,前景和背景之间有足够的对比。在分割的时候,有一点腐蚀/膨胀会引起反射/突出。

第二部分是我不知道如何处理它的地方。

我可以很容易地检索轮廓(顶部和底部非常相似,所以两者都是如此),但我似乎不知道如何将等高线分割成直线部分和弯曲杆来计算角度。

到目前为止,我已经尝试简化轮廓,但要么我得到太多或太少的点,它觉得很难将正确的设置,以保持直的部分直和弯曲的部分简化。

这是我的输入图像(bend.png)

到目前为止,我尝试过的是:

代码语言:javascript
运行
复制
#!/usr/bin/env python
import numpy as np
import cv2

threshold = 229
# erosion/dilation kernel
kernel = np.ones((5,5),np.uint8)
# contour simplification
epsilon = 0

# slider callbacks
def onThreshold(x):
    global threshold
    print "threshold = ",x
    threshold = x
def onEpsilon(x):
    global epsilon
    epsilon = x * 0.01
    print "epsilon = ",epsilon

# make a window to add sliders/preview to
cv2.namedWindow('processed')
#make some sliders
cv2.createTrackbar('threshold','processed',60,255,onThreshold)
cv2.createTrackbar('epsilon','processed',1,1000,onEpsilon)
# load image
img = cv2.imread('bend.png',0)
# continuously process for quick feedback
while 1:
    # exit on ESC key
    k = cv2.waitKey(1) & 0xFF
    if k == 27:
        break

    # Threshold
    ret,processed = cv2.threshold(img,threshold,255,0)
    # Invert
    processed = (255-processed)
    # Dilate
    processed = cv2.dilate(processed,kernel)
    processed = cv2.erode(processed,kernel)
    # Canny
    processed = cv2.Canny(processed,100,200)

    contours, hierarchy = cv2.findContours(processed,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    if len(contours) > 0:
        approx = cv2.approxPolyDP(contours[0],epsilon,True)
        # print len(approx)
        cv2.drawContours(processed, [approx], -1, (255,255,255), 3)
        demo = img.copy()
        cv2.drawContours(demo, [approx], -1, (192,0,0), 3)
    # show result
    cv2.imshow('processed ',processed)
    cv2.imshow('demo ',demo)


# exit
cv2.destroyAllWindows()

到目前为止,我的情况如下,但我不相信这是最好的方法:

我试着从视觉上弄清楚这一点,我的目标是这样的:

因为最终的目标是计算弯曲部分之间的角度,类似于这样的感觉比较简单:

我的假设是,拟合线和计算两对相交线之间的角度可以工作:

我使用HoughLines OpenCV Python教程进行了快速测试,但不管传递的参数如何,我都没有得到很好的结果:

代码语言:javascript
运行
复制
#!/usr/bin/env python
import numpy as np
import cv2

threshold = 229
minLineLength = 30
maxLineGap = 10
houghThresh = 15

# erosion/dilation kernel
kernel = np.ones((5,5),np.uint8)

# slider callbacks
def onMinLineLength(x):
    global minLineLength
    minLineLength = x
    print "minLineLength = ",x

def onMaxLineGap(x):
    global maxLineGap
    maxLineGap = x
    print "maxLineGap = ",x

def onHoughThresh(x):
    global houghThresh
    houghThresh = x
    print "houghThresh = ",x

# make a window to add sliders/preview to
cv2.namedWindow('processed')
#make some sliders
cv2.createTrackbar('minLineLength','processed',1,50,onMinLineLength)
cv2.createTrackbar('maxLineGap','processed',5,30,onMaxLineGap)
cv2.createTrackbar('houghThresh','processed',15,50,onHoughThresh)
# load image
img = cv2.imread('bend.png',0)
# continuously process for quick feedback
while 1:
    # exit on ESC key
    k = cv2.waitKey(1) & 0xFF
    if k == 27:
        break

    # Threshold
    ret,processed = cv2.threshold(img,threshold,255,0)
    # Invert
    processed = (255-processed)
    # Dilate
    processed = cv2.dilate(processed,kernel)
    processed = cv2.erode(processed,kernel)
    # Canny
    processed = cv2.Canny(processed,100,200)

    lineBottom = np.zeros(img.shape,np.uint8)

    contours, hierarchy = cv2.findContours(processed,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    if len(contours) > 0:
        cv2.drawContours(lineBottom, contours, 0, (255,255,255), 1)

    # HoughLinesP
    houghResult = img.copy()
    lines = cv2.HoughLinesP(lineBottom,1,np.pi/180,houghThresh,minLineLength,maxLineGap)
    try:
        for x in range(0, len(lines)):
            for x1,y1,x2,y2 in lines[x]:
                cv2.line(houghResult,(x1,y1),(x2,y2),(0,255,0),2)
    except Exception as e:
        print e

    # show result
    cv2.imshow('lineBottom',lineBottom)
    cv2.imshow('houghResult ',houghResult)


# exit
cv2.destroyAllWindows()

这是否可行的方法呢?如果是这样的话,在OpenCV Python中进行行拟合的正确方法是什么?

否则,这是解决这个问题的最好方法吗?

Update遵循Miki的建议,我尝试了OpenCV 3的LSD,并获得了比HoughLinesP更好的结果,但是看起来仍然需要一些调整,尽管看起来除了cv2.createLineSegmentDetector之外,没有太多的选项可供选择:

EN

回答 3

Stack Overflow用户

发布于 2017-08-10 17:57:52

使用曲率可以方便地找到线段。在这里,用最小曲率点分割等高线的示例,在您的情况下使用最大曲率点可能更好。B你可以把你的曲线分成几个部分,然后用RANSAC方法用线段近似每个部分。

票数 1
EN

Stack Overflow用户

发布于 2020-07-10 15:15:03

我知道这很古老,但在遇到类似的问题后,我发现我使用的方法(在找到二值图像之后)是这样的:

  1. 找出终点(邻居最少的点)
  2. 骨骼化 (可选)
  3. 从一端开始使用skimage cdist找到几个最近的点
  4. 对这些点执行线性回归,并在最佳拟合线的几个像素误差范围内找到图像中的所有点。我用了
  5. 这给出在同一直线内的附加点。按距最后一个基准点的距离订购。其中一些可能是将线投影到物体的遥远部分,应予删除。
  6. 重复步骤4和5,直到没有添加更多的点。
  7. 一旦没有更多的点被添加到这条线上,你就可以通过查看R-平方来找到下一个有效行的开始。这条线应该有很高的R平方。> 0.95 (取决于图像-我得到的是> 0.99)。不断改变起点,直到达到高R平方。
  8. 这给了许多线段,从那里应该很容易找到他们之间的角度。一个潜在的问题,当段是垂直的(或水平的),而斜率变成无限。当这件事发生的时候,我就把斧头转过来了。您还可以通过定义一条线的端点并找到离那条线的阈值距离中的所有点来解决这个问题,而不是进行回归。

这涉及到比使用其他方法更多的编码,但是执行时间非常快,并且可以更好地控制正在发生的事情。

票数 1
EN

Stack Overflow用户

发布于 2017-08-17 08:36:09

一旦有了轮廓,就可以使用本文中提出的方法来分析它:https://link.springer.com/article/10.1007/s10032-011-0175-3

基本上,轮廓是跟踪计算曲率在每个点。然后,你可以使用曲率阈值将轮廓分割成直线和弯曲的部分。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45619018

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档