Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何连接边的端点以闭合它们之间的孔?_Python_Opencv_Image Processing_Contour_Edge Detection - Fatal编程技术网

Python 如何连接边的端点以闭合它们之间的孔?

Python 如何连接边的端点以闭合它们之间的孔?,python,opencv,image-processing,contour,edge-detection,Python,Opencv,Image Processing,Contour,Edge Detection,我的任务是检测土壤表面的裂缝并计算裂缝的总面积。为此,我使用了Canny边缘检测 输入图像 结果 我的下一步是将canny边转换为轮廓,因为我想使用cv2.mean过滤裂缝,并使用cv2.contourArea函数计算其面积。在这一步上,我面对了这个问题。当我使用: canny_cracks = cv2.Canny(gray, 100, 200) contours, _ = cv2.findContours(canny_cracks, cv2.RETR_EXTERNAL, cv2.CHAIN

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

输入图像

结果

我的下一步是将canny边转换为轮廓,因为我想使用
cv2.mean
过滤裂缝,并使用
cv2.contourArea
函数计算其面积。在这一步上,我面对了这个问题。当我使用:

canny_cracks = cv2.Canny(gray, 100, 200)
contours, _ = cv2.findContours(canny_cracks, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
由于边缘末端有孔,因此无法正确转换。看到问题了吗

我的问题是如何连接边的端点以闭合它们之间的孔

注意:我使用了轮廓检测,但没有应用精明的边缘。问题是轮廓检测会产生大量噪声,并且不能很好地检测所有裂纹。或者也许我不知道如何像精明的边缘那样找到轮廓。

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

结果:

代码:

从您提供的第二张图片开始,以下是我解决此问题的方法:

  • 高斯模糊图像及其灰度转换
  • 把土从盆里隔出来
    • 创建仅土壤的圆形遮罩
    • 提取土壤ROI
  • 执行形态变换以闭合孔
  • 查找轮廓并按轮廓区域过滤
  • 求和面积以获得结果

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

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()
找到罐子的外圆,缩小圆以抓住土壤区域,并使用原始图像的形状创建遮罩

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

土壤覆盖层

土壤投资回报率

你的问题是

如何连接边的端点以闭合边之间的孔

为此,您可以使用
cv2.morphologyEx()
执行一次关闭孔的操作,从而导致此问题

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

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

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


您可以使用连接线。如果裂缝比土壤暗,您也可以查看或,尽管它可能无法很好地推广到其他图像或其他类型的土壤。感谢您的回复。我使用基于颜色的分离,它会产生很多不容易处理的噪音。关于形态变换,你是说扩张吗?
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
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)