如何使用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
我们将获得以下**输出**窗口:
凸包以黄色绘制。它还显示每个物体的填充率和等效直径。