Python 获得不规则形状的中心

Python 获得不规则形状的中心,python,opencv,image-processing,opencv-python,Python,Opencv,Image Processing,Opencv Python,我有一个不规则的形状,如下所示: 我需要得到白色区域的中心,我刚刚在openCV中尝试了轮廓,如下所示 img=cv.imread('mypic',0) ret,thresh = cv.threshold(img,127,255,cv.THRESH_BINARY_INV) cnts = cv.findContours(thresh.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE) cnt = contours[0] x,y,w,h =

我有一个不规则的形状,如下所示:

我需要得到白色区域的中心,我刚刚在openCV中尝试了轮廓,如下所示

img=cv.imread('mypic',0)
ret,thresh = cv.threshold(img,127,255,cv.THRESH_BINARY_INV)
cnts = cv.findContours(thresh.copy(), cv.RETR_EXTERNAL,
    cv.CHAIN_APPROX_SIMPLE)
cnt = contours[0]
x,y,w,h = cv.boundingRect(cnt)
res_img = cv.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
cv.imwrite('output.png',res_img)
但是这些碳纳米管没有给我很好的效果,因为你可以看到原始图像和图片下方的两个小黑点。有人能给我指出一个很好的解决办法来得到一个不规则形状的中心吗


您可能需要尝试
ConnectedComponentsWithStats
功能。这将返回质心、面积和边界框参数。如上所述,模糊和形态(扩张/侵蚀)对噪音也有很大帮助。如果你对腐蚀足够慷慨,你在处理后几乎不会得到任何杂散像素。

正如我建议的,在二值图像上执行
腐蚀
,然后执行
膨胀
(一种
打开
操作),然后计算
中心矩
,并使用此信息计算
质心
。以下是步骤:

  • 通过大津阈值化从输入中获取二值图像
  • 使用
    cv2.矩计算中心矩
  • 使用前面的信息计算水滴的质心
  • 让我们看看代码:

    import cv2
    import numpy as np
    
    # Set image path
    path = "C:/opencvImages/"
    fileName = "pn43H.png"
    
    # Read Input image
    inputImage = cv2.imread(path+fileName)
    
    # Convert BGR to grayscale:
    grayscaleImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY)
    
    # Threshold via Otsu + bias adjustment:
    threshValue, binaryImage = cv2.threshold(grayscaleImage, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
    
    这是你得到的二值图像。注意小噪音:

    打开操作将清除小水滴。一个矩形的
    结构元素
    就足够了,让我们使用
    3
    迭代:

    # Apply an erosion + dilation to get rid of small noise:
    
    # Set kernel (structuring element) size:
    kernelSize = 3
    
    # Set operation iterations:
    opIterations = 3
    
    # Get the structuring element:
    maxKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernelSize, kernelSize))
    
    # Perform closing:
    openingImage = cv2.morphologyEx(binaryImage, cv2.MORPH_OPEN, maxKernel, None, None, opIterations, cv2.BORDER_REFLECT101)
    
    这是过滤后的图像:

    现在,计算
    中心力矩
    ,然后计算水滴的
    质心

    # Calculate the moments
    imageMoments = cv2.moments(openingImage)
    
    # Compute centroid
    cx = int(imageMoments['m10']/imageMoments['m00'])
    cy = int(imageMoments['m01']/imageMoments['m00'])
    
    # Print the point:
    print("Cx: "+str(cx))
    print("Cy: "+str(cy))
    
    此外,让我们在二值图像上绘制这一点,以检查结果:

    # Draw centroid onto BGR image:
    bgrImage = cv2.cvtColor(binaryImage, cv2.COLOR_GRAY2BGR)
    bgrImage = cv2.line(bgrImage, (cx,cy), (cx,cy), (0,255,0), 10)
    
    结果是:


    可以将使用图像矩计算的质心视为对象相对于像素强度的“质量”中心。根据对象的实际形状,它甚至可能不在对象内部。 另一种方法是计算边界圆的中心:

    thresh = cv2.morphologyEx(thresh, cv2.MORPH_DILATE, np.ones((3, 3)))
    contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = [c for c in contours if cv2.contourArea(c) > 100]
    (x, y), r = cv2.minEnclosingCircle(contours[0])
    output = thresh.copy()
    cv2.circle(output, (int(x), int(y)), 3, (0, 0, 0), -1)
    cv2.putText(output, f"{(int(x), int(y))}", (int(x-50), int(y-10)), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 0), 1)
    cv2.circle(output, (int(x), int(y)), int(r), (255, 0, 0), 2)
    
    该代码的输出如下所示:

    应用一些形态学来获得一个独特的水滴并计算中心矩。你可以使用零阶矩和一阶矩计算重心。我使用了一些形态学变换,如膨胀和侵蚀,但没有任何区别!你的轮廓是什么样子的?如上所述,
    @eldesgraciado
    ,计算中心力矩以获得质心点坐标。看见