如何使用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()
让我们看一些示例以更清楚地理解。
Example 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()
我们将使用此图像作为此程序中的 输入文件 −
输出
当我们执行上面的代码时,它将产生以下输出−
检测到的对象数:1
固定度:0.7
等效直径: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()
我们将使用此图像作为程序中的输入文件,操作如下:
输出结果
执行以上代码后,将产生以下输出结果 :
检测到的物体数量:3
第1个物体的紧密度:0.55
第1个物体的等效直径:74.47
第2个物体的紧密度:0.73
第2个物体的等效直径:102.72
第3个物体的紧密度:0.8
第3个物体的等效直径:141.32
然后,我们可以在下方窗口获取以下 输出结果 :
凸包用黄色绘制。它还显示每个物体的紧密度和等效直径。