Как удалить объект, отмеченный наибольшим контуром с изображения, и сохранить его как отдельное изображение? - PullRequest
2 голосов
/ 07 ноября 2019

Наша цель - классифицировать растения в поле на основе его листьев. Мы обучили нашу модель на сегментированных изображениях (эти изображения имеют только лист и черный фон). Но прямая трансляция с камеры будет выглядеть следующим образом:

enter image description here

Поэтому наша идея состоит в том, чтобы найти самый большой контур, отделить отмеченный им лист ивыделите его черным фоном.

biggest contour marked

Это своего рода то, чего мы пытаемся достичь (за исключением появления маленького листа):

enter image description here

Наш подход состоял в том, чтобы нарисовать ограничивающую рамку вокруг листа и сформировать новую отдельную рамку. Это наш код:

def nothing(useless=None):
    pass

cv2.namedWindow("Mask")
cap = cv2.VideoCapture(0)

cv2.createTrackbar('R_l','Mask',26,255,nothing)
cv2.createTrackbar('G_l','Mask',46,255,nothing)
cv2.createTrackbar('B_l','Mask',68,255,nothing)

cv2.createTrackbar('R_h','Mask',108,255,nothing)
cv2.createTrackbar('G_h','Mask',138,255,nothing)
cv2.createTrackbar('B_h','Mask',155,255,nothing)

while True:

    R_l = cv2.getTrackbarPos('R_l', 'Mask')
    G_l = cv2.getTrackbarPos('G_l', 'Mask')
    B_l = cv2.getTrackbarPos('B_l', 'Mask')

    R_h = cv2.getTrackbarPos('R_h', 'Mask')
    G_h = cv2.getTrackbarPos('G_h', 'Mask')
    B_h = cv2.getTrackbarPos('B_h', 'Mask')

    _,frame = cap.read()
    blurred_frame = cv2.blur(frame,(5,5),0)

    hsv_frame = cv2.cvtColor(blurred_frame,cv2.COLOR_BGR2HSV)

    low_green = np.array([R_l, G_l, B_l])
    high_green = np.array([R_h, G_h, B_h])
    green_mask = cv2.inRange(hsv_frame, low_green, high_green)
    green = cv2.bitwise_and(frame, frame, mask=green_mask)

    contours,_ = cv2.findContours(green_mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)

    try:
        sorted_ = sorted(contours,key=cv2.contourArea,reverse=True)
        biggest = sorted_[0]
        cv2.drawContours(frame,biggest,-1,(255,0,0),1)
    except :
        pass
    #kernel = np.zeros(frame.shape(), np.uint8)
    x,y,w,h=cv2.boundingRect(biggest)
    roi= frame[y:y+h, x:x+w] 
    blurred_frame1 = cv2.blur(roi,(5,5),0)
    hsv_frame1 = cv2.cvtColor(blurred_frame1,cv2.COLOR_BGR2HSV)
    low_green1 = np.array([R_l, G_l, B_l])
    high_green1 = np.array([R_h, G_h, B_h])
    green_mask1 = cv2.inRange(hsv_frame1, low_green, high_green)
    green1= cv2.bitwise_and(roi,roi, mask=green_mask1)


    cv2.imshow("frame",frame)
    cv2.imshow("Mask",green1)
    key = cv2.waitKey(1)
    if key == 27:
        break
cap.release()
cv2.destroyAllWindows()

Как мы можем подготовить желаемое изображение?

1 Ответ

2 голосов
/ 08 ноября 2019

Вы на правильном пути. Я предлагаю использовать пороговое значение цвета HSV с нижним / верхним порогом, чтобы изолировать зеленые листья. Чтобы определить нижний / верхний диапазоны цветового порога HSV, я использовал скрипт цветового порога HSV из предыдущего ответа . Это даст нам бинарную маску. Отсюда мы выполняем морфологические операции, чтобы сгладить изображение и удалить шум. Далее мы находим контуры и сортируем их по области контура. Мы извлекаем самый большой контур, рисуем его на пустой маске, затем побитово - и получаем цвет. Отсюда мы находим координаты ограничивающего прямоугольника на маске, а затем обрезаем область интереса из цветного изображения, используя срез Numpy. Вот результат

enter image description here

Код

import numpy as np
import cv2

# Read image, create blank masks, color threshold
image = cv2.imread('1.jpg')
blank_mask = np.zeros(image.shape, dtype=np.uint8)
original = image.copy()
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower = np.array([0, 18, 0])
upper = np.array([88, 255, 139])
mask = cv2.inRange(hsv, lower, upper)

# Perform morphological operations
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=1)
close = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel, iterations=1)

# Find contours and filter for largest contour
# Draw largest contour onto a blank mask then bitwise-and
cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)[0]
cv2.fillPoly(blank_mask, [cnts], (255,255,255))
blank_mask = cv2.cvtColor(blank_mask, cv2.COLOR_BGR2GRAY)
result = cv2.bitwise_and(original,original,mask=blank_mask)

# Crop ROI from result
x,y,w,h = cv2.boundingRect(blank_mask)
ROI = result[y:y+h, x:x+w]

cv2.imshow('result', result)
cv2.imshow('ROI', ROI)
cv2.waitKey()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...