Я думаю, это связано с тем, что код поиска контура возвращает точный контур, который, возможно, из-за ошибок совмещения имен, на самом деле длиннее, чем должен быть.Если я сглаживаю получающийся контур, я получаю «правильное» значение ~ 1.
import cv2
import numpy as np
from scipy.interpolate import splprep, splev
image = cv2.imread("circle.png", 0)
_, thresh = cv2.threshold(image, 127, 255, 0)
# remove extra dimensions here to simplify later code
[contour], hierarchy = cv2.findContours(thresh, 1, 2)
contour = contour[:,0,:]
# smooth contour
tck, u = splprep(contour.T, u=None, s=30, per=1)
u_new = np.linspace(u.min(), u.max(), 50)
new_cont = np.column_stack(splev(u_new, tck, der=0))
# change types to stop cv2 complaining
new_cont = new_cont.astype(np.float32)
# calculate as before
area = cv2.contourArea(new_cont)
circum = cv2.arcLength(new_cont, True)
(4 * pi * area) / (circum**2)
, что дает мне 0.9986, что для меня нормально.Обратите внимание, что если вы работаете с OpenCV версии 3, вам нужно изменить строку findContours
, поскольку она возвращает тройку вместо пары значений .
Я позаимствовалbspline сглаживающий код из здесь , который, по-видимому, в свою очередь заимствован из здесь .Вы можете поиграть с различными коэффициентами сглаживания (попробуйте уменьшить s
до 1) и указать, где его сэмплировать (измените последний параметр на linspace
).