如何使用OpenCV Python在图像中查找物体的填充率和等效直径?


物体的填充率计算为轮廓面积与其凸包面积之比。因此,要计算填充率,我们首先必须找到轮廓面积和凸包面积。可以使用**cv2.contourArea()**函数找到物体的轮廓面积。

等效直径是指面积与轮廓面积相同的圆的直径。填充率和等效直径的计算如下:

语法

area = cv2.contourArea(cnt)
hull = cv2.convexHull(cnt)
hull_area = cv2.contourArea(hull)
solidity = float(area)/hull_area
equi_diameter = np.sqrt(4*area/np.pi)

其中,**cnt**是图像中物体轮廓点的NumPy数组。

步骤

您可以使用以下步骤来计算图像中物体的填充率和等效直径:

导入所需的库。在以下所有Python示例中,所需的Python库是**OpenCV**。请确保您已安装它。

import cv2

使用**cv2.imread()**读取输入图像并将其转换为灰度图像。

img = cv2.imread('star.png.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

对灰度图像应用阈值处理以创建二值图像。调整第二个参数以更好地检测轮廓。

ret,thresh = cv2.threshold(gray,40,255,0)

使用**cv2.findContours()**函数查找图像中的轮廓。

contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

选择一个轮廓“**cnt**”或遍历所有轮廓。计算物体的填充率和等效直径。我们首先计算轮廓面积和凸包面积。

area = cv2.contourArea(cnt)
hull = cv2.convexHull(cnt)
hull_area = cv2.contourArea(hull)
solidity = float(area)/hull_area
equi_diameter = np.sqrt(4*area/np.pi)

您可以选择在输入图像上绘制凸包。并将填充率和等效直径作为文本添加到图像上。

cv2.drawContours(img, [hull], -1, (0,255,255), 3)

打印填充率和等效直径,并显示带有绘制的凸包和已写入文本的图像。

print("Solidity: ", solid)
print("Equivalent Diameter: ", dia)
cv2.imshow("Solidity & Equivalent Diameter", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

让我们来看一些例子,以便更好地理解。

示例1

在这个Python程序中,我们计算图像中物体的填充率和等效直径。我们在图像中绘制物体的凸包。我们还在图像上将填充率和等效直径值作为文本显示。

# import required libraries import cv2 # load the input image img = cv2.imread('star.png') # convert the image to grayscale gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # apply thresholding to convert grayscale to binary image ret,thresh = cv2.threshold(gray,40,255,0) # find the contours contours,hierarchy = cv2.findContours(thresh, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) print("Number of objects detected:", len(contours)) # define function to compute the solidity def solidity(cnt): area = cv2.contourArea(cnt) hull = cv2.convexHull(cnt) hull_area = cv2.contourArea(hull) solidity = float(area)/hull_area return solidity # define function to compute the equivalent diameter def eq_dia(cnt): area = cv2.contourArea(cnt) equi_diameter = np.sqrt(4*area/np.pi) return equi_diameter # select first contour cnt = contours[0] # find the solidity for this contour solid = solidity(cnt) solid= round(solid, 2) # find the equivalent diameter for this contour dia = eq_dia(cnt) dia =round(dia, 2) # draw convex hull on the image hull = cv2.convexHull(cnt) x1, y1 = hull[0][0] img = cv2.drawContours(img,[hull],0,(255,255,0),2) cv2.putText(img, f'Solidity={solid}', (x1, y1), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) cv2.putText(img, f'Equivalent Diameter={dia}', (x1, y1+30), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) print("Solidity: ", solid) print("Equivalent Diameter: ", dia) cv2.imshow("Solidity & Equivalent Diameter", img) cv2.waitKey(0) cv2.destroyAllWindows()

我们将此图像用作此程序中的**输入文件**:

输出

执行上述代码后,将产生以下输出:

Number of objects detected: 1 
Solidity: 0.7 
Equivalent Diameter: 164.4

我们将获得以下**输出**窗口:

输出显示检测到的物体,凸包以青色绘制。检测到的物体的填充率和等效直径以绿色显示。

示例2

在这个Python程序中,我们计算图像中多个物体的填充率和等效直径。我们在图像上绘制每个物体的凸包。我们还为每个物体显示填充率和等效直径作为文本。

import cv2 import numpy as np img = cv2.imread('convexhull.png') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(gray,100,255,0) contours,hierarchy = cv2.findContours(thresh, 1, 2) print("Number of objects detected:", len(contours)) def solidity(cnt): area = cv2.contourArea(cnt) hull = cv2.convexHull(cnt) hull_area = cv2.contourArea(hull) solidity = float(area)/hull_area return solidity def eq_dia(cnt): area = cv2.contourArea(cnt) equi_diameter = np.sqrt(4*area/np.pi) return equi_diameter for i, cnt in enumerate(contours): solid = solidity(cnt) solid= round(solid, 2) dia = eq_dia(cnt) dia =round(dia, 2) x,y,w,h = cv2.boundingRect(cnt) hull = cv2.convexHull(cnt) img = cv2.drawContours(img,[hull],0,(0,255,255),2) cv2.putText(img, f'Solidity={solid}', (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) cv2.putText(img, f'Equivalent Diameter={dia}', (x, y+30), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 0), 2) print(f"Solidity of object {i+1}: ", solid) print(f"Equivalent Diameter of object {i+1}: ", dia) cv2.imshow("Solidity and Equi Diameter", img) cv2.waitKey(0) cv2.destroyAllWindows()

我们将此图像用作此程序中的**输入文件**:

输出

执行上述代码后,将产生以下输出:

Number of objects detected: 3 
Solidity of object 1: 0.55 
Equivalent Diameter of object 1: 74.47 
Solidity of object 2: 0.73 
Equivalent Diameter of object 2: 102.72 
Solidity of object 3: 0.8 
Equivalent Diameter of object 3: 141.32

我们将获得以下**输出**窗口:

凸包以黄色绘制。它还显示每个物体的填充率和等效直径。

更新于:2022年9月28日

1K+ 次浏览

开启你的职业生涯

通过完成课程获得认证

开始学习
广告