前段時間我將網(wǎng)上最大內(nèi)切圓算法進行了代碼的整理,原先博主上傳的代碼稍微有點亂,可能也是它自己使用,大家可以看這篇整理好的:最大內(nèi)切圓算法計算裂縫寬度。
最大內(nèi)切圓算法詳解
一個圓與給定的多邊形或曲線的每一條邊或曲線都相切的圓。而我們就是需要計算的是給定圖像的輪廓的最大內(nèi)切圓,也就是與輪廓的每一條邊都相切的圓中直徑最大的圓。這樣直徑就是我們的輪廓的寬度了。
既然要求輪廓的內(nèi)接圓,從圓的特點來說,想要唯一的確定一個圓,就是要知道它的圓心和半徑。好的,那現(xiàn)在的問題就從求取輪廓的內(nèi)接圓,巧妙地轉(zhuǎn)變成求取某個點和一個多邊形的距離和關(guān)系。
在opencv中有一個函數(shù)pointPolygonTest就是能夠得到某個點和某個多邊形之間的關(guān)系,例如這個點是在多邊形內(nèi)部、外部、或者是在多邊形上,還能得到該點距離多邊形的像素距離。那問題其實就很好解決了。我們再使用cv2.minMaxLoc(src)來獲得給定的數(shù)組中尋找最小值和最大值的位置,它的語法如下
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(src)
其中,src是輸入的數(shù)組或圖像。函數(shù)會返回最小值min_val和最大值max_val,以及它們在數(shù)組中的位置最小值的位置min_loc和最大值的位置max_loc。?
講到這里我想大家也知道怎么求輪廓的寬度了吧,即為:max_loc * 2。
詳細代碼
import cv2
import string
import numpy as np
import pyzjr as pz
def incircle(img, contours_arr, color=(0, 0, 255)):
"""
輪廓最大內(nèi)切圓算法,所有輪廓當(dāng)中的內(nèi)切圓
"""
result = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
raw_dist = np.zeros(img.shape, dtype=np.float32)
letters = list(string.ascii_uppercase)
label = {}
for k, contours in enumerate(contours_arr):
for i in range(img.shape[0]):
for j in range(img.shape[1]):
raw_dist[i, j] = cv2.pointPolygonTest(contours, (j, i), True)
min_val, max_val, _, max_dist_pt = cv2.minMaxLoc(raw_dist)
label[letters[k]] = max_val * 2
radius = int(max_val)
cv2.circle(result, max_dist_pt, radius, color, 1, 1, 0)
return result, label
if __name__=="__main__":
path = r"D:\PythonProject\RoadCrack\dimension2_data\num/001.png"
img = cv2.imread(path)
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
thresh = pz.BinaryImg(img)
contours_arr, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
result, label = incircle(gray_img, contours_arr)
print("裂縫寬度:",label)
cv2.imwrite("result.png",result)
先檢測輪廓,你可以使用opencv的findContours。需要確保是ndarray數(shù)組的形式。
裂縫寬度: {'A': 5.656854152679443, 'B': 4.4721360206604}
現(xiàn)在我們就能知道兩條裂縫對應(yīng)的最大內(nèi)切圓直徑,即裂縫的寬度。
算法對比
并且從時間角度來看:
- 原先的最大內(nèi)切圓算法: 1.79125 sec
- 改進后的內(nèi)切圓算法:??1.05487 sec
從計算的直徑上來看:文章來源:http://www.zghlxwxcb.cn/news/detail-730674.html
- 原先的最大內(nèi)切圓算法:13.81
- 改進后的內(nèi)切圓算法:{'A': 14.0}
這里的實現(xiàn)比較簡單,只是嵌套的循環(huán)比較多,但能存儲每條裂縫對應(yīng)的寬度。文章來源地址http://www.zghlxwxcb.cn/news/detail-730674.html
2023/10/22更新
# pip install pyzjr==1.2.5
import cv2
import pyzjr as pz
from pyzjr.augmentation import incircle
if __name__=="__main__":
path = r"D:\PythonProject\RoadCrack\dimension2_data\num/001.png"
img = cv2.imread(path)
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
thresh = pz.BinaryImg(img)
contours_arr, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
result, label = incircle(gray_img, contours_arr)
print("裂縫寬度:",label)
cv2.imwrite("result.png",result)
到了這里,關(guān)于改進的最大內(nèi)切圓算法求裂縫輪廓寬度的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!