Как мне найти ограничивающую рамку этого контура?

#python #opencv

Вопрос:

Я относительно новичок в написании сценариев. (Я знаю совсем немного, но я также не знаю совсем немного.)

Я пытаюсь создать простой скрипт, использующий OpenCV-Python, чтобы вычесть два кадра из веб-камеры и нарисовать ограничивающую рамку вокруг измененных пикселей. Проблема в том, что когда я пытаюсь определить функцию boundingRect ( x,y,w,h = cv2.boundingRect(contours) ), она выдает ошибку:

   Message=OpenCV(4.5.3) :-1: error: (-5:Bad argument) in function 'boundingRect'
> Overload resolution failed:
>  - array is not a numpy array, neither a scalar
>  - Expected Ptr<cv::UMat> for argument 'array'
 

Я искал вокруг довольно долго, но, похоже, очень небольшое количество людей, у которых была моя проблема, и в значительной степени ни у кого из них не было решений, которые бы работали.

Вот мой код:

 import cv2
from time import sleep as wait
import numpy as np
 
lastFrame = "foobaz"

i = 0

#My webcam is on index 1, this isn't (at least shouldn't) be the issue. Make sure to set it back to 0 if you are testing
vid = cv2.VideoCapture(1)
#A placeholder black image for the 'subract' imshow window
black = np.zeros((512,512,3), np.uint8)

while(True):
    wait(0.5)

    ret, frame = vid.read()

    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    blurframe = cv2.GaussianBlur(frame,(25,25),0)

    #Makes sure the lastFrame has been assigned, if not set it as placeholder black image.
    if lastFrame != "foobaz":
        #Subtracts current frame and the last frame to find difference.
        subFrame = cv2.subtract(blurframe,lastFrame)
    else:
        subFrame = black

    #Assigns the next lastFrame
    lastFrame = blurframe

    #Gets the threshold of the subtracted image
    ret,thresh1 = cv2.threshold(subFrame,40,255,cv2.THRESH_BINARY)

    #Sets the thresholded image to grayscale if the loop was ran for the first time.
    if i==0:
        thresh1 = cv2.cvtColor(thresh1, cv2.COLOR_BGR2GRAY)
    i =1

    #This is where issues arize. I'm trying to apply a bounding box using a contour but it always errors at line 44.
    contours = cv2.findContours(thresh1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
    print(len(contours))
    x,y,w,h = cv2.boundingRect(contours)
    cv2.rectangle(frame,(x,y),(x w,y h),(0,255,0),2)
    
    cv2.imshow('frame',frame)
    cv2.imshow('subtract',thresh1)

    if cv2.waitKey(1) amp; 0xFF == ord('q'):
        break
 

Я видел, что у некоторых других сообщений был тип контура (), поэтому вот он:
type(contours) = <class 'list'>

закрытый: Я выяснил эту проблему. Вы должны повторить contours , чтобы это сработало.

Комментарии:

1. пробовать x,y,w,h = cv2.boundingRect([contours]) . Обратите внимание на квадратные скобки

2. Я попробовал, и, похоже, у меня та же ошибка. Дело в том, что я обнаружил cv2.findContours , что неправильно использовал функцию. Мне просто нужно было повторить contours , вместо того чтобы просто пытаться сделать ограничивающую рамку вокруг него. Я не знаю, как я не узнал об этом раньше.

3. вместо [contours] того , чтобы усугублять проблему, я бы рекомендовал объединить (сгладить) их. np.concatenate(contours) . на самом деле просто нужно объединить все списки точек в один список точек. boundingRect считает аргумент неупорядоченным набором точек, за исключением того, что он должен быть массивом numpy (возможно, он также принимает списки, а может быть, и нет).