Я пытаюсь определить количество труб на этой картинке. Для этого я использую OpenCV и обнаружение на основе Python. Основываясь на существующих ответах на подобные вопросы, я смог придумать следующие шаги
- Откройте изображение
- Фильтруйте это
- Применить обнаружение края
- Использовать контуры
- Проверьте на счет
Общее количество каналов составляет ~ 909, если мы посчитаем это вручную или 4.
После применения фильтра
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv2.imread('images/input-rectpipe-1.jpg')
blur_hor = cv2.filter2D(img[:, :, 0], cv2.CV_32F, kernel=np.ones((11,1,1), np.float32)/11.0, borderType=cv2.BORDER_CONSTANT)
blur_vert = cv2.filter2D(img[:, :, 0], cv2.CV_32F, kernel=np.ones((1,11,1), np.float32)/11.0, borderType=cv2.BORDER_CONSTANT)
mask = ((img[:,:,0]>blur_hor*1.2) | (img[:,:,0]>blur_vert*1.2)).astype(np.uint8)*255
Я получаю это изображение в маске
Это выглядит довольно точно с точки зрения количества видимых прямоугольников, которые он показывает. Однако, когда я пытаюсь взять счетчик и нанести ограничивающий прямоугольник на верхнюю часть изображения, он также выделяет много нежелательных областей. Для кругов в HoughCircles есть способ определения максимального и минимального радиуса. Есть ли что-то подобное для прямоугольников, которое может улучшить точность. Также я открыт для предложений по альтернативным подходам к этой проблеме.
ret,thresh = cv2.threshold(mask,127,255,0)
contours,hierarchy = cv2.findContours(thresh, 1, 2)
count = 0
for i in range(len(contours)):
count = count+1
x,y,w,h = cv2.boundingRect(contours[i])
rect = cv2.minAreaRect(contours[i])
area = cv2.contourArea(contours[i])
box = cv2.boxPoints(rect)
ratio = w/h
M = cv2.moments(contours[i])
if M["m00"] == 0.0:
cX = int(M["m10"] / 1 )
cY = int(M["m01"] / 1 )
if M["m00"] != 0.0:
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
if (area > 50 and area < 220 and hierarchy[0][i][2] < 0 and (ratio > .5 and ratio < 2)):
#cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)
cv2.circle(img, (cX, cY), 1, (255, 255, 255), -1)
count = count + 1
print(count)
cv2.imshow("m",mask)
cv2.imshow("f",img)
cv2.waitKey(0)
ОБНОВЛЕНИЕ На основе второго ответа я преобразовал код C ++ в код Python и получил более близкие результаты, но все еще упускал несколько очевидных прямоугольников.
Ответы:
Конечно, вы можете отфильтровать их по площади. Я взял ваше двоичное изображение и продолжил работу, как показано ниже:
1. Сделайте цикл по всем контурам, которые вы нашли в findContours
2- В цикле проверьте, является ли каждый контур внутренним контуром или нет
3- Из тех, которые являются внутренними контурами, проверьте их площадь и, если область находится в приемлемом диапазоне, проверьте соотношение ширины / высоты каждого контура и, наконец, если он также хорош, считайте этот контур как трубу.
Я сделал вышеупомянутый метод на вашем двоичном изображении и нашел 794 канала :
(Однако некоторые поля потеряны. Вы должны изменить параметры детектора краев, чтобы получить более четкие рамки на изображении.)
и вот код (это C ++, но легко конвертируется в Python):
источник
Есть много методов для решения этой проблемы, но я сомневаюсь, что будет один метод без каких-либо специальных мер. Вот еще одна попытка этой проблемы.
Вместо того, чтобы использовать информацию о краях, я предлагаю фильтр, подобный LBP (локальный двоичный шаблон), который сравнивает окружающий пиксель с центральным значением. Если определенный процент окружающего пикселя больше, чем центральный пиксель, центральный пиксель будет помечен 255. Если условие не выполнено, то центральный пиксель будет помечен 0.
Этот метод основан на предположении, что центр трубы всегда темнее, чем края трубы. Поскольку он сравнивает интенсивность, он должен работать хорошо, пока сохраняется некоторый контраст.
Благодаря этому процессу вы получите изображение с двоичными каплями для каждой трубы и некоторыми шумами. Вам придется удалить их с некоторыми заранее известными условиями, такими как, размер, форма, fill_ratio, цвет и т. Д. Условие можно найти в данном коде.
Результат от LBP-подобной обработки
После очистки с морфологическим процессом
Окончательный результат с красными прямоугольниками, показывающими все кандидаты в BLOB, и желтыми сегментами, показывающими BLOB-объекты, которые отвечают всем установленным нами условиям. Ниже и сверху трубного пучка есть несколько ложных тревог, но они могут быть опущены при некоторых граничных условиях.
Всего найдено труб: 943
источник