简体   繁体   中英

Eliminate or Ignore all small or overlapping contours or rectangles inside a big contours/rectangle opencv

I want to ignore all rectangles or contours that are overlapping or inside a big rectangle, I found many solutions but no one work in my case.

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()

Please look at the image attached in here you will find that lots of contours detected inside a big contour, I really want to eliminate these all contours(small) that is inside a big contour or even you can say rectangle that, I draw after calculating area. 在此处输入图片说明

Compare the top left point and bottom right point of each rectangle, contained in another rectangle, then eliminate them.

Use this function below to check if a point is inside the rectangle.

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

Call this function only for top left and bottom right for each rectangle, and if its contained inside another rectangle, eliminate them.

If you are intending to make it faster, the reduce the number of comparisons.

For all the contours detected, sort them in the order of size,

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

From the sorted contours and start from smallest, and compare it with rectangle which are largest. basically first element with the last element and so on

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM