Python 获得不规则形状的中心
我有一个不规则的形状,如下所示: 我需要得到白色区域的中心,我刚刚在openCV中尝试了轮廓,如下所示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 =
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
,计算中心力矩以获得质心点坐标。看见