Python實現任意多邊形的最大內切圓演算法

2021-10-05 04:58:37 字數 3837 閱讀 4481

參考matlab計算輪廓內切圓

初衷是為了求裂縫的最大寬度

直接上**

import random

import cv2

import math

import numpy as np

from numpy.ma import cos, sin

import matplotlib.pyplot as plt

def max_circle(f):

img = cv2.imread(f, cv2.imread_color)

img_gray = cv2.cvtcolor(img, cv2.color_bgr2gray)

# _, img_gray = cv2.threshold(img_gray, 0, 255, cv2.thresh_binary + cv2.thresh_otsu)

"""cv2.retr_external表示只檢測外輪廓

cv2.retr_list檢測的輪廓不建立等級關係

cv2.retr_ccomp建立兩個等級的輪廓,上面的一層為外邊界,裡面的一層為內孔的邊界資訊。如果內孔內還有乙個連通物體,這個物體的邊界也在頂層。

cv2.retr_tree建立乙個等級樹結構的輪廓。

第三個引數method為輪廓的近似辦法

"""for c in contous:

left_x = min(c[:, 0, 0])

right_x = max(c[:, 0, 0])

down_y = max(c[:, 0, 1])

up_y = min(c[:, 0, 1])

upper_r = min(right_x - left_x, down_y - up_y) / 2

# 定義相切二分精度

precision = math.sqrt((right_x - left_x) ** 2 + (down_y - up_y) ** 2) / (2 ** 13)

# 構造包含輪廓的矩形的所有畫素點

nx = 2 ** 8

ny = 2 ** 8

pixel_x = np.linspace(left_x, right_x, nx)

pixel_y = np.linspace(up_y, down_y, ny)

# [pixel_x, pixel_y] = ndgrid(pixel_x, pixel_y);

# pixel_x = reshape(pixel_x, numel(pixel_x), 1);

# pixel_y = reshape(pixel_y, numel(pixel_y), 1);

xx, yy = np.meshgrid(pixel_x, pixel_y)

# % 篩選出輪廓內所有畫素點

in_list =

for c in contous:

for i in range(pixel_x.shape[0]):

for j in range(pixel_x.shape[0]):

if cv2.pointpolygontest(c, (xx[i][j], yy[i][j]), false) > 0:

in_point = np.array(in_list)

pixel_x = in_point[:, 0]

pixel_y = in_point[:, 1]

# 隨機搜尋百分之一畫素提高內切圓半徑下限

n = len(in_point)

rand_index = random.sample(range(n), n // 100)

rand_index.sort()

radius = 0

big_r = upper_r

center = none

for id in rand_index:

tr = iterated_optimal_incircle_radius_get(c, in_point[id][0], in_point[id][1], radius, big_r, precision)

if tr > radius:

radius = tr

center = (in_point[id][0], in_point[id][1]) # 只有半徑變大才允許位置變更,否則保持之前位置不變

# 迴圈搜尋剩餘畫素對應內切圓半徑

loops_index = [i for i in range(n) if i not in rand_index]

for id in loops_index:

tr = iterated_optimal_incircle_radius_get(c, in_point[id][0], in_point[id][1], radius, big_r, precision)

if tr > radius:

radius = tr

center = (in_point[id][0], in_point[id][1]) # 只有半徑變大才允許位置變更,否則保持之前位置不變

# 效果測試

plot_x = np.linspace(0, 2 * math.pi, 100)

circle_x = center[0] + radius * cos(plot_x)

circle_y = center[1] + radius * sin(plot_x)

print(radius * 2)

plt.figure()

plt.imshow(img_gray)

plt.plot(circle_x, circle_y)

plt.show()

def iterated_optimal_incircle_radius_get(contous, pixelx, pixely, small_r, big_r, precision):

radius = small_r

l = np.linspace(0, 2 * math.pi, 360) # 確定圓散點剖分數360, 720

circle_x = pixelx + radius * cos(l)

circle_y = pixely + radius * sin(l)

for i in range(len(circle_y)):

if cv2.pointpolygontest(contous, (circle_x[i], circle_y[i]), false) < 0: # 如果圓散集有在輪廓之外的點

return 0

while big_r - small_r >= precision: # 二分法尋找最大半徑

half_r = (small_r + big_r) / 2

circle_x = pixelx + half_r * cos(l)

circle_y = pixely + half_r * sin(l)

if_out = false

for i in range(len(circle_y)):

if cv2.pointpolygontest(contous, (circle_x[i], circle_y[i]), false) < 0: # 如果圓散集有在輪廓之外的點

big_r = half_r

if_out = true

if not if_out:

small_r = half_r

radius = small_r

return radius

if __name__ == '__main__':

max_circle('thresh_crack.png')

C 實現 任意多邊形的面積

求任意多邊形的面積 語法 result polygonarea vector polygon,int n 引數 polygon 多變形頂點陣列 n 多邊形頂點數目 返回值 多邊形面積 注意 支援任意多邊形,凹 凸皆可 多邊形頂點輸入時按順時針順序排列 include include using na...

任意多邊形面積

給定多邊形的頂點座標 有序 讓你來求這個多邊形的面積,你會怎麼做?我們知道,任意多邊形都可以分割為n個三角形,所以,如果以這為突破點,那麼我們第一步就是把給定的多邊形,分割為數個三角形,分別求面積,最後累加就可以了,把多邊形分割為三角形的方式多種多樣,在這裡,我們按照如下圖的方法分割 s點作為起始點...

任意多邊形的面積

給定多邊形的頂點座標 有序 讓你來求這個多邊形的面積,你會怎麼做?我們知道,任意多邊形都可以分割為n個三角形,所以,如果以這為突破點,那麼我們第一步就是把給定的多邊形,分割為數個三角形,分別求面積,最後累加就可以了,把多邊形分割為三角形的方式多種多樣,在這裡,我們按照如下圖的方法分割 s點作為起始點...