У вас правильная идея, но я думаю, что вы злоупотребляете cv2.morphologyEx
, чтобы постоянно разрушать и расширять изображение.Вы упоминаете о своей проблеме:
В настоящее время мой код иногда размещает несколько меньших ограничивающих рамок вокруг разных частей единственного изображения вместо создания одной большой рамки вокруг изображения.
Когда вы используете cv2.findContours
, он работает правильно, но так как ваши контуры на самом деле являются каплями, а не одним взаимосвязанным единичным изображением, он создает несколько ограничивающих рамок.Чтобы устранить эту проблему, вы можете расширить изображение, чтобы соединить капли вместе.
Я переписал ваш код без лишних cv2.morphologyEx
повторений.Основная идея заключается в следующем:
- Преобразование изображения в оттенки серого
- Размытие изображения
- Пороговое изображение для отделения фона от нужного объекта
- РасширениеИзображение для подключения больших двоичных объектов для формирования единственного изображения
- Поиск контуров и контуров фильтров с использованием минимальной / максимальной области порога
Пороговое изображение для выделения нужных участков.Обратите внимание, что некоторые контуры имеют разорванные соединения.Чтобы исправить это, мы расширяем изображение, чтобы соединить капли.
Расширяем изображение для формирования единичных объектов.Теперь обратите внимание, что у нас есть нежелательный горизонтальный участок внизу, мы можем найти контуры, а затем отфильтровать, используя область, чтобы удалить этот участок.
Результаты
import numpy as np
import cv2
original_image = cv2.imread("1.jpg")
image = original_image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (3, 3), 0)
thresh = cv2.threshold(blurred, 160, 255, cv2.THRESH_BINARY_INV)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
dilate = cv2.dilate(thresh, kernel , iterations=4)
cv2.imshow("thresh", thresh)
cv2.imshow("dilate", dilate)
# Find contours in the image
cnts = cv2.findContours(dilate.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
contours = []
threshold_min_area = 400
threshold_max_area = 3000
for c in cnts:
x,y,w,h = cv2.boundingRect(c)
area = cv2.contourArea(c)
if area > threshold_min_area and area < threshold_max_area:
# cv2.drawContours(original_image,[c], 0, (0,255,0), 3)
cv2.rectangle(original_image, (x,y), (x+w, y+h), (0,255,0),1)
contours.append(c)
cv2.imshow("detected", original_image)
print('contours detected: {}'.format(len(contours)))
cv2.waitKey(0)