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

Python 如何使用opencv轮廓裁剪对象/从图像中获取位置信息,python,opencv,image-processing,opencv-contour,Python,Opencv,Image Processing,Opencv Contour,我使用Unrelcv从UE4生成了图像,每个图像都有RGB和掩码格式。每个图像只包含一个对象,并且还显示背景。大多数情况下,对象形状为矩形/正方形。我想裁剪,以及有对象的位置只。我知道如果我得到的位置使用轮廓然后裁剪是很容易的。我也为一些物体做过。但问题是对于每一个它不起作用的物体。有时是说没有检测到轮廓,有时是检测到错误的轮廓。我的问题是,对于我的每一张照片,有没有什么可以解决的基本事实 到目前为止,我已经完成了转换BGR2GRAY,然后做了阈值(自适应阈值也做了),然后尝试找到轮廓。我也尝试

我使用Unrelcv从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()

此处[为方便起见,提供了一些示例图像

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

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

  • 将图像转换为灰度
  • 执行Canny边缘检测
  • 放大图像以连接损坏的组件
  • 查找轮廓并使用纵横比进行过滤
  • 裁剪所需的ROI
从您的“蒙版图像2”开始,我们执行canny边缘检测

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

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

一旦我们获得了所需的ROI,我们就绘制边界框,并使用一个简单的图形裁剪图像

导入cv2
原始图像=cv2.imread('1.png')
original\u copy=原始图像。copy()
image=cv2.imread('2.png')
灰色=cv2.CVT颜色(图像,cv2.COLOR\u BGR2GRAY)
canny=cv2.canny(灰色,130255,1)
kernel=cv2.getStructuringElement(cv2.morp_RECT,(3,3))
explate=cv2.explate(canny,内核,迭代次数=1)
cnts=cv2.查找对象(扩张、cv2.RETR\u树、cv2.链近似\u简单)
如果len(cnts)==2个其他cnts[1],则cnts=cnts[0]
对于碳纳米管中的碳:
peri=cv2.弧长(c,真)
近似值=cv2.近似聚合度(c,0.01*peri,真)
x、 y,w,h=cv2.边界矩形(近似值)
纵横比=宽/浮点数(h)

如果(纵横比>=0.8和纵横比谢谢你的回复。我已经使用遮罩图像转换为灰色。问题还没有解决。它正在创建。我每时每刻都有4种不同的类型。有没有办法,我可以使用没有对象的图像从RGB图像提取对象?我不明白你的意思。因为你在蒙版上,你可以找到它的轮廓,然后使用边界框坐标来抓取ROIyes@Nathance我也认为,但问题是图像的预处理并不能为所有图像提供良好的结果。这就是为什么有时裁剪的部分是完全错误的。
ROI = original_copy[y:y+h, x:x+w]
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)