Я только начинаю играть с OpenCV и обнаружил очень странное поведение в функции contourArea.
Смотрите это изображение.
У него три не связанные области, слева - группа длинных штрихов, а в центре вверху - одна точка и, наконец, большой квадрат справа.
Когда я запускаю свою функцию Я получаю этот результат
Contour[0] Area: 221, Length: 70, Colour: Red
Contour[1] Area: 13772, Length: 480, Colour: Green
Contour[2] Area: 150, Length: 2370, Colour: Blue
Хотя я фактически не посчитал площадь левой части, кажется, что она охватывает гораздо больше, чем 150 пикселей и, безусловно, будет иметь более высокое значение, чем точка в верхнем центре, я бы сказал, что точка должна быть в состоянии вписаться в левую часть по крайней мере 10 раз. Площадь квадрата действительно работает.
Square Area
width = 118
height = 116
118 * 116 = 13,688
13 688 действительно близко к тому, что opencv дал как площадь (13 772), разница, скорее всего, ошибка измерения от моего имени. Я вручную вычислил площадь точки
Dot Area
width = 27
height = 6
27*6 = 162
Не слишком далеко от того, что OpenCV сказал, что это будет (221)
Чтение со страницы документов OpenCV на contourArea это говорит о том, что это даст неправильные результаты для контуров с самопересечениями. Не совсем понимая, что такое самопересечения, я сделал тестовое изображение.
Как вы видите, у меня есть прямоугольник слева и крестик в средний и другой крест повернут на 45 градусов. Я ожидаю, что площадь креста будет немного меньше, чем удвоенная площадь прямоугольника из-за перекрытия в центре.
Contour[0] Area: 1805, Length: 423, Colour: Red
Contour[1] Area: 947, Length: 227, Colour: Green
Contour[2] Area: 1825, Length: 415, Colour: Blue
Как вы Можно увидеть площадь двух крестов, чуть меньше удвоенной площади прямоугольника. Как и ожидалось.
Я не заинтересован в том, чтобы захватить внутреннюю часть квадрата или нарисовать прямоугольник вокруг фигуры слева и точки (хотя это было бы очень интересно), это не совсем то, о чем я спрашиваю в этом вопрос.
Итак, мой вопрос: почему площадь моей неправильной формы сильно недооценена?
- Я использую неправильную функцию?
- Я правильно использую правильную функцию?
- Нашел ли я ошибку в opencv?
- Имеет ли само пересечение значение, которое не было продемонстрировано в моем тесте?
Я скопировал большую часть этого кода из этого урока
Я сократил свой код этого автономного примера ниже.
def contour_test(name):
import cv2 as cv
colours = [{'name': 'Red ', 'bgr': (0, 0, 255)},
{'name': 'Green ', 'bgr': (0, 255, 0)},
{'name': 'Blue ', 'bgr': (255, 0, 0)}]
src = cv.imread(cv.samples.findFile(name))
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
src_gray = cv.blur(src_gray, (3,3))
threshold = 100
canny_output = cv.Canny(src_gray, threshold, threshold * 2)
contours, _ = cv.findContours(canny_output, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
# Get the moments
mu = [None for i in contours]
for i in range(len(contours)):
mu[i] = cv.moments(contours[i])
# Get the mass centers
mc = [None for i in contours]
for i in range(len(contours)):
mc[i] = (mu[i]['m10'] / (mu[i]['m00'] + 1e-5), mu[i]['m01'] / (mu[i]['m00'] + 1e-5))
# Draw contours
drawing = np.zeros((canny_output.shape[0], canny_output.shape[1], 3), dtype=np.uint8)
for i, j in enumerate(contours):
colour = colours[i]['bgr']
cv.drawContours(drawing, contours, i, colour, 2)
area = int(cv.contourArea(contours[i]))
length = int(cv.arcLength(contours[i], True))
print('Contour[{0}] Area: {1}, Length: {2}, Colour: {3}'.format(i, area, length, colours[i]['name']))