Python 有没有办法在OpenCV/skimage中获取浮点坐标的轮廓属性?

Python 有没有办法在OpenCV/skimage中获取浮点坐标的轮廓属性?,python,image,opencv,scikit-image,Python,Image,Opencv,Scikit Image,我在Matplotlib中创建了等高线图,我需要进一步分析它们是否为闭合曲线,然后查看细胞结构的面积、凸度、坚固度等。在Matplotlib中,它们的类型为LineCollection和Path 在OpenCV中,我无法将float数组传递给cv2.contourArea或类似函数。另一方面,转换为uint8坐标会丢失嵌套结构等重要数据。在这种情况下,我需要得到内部嵌套的凸轮廓 在Python中是否有任何选项可以查找面积、凸包、边框等信息 我可以放大图像,但我担心它可能会不可预测地扭曲图片 例如

我在Matplotlib中创建了等高线图,我需要进一步分析它们是否为闭合曲线,然后查看细胞结构的面积、凸度、坚固度等。在Matplotlib中,它们的类型为
LineCollection
Path

在OpenCV中,我无法将
float
数组传递给
cv2.contourArea
或类似函数。另一方面,转换为
uint8
坐标会丢失嵌套结构等重要数据。在这种情况下,我需要得到内部嵌套的凸轮廓

在Python中是否有任何选项可以查找面积、凸包、边框等信息

我可以放大图像,但我担心它可能会不可预测地扭曲图片

例如:带有浮点和整数坐标的附加图像


我假设您可以完全控制Matplotlib部件。所以,让我们试着从那里得到一个图像,你可以很容易地使用OpenCV进行进一步的图像处理

我们从一些常见的情节开始,如您的问题所示:

可以设置参数以获取单个轮廓标高。这有助于分别在多个级别上工作。在下面,我将重点介绍
级别=[1.75]
(最内部的绿色椭圆)。稍后,您可以简单地循环所有需要的级别,并执行分析

对于自定义等高线图,我们将使用和设置一个固定的
x,y
域,例如
[-3,3]x[-2,2]
。因此,我们知道实际画布的尺寸。我们使用摆脱了轴,使用了画布周围的边距。剩下的是全尺寸的普通画布(图形大小调整为
(10,5)
,颜色自动调整为级别数):

现在,我们将画布保存到某个NumPy数组,cf。从那里,我们可以执行任何OpenCV操作。为了找到该级别轮廓的组合区域,我们可以对灰度图像进行阈值处理,找到所有轮廓,并使用
cv2.contourArea
计算它们的面积。我们将这些面积相加,得到整个面积的像素值。从已知的画布尺寸,我们知道整个画布区域的“单位”,从图像尺寸,我们知道整个画布区域的像素。因此,我们只需要将整个轮廓区域(以像素为单位)除以整个画布区域(以像素为单位),然后乘以整个画布区域(以“单位”为单位)

这就是全部代码:

导入cv2
将matplotlib.pyplot作为plt导入
将numpy作为np导入
#为等高线图生成一些数据
增量=0.025
x=np.arange(-3.0,3.0,delta)
y=np.arange(-2.0,2.0,delta)
十、 Y=np.meshgrid(X,Y)
Z1=np.exp(-(X+1.5)**2-Y**2)
Z2=np.exp(-(X-1.5)**2-Y**2)
Z=(Z1+Z2)*2
#自定义等高线图
最小x_,最大x_=-3,3
y_min,y_max=-2,2
fig=plt.图(2,figsize=(10,5))#设置大尺寸
plt.等高线(X,Y,Z,levels=[1.75])#如果需要,设置单个levels
plt.xlim([x_min,x_max])#明确设置x限制
plt.ylim([y_min,y_max])#显式设置y限制
plt.轴(“关闭”)#完全没有显示轴
plt.紧凑布局(pad=0)#完全没有边距
#以NumPy数组的形式获取人物的画布,cf。https://stackoverflow.com/a/7821917/11089932
图canvas.draw()
img=np.frombuffer(图canvas.tostring_rgb(),dtype=np.uint8)
img=img.reformate(图canvas.get_width\u height()[::-1]+(3,))
#灰度和阈值图像
遮罩=cv2.CVT颜色(img,cv2.COLOR\u RGB2GRAY)
掩码=cv2.阈值(掩码,0,255,cv2.THRESH\u OTSU+cv2.THRESH\u BINARY\u INV)[1]
#查找轮廓,计算面积(像素),求和以得到特定级别的整个面积(像素)
cnts=cv2.查找孔(屏蔽,cv2.外部翻新,cv2.链约无)
如果len(cnts)==2个其他cnts[1],则cnts=cnts[0]
面积=np.和(np.阵列([cv2.cnt中cnt的轮廓面积(cnt]))
#从画布区域(像素)到x_min、x_max等的整个区域(坐标)。
面积=面积/np.prod(掩模形状[:2])*(x_最大值-x_最小值)*(y_最大值-y_最小值)
打印('区域:',区域)
输出面积似乎合理:

面积:0.861408
现在,您可以使用您喜欢的OpenCV进行任何图像处理。始终记住将任何像素结果转换为某些“单位”结果

----------------------------------------
系统信息
----------------------------------------
平台:Windows-10-10.0.16299-SP0
Python:3.9.1
PyCharm:2021.1.1
Matplotlib:3.4.1
NumPy:1.20.2
OpenCV:4.5.1

太好了,这很有帮助!设置figsize非常方便,可以让matplotlib完成这项工作。