如何使用opencv轮廓裁剪对象/从图像中获取位置信息

时间:2019-05-30 11:02:53

标签: python opencv image-processing opencv-contour

我已经使用UnrealCV从UE4生成了图像,每个图像都具有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 个答案:

答案 0 :(得分:0)

这是使用一些过滤的简单方法。主要思想是:

  • 将图像转换为灰度
  • 执行Canny边缘检测
  • 扩大图像以连接损坏的组件
  • 使用宽高比查找轮廓和过滤器
  • 收获理想的投资回报率

从您的“蒙版图像2”开始,我们执行精巧边缘检测

enter image description here

接下来,我们将其放大以连接轮廓

enter image description here

然后我们找到轮廓并过滤ROI。对于矩形/正方形,长宽比可能在0.81.6之间,但可能会因图像而异。要检测其他对象,可以更改纵横比。如果要进行更多过滤,可以使用cv2.contourArea()在最小/最大轮廓区域中添加。

enter image description here

一旦有了所需的ROI,我们将绘制边界框并使用old answer裁剪图像。

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)