首页 > 解决方案 > 消除或忽略大轮廓/矩形opencv中的所有小或重叠轮廓或矩形

问题描述

我想忽略所有重叠或在大矩形内的矩形或轮廓,我找到了很多解决方案,但没有一个适合我的情况。

import numpy as np
import cv2
import imutils

cap = cv2.VideoCapture('rtsp://admin:admin@192.168.1.72')

#read the first frame from camera for our background
_,first_frame = cap.read()

#We’ll also convert the image to grayscale since color has no bearing on our motion detection
first_gray = cv2.cvtColor(first_frame, cv2.COLOR_BGR2GRAY)

#Due to tiny variations in the digital camera sensors, no two frames will be 100% same, to account for this and apply Gaussian smoothing
first_gray = cv2.GaussianBlur(first_gray, (21, 21), 0)

open('/tmp/test.txt', 'w').close()

while(1):
    _, frame = cap.read()

    #We’ll also convert the image to grayscale since color has no bearing on our motion detection
    gray_frame = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)

    #Due to tiny variations in the digital camera sensors, no two frames will be 100% same, to account for this and apply Gaussian smoothing
    blurFrame = cv2.GaussianBlur(gray_frame, (21, 21), 0)

    #Computing the difference between two frames is a simple subtraction
    diff = cv2.absdiff(first_gray, blurFrame)

    _,thresh = cv2.threshold(diff, 25, 255, cv2.THRESH_BINARY)

    # dilate the thresholded image to fill in holes
    thresh = cv2.dilate(thresh, None, iterations=2)

    #find contours on thresholded image
    contours,_ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    pixelList = \[\]

    for contour in contours:

        if( cv2.contourArea(contour) > 100):

            (x, y, w, h) = cv2.boundingRect(contour)

            pixelList.append(list((x, y, w, h)))

            cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)

    if len(pixelList) !=0:        
        with open("/tmp/test.txt", "a") as myfile:
            myfile.write(str(pixelList)+'\n')

    orgFrame = cv2.resize(frame, (600, 600))

    diffFrame = cv2.resize(diff, (300, 300))


    cv2.imshow('diffFrameBlur',diff)
    cv2.imshow('frameBlur',frame)

    k = cv2.waitKey(1) & 0xff
    if k == 27:
        break
cap.release()
cv2.destroyAllWindows()

请看这里附上的图片,你会发现在一个大轮廓内检测到很多轮廓,我真的想消除这些在一个大轮廓内的所有轮廓(小),甚至你可以说是矩形,我在计算后绘制区域。在此处输入图像描述

标签: pythonalgorithmnumpyopencvcontour

解决方案


比较每个矩形的左上角和右下角,包含在另一个矩形中,然后消除它们。

使用下面的这个函数来检查一个点是否在矩形内。

def rectContains(rect,pt):
    in = rect[0] < pt[0] < rect[0]+rect[2] and rect[1] < pt[1] < rect[1]+rect[3]
    return in

仅对每个矩形的左上角和右下角调用此函数,如果它包含在另一个矩形内,则消除它们。

如果您打算使其更快,请减少比较次数。

对于检测到的所有轮廓,按大小顺序对它们进行排序,

cntsSorted = sorted(cnts, key=lambda x: cv2.contourArea(x))

从排序后的轮廓开始,从最小的开始,与最大的矩形进行比较。基本上是第一个元素和最后一个元素,依此类推


推荐阅读