Я пытаюсь найти область внутри замкнутой кривой произвольной формы, построенной на питоне (пример изображения ниже). До сих пор я пытался использовать как метод альфа-формы, так и метод многоугольника, чтобы добиться этого, но оба потерпели неудачу. Теперь я пытаюсь использовать OpenCV и метод заливки для подсчета количества пикселей внутри кривой, а затем я позже преобразую это в область с учетом области, которую один пиксель охватывает на графике. Пример изображения: testplot.jpg
Для этого я делаю следующее, которое я адаптировал из другого поста об OpenCV.
import cv2
import numpy as np
# Input image
img = cv2.imread('testplot.jpg', cv2.IMREAD_GRAYSCALE)
# Dilate to better detect contours
temp = cv2.dilate(temp, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)))
# Find largest contour
cnts, _ = cv2.findContours(255-temp, cv2.RETR_TREE , cv2.CHAIN_APPROX_NONE) #255-img and cv2.RETR_TREE is to account for how cv2 expects the background to be black, not white, so I convert the background to black.
largestCnt = [] #I expect this to yield the blue contour
for cnt in cnts:
if (len(cnt) > len(largestCnt)):
largestCnt = cnt
# Determine center of area of largest contour
M = cv2.moments(largestCnt)
x = int(M["m10"] / M["m00"])
y = int(M["m01"] / M["m00"])
# Initial mask for flood filling, should cover entire figure
width, height = temp.shape
mask = img2 = np.ones((width + 2, height + 2), np.uint8) * 255
mask[1:width, 1:height] = 0
# Generate intermediate image, draw largest contour onto it, flood fill this contour
temp = np.zeros(temp.shape, np.uint8)
temp = cv2.drawContours(temp, largestCnt, -1, 255, cv2.FILLED)
_, temp, mask, _ = cv2.floodFill(temp, mask, (x, y), 255)
temp = cv2.morphologyEx(temp, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)))
area = cv2.countNonZero(temp) #Number of pixels encircled by blue line
Я ожидаю от этого получить то же самое изображение, что и выше, но с центром контура, заполненным белым, а фон и исходный синий контур черным. Я заканчиваю с этим:
Хотя на первый взгляд кажется, что это точно превратило область внутри контура в белый цвет, белая область на самом деле больше, чем область внутри контура, и поэтому результат, который я получаю, переоценивает количество пикселей внутри него. Любой вклад в это будет принят с благодарностью. Я новичок в OpenCV, поэтому, возможно, я что-то неправильно понял.
РЕДАКТИРОВАТЬ: благодаря комментарию ниже я внес некоторые изменения, и теперь это мой код с отмеченными изменениями:
import cv2
import numpy as np
# EDITED INPUT IMAGE: Input image
img = cv2.imread('testplot2.jpg', cv2.IMREAD_GRAYSCALE)
# EDIT: threshold
_, temp = cv2.threshold(img, 250, 255, cv2.THRESH_BINARY_INV)
# EDIT, REMOVED: Dilate to better detect contours
# Find largest contour
cnts, _ = cv2.findContours(temp, cv2.RETR_EXTERNAL , cv2.CHAIN_APPROX_NONE)
largestCnt = [] #I expect this to yield the blue contour
for cnt in cnts:
if (len(cnt) > len(largestCnt)):
largestCnt = cnt
# Determine center of area of largest contour
M = cv2.moments(largestCnt)
x = int(M["m10"] / M["m00"])
y = int(M["m01"] / M["m00"])
# Initial mask for flood filling, should cover entire figure
width, height = temp.shape
mask = img2 = np.ones((width + 2, height + 2), np.uint8) * 255
mask[1:width, 1:height] = 0
# Generate intermediate image, draw largest contour, flood filled
temp = np.zeros(temp.shape, np.uint8)
temp = cv2.drawContours(temp, largestCnt, -1, 255, cv2.FILLED)
_, temp, mask, _ = cv2.floodFill(temp, mask, (x, y), 255)
temp = cv2.morphologyEx(temp, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)))
area = cv2.countNonZero(temp) #Number of pixels encircled by blue line
Я ввожу другое изображение с осями и кадром, который python добавляет по умолчанию, удаленным для простота. Я получаю то, что ожидаю, на втором этапе, поэтому это изображение. Однако в поле введите здесь описание изображения как исходный контур, так и область, которую он окружает. сделать белым, тогда как я хочу, чтобы исходный контур был черным, и только область, которую он окружает, была белой. Как я могу этого добиться?