Как обрезать изображение вдоль главной оси капли/контура с прямоугольной ограничивающей рамкой с помощью Python

Я хотел бы обрезать изображение с выделенной оранжевым цветом областью, нарисованной от руки, как показано ниже,

введите здесь описание изображения

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

введите здесь описание изображения

Вот что я пробовал,

import numpy as np
import cv2

# load the image
image = cv2.imread("frame50.jpg", 1)

#color boundaries [B, G, R]
lower = [0, 3, 30]
upper = [30, 117, 253]

# create NumPy arrays from the boundaries
lower = np.array(lower, dtype="uint8")
upper = np.array(upper, dtype="uint8")

# find the colors within the specified boundaries and apply
# the mask
mask = cv2.inRange(image, lower, upper)
output = cv2.bitwise_and(image, image, mask=mask)

ret,thresh = cv2.threshold(mask, 50, 255, 0)
if (int(cv2.__version__[0]) > 3):
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
else:
    im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

if len(contours) != 0:
    # find the biggest countour (c) by the area
    c = max(contours, key = cv2.contourArea)
    x,y,w,h = cv2.boundingRect(c)
    ROI = image[y:y+h, x:x+w]
cv2.imshow('ROI',ROI)
cv2.imwrite('ROI.png',ROI)

cv2.waitKey(0)

В большинстве случаев это не работает. Для некоторых изображений происходит следующее:

введите здесь описание изображения

Я хотел бы знать, есть ли лучший способ сделать это или как я могу исправить то, что у меня есть прямо сейчас. Обратите внимание, что выделенная область нарисована от руки и может иметь любую форму, но она закрыта, а не оставлена ​​открытой, а цвет изюминкой является сам оттенок оранжевого во всех случаях. И есть ли способ сохранить содержимое только внутри круга и затемнить все за его пределами?

EDIT1: я смог исправить неправильное отсечение, увеличив пороговое значение. Но мой главный вопрос сейчас таков: есть ли способ сохранить контент только внутри круга и затемнить все за его пределами? Я вижу маску, как показано ниже,

введите здесь описание изображения

Как мне заполнить эту маску и сохранить содержимое внутри круга и затемнить все за его пределами с той же прямоугольной ограничивающей рамкой?


person Nick Rogers    schedule 06.07.2020    source источник


Ответы (2)


Ты пытался

image[x:x+w, y:y+h]

И не могли бы вы установить флажок с кодом ниже

cv2.rectangle(thresh,(x,y),(x+w,y+h),(255,0,0),2)
person puhuk    schedule 06.07.2020
comment
Спасибо, где мне поставить строку bbox? Сорри, я нуб - person Nick Rogers; 06.07.2020
comment
И есть ли способ сохранить содержимое только внутри круга и затемнить все за его пределами? - person Nick Rogers; 06.07.2020
comment
я пробовал image [x: x + w, y: y + h], это не то, как нужно указывать индексы. image[y:y+h, x:x+w] работает правильно. - person Nick Rogers; 06.07.2020
comment
извините за поздний ответ, для строки bbox, не могли бы вы сослаться на ссылку ниже geeksforgeeks. org/python-opencv-cv2-прямоугольник-метод - person puhuk; 07.07.2020

Прежде всего, всегда лучше использовать изображение HSV вместо изображения BGR для маскирования (извлечения цвета). Вы можете сделать это с помощью следующего кода.

HSV_Image = cv2.cvtColor(Image, cv2.COLOR_BGR2HSV)
ThreshImage = cv2.inRange(HSV_Image, np.array([0, 28, 191]), np.array([24, 255, 255]))

В данном случае значения диапазона указаны для оранжевого цвета.

Image — это входное изображение, а ThreshImage — это выходное изображение, в котором оранжевая область окрашена в белый цвет, а все остальное — в черный.

Теперь поиск контура в ThreshImage с флагом cv2.RETR_EXTERNAL даст только один контур, который является внешней границей оранжевой области.

Contours, Hierarchy = cv2.findContours(ThreshImage, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

Чтобы обрезать оранжевую область:

BoundingRect = cv2.boundingRect(Contours[0])
(x, y, w, h) = BoundingRect
CroppedImage = Image[y:y+h, x:x+w].copy()

CroppedImage сохранит обрезанную оранжевую область по желанию.

Чтобы получить содержимое только внутри контура:

Здесь будет полезна побитовая операция И, так как мы уже обнаружили контур.

Во-первых, мы должны создать черное изображение той же формы, что и исходное изображение, и нарисовать контур, залитый белым цветом.

ContourFilledImage = np.zeros(Image.shape, dtype=np.uint8)
cv2.drawContours(ContourFilledImage, Contours, -1, (255, 255, 255), -1)

Теперь выполните побитовую операцию И над входным изображением и ContourFilledImage.

OnlyInnerData = cv2.bitwise_and(ContourFilledImage, Image)

Изображение OnlyInnerData — это желаемое выходное изображение, имеющее только содержимое внутри круга.

person Rahul Kedia    schedule 09.07.2020