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

标签 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 为您提供了方便。

如果您需要更多信息,请告诉我。
希望得到回应并解决问题。

最佳答案

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

  • 将图像转换为灰度
  • 执行Canny边缘检测
  • 扩展图像以连接损坏的组件
  • 使用宽高比
  • 查找轮廓并过滤
  • 裁剪所需的ROI

  • 从您的“蒙版图像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)
    

    关于python - 如何使用opencv轮廓裁剪对象/从图像中获取位置信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56376996/

    相关文章:

    c++ - cvBlob/Opencv : Why is my output variable empty?

    python - Django 中 AbstractUser 和 AbstractBaseUser 的区别?

    python - Beautifulsoup 正在从表中提取四舍五入的小数(可见的)而不是实际的单元格值

    python - 如何检测一个图像是否在另一个图像中?

    opencv - 视频中的场景变化检测(移动摄像机)

    c++ - 在不使用外部库的情况下在 C++ 中读取灰度 .jpeg 图像?

    matlab - Matlab中的颜色直方图算法

    打印执行下一条指令后的 Python 尾随逗号

    python - 如何根据特定条件替换列中的某些值?

    python - 当我尝试 reshape 我的训练数据时,出现此错误.... ValueError : cannot reshape array of size 568 into shape (28, 28,3)