Как обрезать объект / получить информацию о местоположении из изображения, используя OpenCV контур - PullRequest
3 голосов
/ 30 мая 2019

Я сгенерировал изображения из UE4, используя UnrealCV, и каждое изображение имеет формат RGB, а также формат маски. Каждое изображение содержит только один объект и фон также присутствует. Большую часть времени форма объекта является прямоугольной / квадратной. Я хочу обрезать, а также иметь местоположение только объекта. Я знаю, если я получу местоположение, используя контур, то обрезка будет легкой. Я также сделал это для какого-то объекта. Но проблема в том, что для каждого объекта это не работает. Иногда говорят, что контур не обнаружен, иногда обнаруживают неправильный контур. У меня вопрос, есть ли какая-то основополагающая истина, которая будет решением для каждого моего изображения?

До сих пор я выполнил преобразование BGR2GRAY, затем выполнил настройку порогового значения (также было выполнено адаптивное определение порогового значения), а затем попытался найти контур. Я также попытался сделать шаги после преобразования BGR2HSV, но каждый раз не получалось. Я даю код, который я пробовал

import numpy as np
import cv2
import os

rgb=cv2.imread('image_path/rgb_1.png')
mask = cv2.imread('image_path/mask_1.png')

imgray=cv2.cvtColor(mask,cv2.COLOR_BGR2GRAY)

ret,thresh = cv2.threshold(imgray,127,255,0)
# ret,thresh = cv2.threshold(imgray,127,255,cv2.THRESH_BINARY_INV)
# thresh = cv2.adaptiveThreshold(imgray,255,cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY,11,2)
# thresh = cv2.adaptiveThreshold(imgray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)
#Here I have given all the thresholding way that I have tried

image, contours, hierarchy =  cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
if len(contours)>0:
    print('here length of contours: ',len(contours))
    cnt=contours[0]
    x,y,w,h = cv2.boundingRect(cnt)

    draw_contour_mask=cv2.rectangle(mask,(x,y),(x+w,y+h),(255,255,255),1) #draw this box on masked image
    # cv2.imshow('rec_mask',draw_contour_mask)

    draw_contour_rgb=cv2.rectangle(rgb,(x,y),(x+w,y+h),(255,255,255),1) #draw this box on rgb image
    # cv2.imshow('rec_rgb_chair',draw_contour_rgb)

    crop_rgb = draw_contour_rgb[y:y+h, x:x+w] #to crop the applied bounded box
    cv2.imshow("cropped_chair", crop_rgb)


    if cv2.waitKey() == ord('q'): #press q to close the output image window
        cv2.destroyAllWindows()
else:
    print('Now length of contours: ',len(contours))
    pass

if cv2.waitKey() == ord('q'): #press q to close the output image window
        cv2.destroyAllWindows()

Здесь [ некоторые примеры изображений ] https://imgur.com/a/Gsa75Dg приведены для вашего удобства.

Если вам нужна дополнительная информация, пожалуйста, дайте мне знать. Надеюсь получить ответ и решить проблему.

1 Ответ

1 голос
/ 30 мая 2019

Вот простой подход с использованием некоторой фильтрации.Основная идея заключается в следующем:

  • Преобразование изображения в оттенки серого
  • Выполнение обнаружения Canny edge
  • Расширение изображения для подключения поврежденных компонентов
  • Поиск контуров и фильтраиспользуя соотношение сторон
  • Обрезка требуемой области интереса

Начиная с вашего "маскирующего изображения 2", мы выполняем обнаружение острых краев

enter image description here

Далее мы расширяем его, чтобы соединить контуры

enter image description here

Затем мы находим контуры и фильтр для ROI.Для прямоугольника / квадрата соотношение сторон может быть между 0.8 и 1.6, но может варьироваться в зависимости от изображения.Для обнаружения других объектов вы можете изменить соотношение сторон.Если вы хотите еще больше фильтрации, вы можете добавить в минимальную / максимальную область контура с помощью cv2.contourArea().

enter image description here

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

ROI = original_copy[y:y+h, x:x+w]

enter image description here

import cv2

original_image = cv2.imread('1.png')
original_copy = original_image.copy()
image = cv2.imread('2.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
canny = cv2.Canny(gray, 130, 255, 1)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
dilate = cv2.dilate(canny, kernel, iterations=1)

cnts = cv2.findContours(dilate, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

for c in cnts:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.01 * peri, True)
    x,y,w,h = cv2.boundingRect(approx)
    aspect_ratio = w / float(h)

    if (aspect_ratio >= 0.8 and aspect_ratio <= 1.6):
        ROI = original_copy[y:y+h, x:x+w]
        cv2.rectangle(original_image,(x,y),(x+w,y+h),(0,255,0),3)

cv2.imshow('canny', canny)
cv2.imshow('dilate', dilate)
cv2.imshow('original image', original_image)
cv2.imshow('ROI', ROI)
cv2.waitKey(0)
...