Удалите определенные точки из findContours, чтобы получить лучший результат от fitEllipse - PullRequest
0 голосов
/ 13 февраля 2019

Я хочу подогнать эллипс к частично поврежденному объекту на картинке.(Иллюстрации здесь являются только упрощенными примерами для иллюстрации!)

Изображение с поврежденным эллиптическим объектом

image

Делая это

def sort(n):
    return n.size

Image = cv2.imread('acA2500/1.jpg', cv2.IMREAD_GRAYSCALE)

#otsu binarization
_, binary = cv2.threshold(Image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

#invert binary image for opencv findContours
inverse_binary = cv2.bitwise_not(binary)

#find contours
contours, _ = cv2.findContours(inverse_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

#sort contours by length
largest_contours = sorted(contours, key=sort, reverse=True)

#fit ellipse
contour = largest_contours[0]
ellipse = cv2.fitEllipseDirect(contour)

Я получаю этот результат, который не очень удовлетворяет.

Результат cv2.findContours и cv2.fitEllipse

Итак, я построил этот цикл, чтобы избавиться от точек контура, которые не находятся на эллипсе.

contour = largest_contours[0]
newcontour = np.zeros([1, 1, 2])
newcontour = newcontour.astype(int)
for coordinate in contour:
    if coordinate[0][0] < 600:
        newcontour = np.insert(newcontour, 0, coordinate, 0)
newellipse = cv2.fitEllipse(newcontour)

И получить этот результат, который хорош.

Результат после обрезки точек контура

Проблема в том, что я должен сделатьМногие из них подходят в течение короткого периода времени.Пока что это не достигает желаемой скорости.

Есть ли какой-либо лучший / более быстрый / более хороший способ обрезки точек контура?Так как у меня нет большого опыта программирования, я был бы рад найти здесь некоторую помощь: -)

Редактировать:

Я отредактировал примеры изображений так,что теперь ясно, что, к сожалению, cv2.minEnclosingCircle подход не работает.

Также изображения теперь показывают, почему я сортирую контуры.В моем реальном коде я подгоняю эллипс к трем самым длинным контурам, чем вижу, какой из них я хочу использовать с помощью другой процедуры.

Если я не урежу контур и не выберу контур для cv2.fitEllipse от руки, код должен быть около 0.5s.С обрезкой контура и три раза cv2.fitEllipse это занимает около 2s.Это может занять всего 1s

1 Ответ

0 голосов
/ 13 февраля 2019

Если объект представляет собой круг, то вы можете использовать cv2.minEnclosingCircle на контуре, чтобы захватить его.

#!/usr/bin/python3
# 2019/02/13 08:50 (CST)
# https://stackoverflow.com/a/54661012/3547485

import cv2
img = cv2.imread('test.jpg')

## Convert to grayscale and threshed it
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
th, threshed = cv2.threshold(gray, 100, 255, cv2.THRESH_OTSU|cv2.THRESH_BINARY_INV)

## Find the max outers contour
cnts = cv2.findContours(threshed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2]
cv2.drawContours(img, cnts, -1, (255, 0, 0), 2, cv2.LINE_AA)

## Use minEnclosingCircle
(cx,cy),r = cv2.minEnclosingCircle(cnts[0])
cv2.circle(img, (int(cx), int(cy)), int(r), (0, 255, 0), 1, cv2.LINE_AA)

## This it
cv2.imwrite("dst.jpg", img)

Вот мой результат.

enter image description here

...