【问题标题】:Find middle of partially closed canny edges找到部分闭合的精明边缘的中间
【发布时间】:2021-03-06 11:40:35
【问题描述】:

我有如下(低分辨率)图像:

(图 1 原件)

最终目标是为图像中的每条线定义线段坐标:

我尝试过的策略是扩张 -> 寻找轮廓 -> 模糊 -> 侵蚀 -> 精明的边缘检测:

import numpy as np
import cv2
from skimage.feature import canny

image = cv2.imread('image.png')

kernel = np.ones((1,1),np.uint8)
dilated_img = cv2.dilate(gray, kernel, iterations = 1)
canvas = cv2.cvtColor(dilated_img, cv2.COLOR_GRAY2RGB)
contours, hierarchy = cv2.findContours(dilated_img, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)

for i,cont in enumerate(contours):                                                                                                                                                                                                                                              
    if ( hierarchy[0][i][3] != -1 ):                                                                                                                                                                                                                                            
        cv2.fillPoly(canvas, pts =[cont], color=(0, 180, 0))                                                                                                                                                                                       
    else:                                                                                                                                                                                                                                                                       
        cv2.drawContours(canvas, cont, -1, (255, 0, 0), 1) 

canvas = cv2.GaussianBlur(canvas,(1, 1),39)
edges = canny(image, 3, 1, 25)

输出 (edges) 类似于下图,除了绿色之外,我添加了绿色以表示我希望通过此策略实现的目标:如果我能找到管子的中间(绿色),然后我可以从中构造线段。也许这是实现目标的一种不必要的复杂方式......

边缘大多包含这些管状结构,可以完全封闭或不封闭。

图片中的绿线表示我想要找到的东西——基本上就是管子的大致中间位置。

我尝试对edge 对象执行的操作是逐行(和逐列)逐个像素地根据白色和黑色像素的显示方式找到管的中间,但是结果很混乱,并且不适用于许多管方向。

(图像 1 边缘,颜色反转)

那么假设这个策略对于实现上述目标是可行的,我怎样才能找到管的中点?如果策略不好,什么会更好?

谢谢!

【问题讨论】:

    标签: python opencv computer-vision scikit-image opencv-python


    【解决方案1】:

    希望这个方法对你有帮助。

    您的绿线是阈值图像的骨架图像。查看here 了解更多关于骨架化图像的信息。

    import cv2
    import numpy as np
    from skimage.morphology import skeletonize
    
    
    def read_image(image_path):
        image = cv2.imread(image_path)
        image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        _, thresh = cv2.threshold(image, 200, 255, cv2.THRESH_BINARY_INV)
        return thresh
    
    
    def get_skeleton_iamge(threshold_image):
        skeleton = skeletonize(threshold_image / 255)
        skeleton = skeleton.astype(np.uint8)
        skeleton *= 255
        return skeleton
    
    
    if __name__ == "__main__":
        threshold_image = read_image("image.png")
        cv2.imshow("threshold_image", threshold_image)
    
        skeleton_iamge = get_skeleton_iamge(threshold_image)
        cv2.imshow("skeleton_iamge", skeleton_iamge)
    
        canny_edges = cv2.Canny(threshold_image, 100, 200)
        cv2.imshow("canny_edges", canny_edges)
    
        # for displaying image only
        colour_skeleton_iamge = cv2.cvtColor(skeleton_iamge, cv2.COLOR_GRAY2BGR)
        colour_canny_edges = cv2.cvtColor(canny_edges, cv2.COLOR_GRAY2BGR)
        colour_skeleton_iamge[skeleton_iamge == 255] = [0, 255, 0]
        combined_image = cv2.scaleAdd(colour_skeleton_iamge, 0.5, colour_canny_edges, 0.5)
        cv2.imshow("combined_image", combined_image)
    
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    

    输出:

    image threshold_image skeleton_iamge canny_edges combined_image

    【讨论】:

    • 太棒了,正是我需要的!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-20
    • 2012-06-09
    相关资源
    最近更新 更多