首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何连接边缘的末端,以关闭它们之间的孔?

如何连接边缘的末端,以关闭它们之间的孔?
EN

Stack Overflow用户
提问于 2019-06-25 12:47:44
回答 2查看 5K关注 0票数 17

我的任务是检测土体表面的裂缝,并计算裂缝的总面积。为此,我使用了Canny边缘检测。

输入图像

结果

我的下一步是将精明的边缘转换成等高线,因为我想使用cv2.mean过滤裂缝,并使用cv2.contourArea函数计算它们的面积。在这一步中,我面临着这个问题。当我用:

代码语言:javascript
复制
canny_cracks = cv2.Canny(gray, 100, 200)
contours, _ = cv2.findContours(canny_cracks, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

由于边缘末端的孔,它不能正确地转换。见这里的问题

我的问题是,我如何连接边缘的末端,以关闭它们之间的洞?

备注:我使用轮廓检测而不应用Canny边缘。问题是轮廓检测会产生很大的噪声,而且不能很好地检测出所有的裂纹。或者我不知道如何像精明的边缘那样找到轮廓。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-25 22:17:25

您可以使用形态闭合。这将缩小白色像素之间的空白。如果您在下面的脚本中输入您的Canny图像,您可以自己尝试。

结果:

代码:

代码语言:javascript
复制
    import cv2
    import numpy as np  

    # function that handles trackbar changes
    def doClose(val):
            # create a kernel based on trackbar input
            kernel = np.ones((val,val))
            # do a morphologic close
            res = cv2.morphologyEx(img,cv2.MORPH_CLOSE, kernel)
            # display result
            cv2.imshow("Result", res)

    #load image as grayscale
    img = cv2.imread("KbMHp.png",0)

    # create window and add trackbar
    cv2.namedWindow('Result')
    cv2.createTrackbar('KernelSize','Result',0,15,doClose)

    # display image
    cv2.imshow("Result", img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()  
票数 3
EN

Stack Overflow用户

发布于 2019-06-25 23:53:47

从你提供的第二张图片开始,下面是我解决这个问题的方法:

  • 高斯模糊图像的灰度转换
  • 从盆栽中分离土壤
    • 创造圆圈掩蔽的只是土壤
    • 提取土壤ROI

  • 执行形态转换以关闭孔洞
  • 求等高线并按等高线区域过滤
  • 求和面积

我们从高斯模糊开始,将图像转换为灰度。

代码语言:javascript
复制
image = cv2.imread('5.png')
original = image.copy()

blur = cv2.GaussianBlur(image, (3,3), 0)
gray = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))

目的是将土壤边缘与盆栽边缘隔离开来。为此,我们使用cv2.HoughCircles()找到盆栽的外圆,缩小圆圈以抓取土壤区域,并利用原始图像的形状创建一个掩膜。

代码语言:javascript
复制
circle_mask = np.zeros(original.shape, dtype=np.uint8) 
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.5, 200) 

# Convert the (x, y) coordinates and radius of the circles to integers
circles = np.round(circles[0, :]).astype("int")
circle_ratio = 0.85

# Loop over the (x, y) coordinates and radius of the circles
for (x, y, r) in circles:
    # Draw the circle, create mask, and obtain soil ROI
    cv2.circle(image, (x, y), int(r * circle_ratio), (0, 255, 0), 2)
    cv2.circle(circle_mask, (x, y), int(r * circle_ratio), (255, 255, 255), -1)
    soil_ROI = cv2.bitwise_and(original, circle_mask)

我们在坐标上循环以求圆的半径。从这里我们画出最大的外圆。

现在,为了隔离土壤和盆栽,我们使用了一个定标因子来获得

然后,我们填充圆圈,得到一个掩码,然后将它应用到原始图像上,以获得土壤ROI。

土壤掩模

土壤ROI

你的问题是

我如何连接边缘的末端,以关闭它们之间的孔?

要做到这一点,您可以使用morphological transformation使用cv2.morphologyEx()来关闭漏洞,从而导致

代码语言:javascript
复制
gray_soil_ROI = cv2.cvtColor(soil_ROI, cv2.COLOR_BGR2GRAY)
close = cv2.morphologyEx(gray_soil_ROI, cv2.MORPH_CLOSE, kernel)

现在我们用cv2.findContours()找到轮廓,用最小阈值面积的cv2.contourArea()进行滤波,以去除岩石等小噪声。您可以调整最小面积,以控制过滤器的强度。

代码语言:javascript
复制
cnts = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

crack_area = 0
minumum_area = 25
for c in cnts:
    area = cv2.contourArea(c)
    if area > minumum_area:
        cv2.drawContours(original,[c], 0, (36,255,12), 2)
        crack_area += area

最后,我们总结出裂缝的总面积

3483.5

代码语言:javascript
复制
import cv2
import numpy as np

image = cv2.imread('5.png')
original = image.copy()

blur = cv2.GaussianBlur(image, (3,3), 0)
gray = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))

circle_mask = np.zeros(original.shape, dtype=np.uint8) 
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.5, 200) 

# Convert the (x, y) coordinates and radius of the circles to integers
circles = np.round(circles[0, :]).astype("int")
circle_ratio = 0.85

# Loop over the (x, y) coordinates and radius of the circles
for (x, y, r) in circles:
    # Draw the circle, create mask, and obtain soil ROI
    cv2.circle(image, (x, y), int(r * circle_ratio), (0, 255, 0), 2)
    cv2.circle(circle_mask, (x, y), int(r * circle_ratio), (255, 255, 255), -1)
    soil_ROI = cv2.bitwise_and(original, circle_mask)

gray_soil_ROI = cv2.cvtColor(soil_ROI, cv2.COLOR_BGR2GRAY)
close = cv2.morphologyEx(gray_soil_ROI, cv2.MORPH_CLOSE, kernel)

cnts = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

crack_area = 0
minumum_area = 25
for c in cnts:
    area = cv2.contourArea(c)
    if area > minumum_area:
        cv2.drawContours(original,[c], 0, (36,255,12), 2)
        crack_area += area

print(crack_area)
cv2.imshow('close', close)
cv2.imshow('circle_mask', circle_mask)
cv2.imshow('soil_ROI', soil_ROI)
cv2.imshow('original', original)
cv2.waitKey(0)
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56754451

复制
相关文章

相似问题

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