OpenCV 추적

Salman Mehmood 2024년2월15일
OpenCV 추적

이 데모는 Python 및 OpenCV를 사용하여 매우 기본적이고 간단한 동작 감지 및 추적 시스템을 만드는 방법을 배우는 것을 목표로 합니다. 우리는 이 기사의 끝에 직사각형 경계 상자를 사용하여 모든 사람을 추적합니다.

Python 및 OpenCV를 사용하여 동작 감지 및 추적 시스템 만들기

먼저 CAP 인스턴스에서 두 프레임을 읽어야 합니다.

ret, F1 = CAP.read()

유사하게, 우리는 두 번째 프레임을 읽을 것입니다.

ret, F2 = CAP.read()

이제 DF라는 변수를 선언하고 absdiff() 함수를 사용합니다. absdiff()는 첫 번째 F1과 두 번째 F2인 프레임 간의 절대 차이를 찾는 데 도움이 됩니다.

while CAP.isOpened():
    if ret == False:
        print(ret)
        break
    DF = cv2.absdiff(F1, F2)

cvtColor() 메서드를 사용하여 이 차이를 그레이스케일 모드로 변환합니다. 첫 번째 매개변수는 DF입니다.

두 번째 인수는 COLOR_BGR2GRAY이며 프레임 색상 BGR을 회색조 모드로 변환하는 데 도움이 됩니다. 그레이스케일 모드를 찾는 이유는 무엇입니까?

이후 단계에서 윤곽선을 찾을 것이기 때문에 컬러 모드보다 회색조 모드에서 윤곽선을 찾는 것이 더 쉽습니다.

Gray_Scale = cv2.cvtColor(DF, cv2.COLOR_BGR2GRAY)

회색조 모드가 있으면 GaussianBlur() 메서드를 사용하여 회색조 프레임을 흐리게 처리해야 합니다. 몇 가지 매개변수가 필요합니다. 첫 번째는 Gray_Scale, 두 번째 매개변수는 커널 크기 5x5, 세 번째 매개변수는 Sigma X 값입니다.

BL = cv2.GaussianBlur(Gray_Scale, (5, 5), 0)

threshold() 메서드를 사용하여 임계값을 결정해야 합니다. 두 개의 객체를 반환합니다. 첫 번째 변수가 필요하지 않고 두 번째 변수가 thresh가 되기 때문에 _를 정의합니다.

첫 번째 매개변수에서 흐릿한 이미지를 소스로 전달하고 두 번째 매개변수는 임계값 20이 됩니다. 최대 임계값은 255입니다. 유형은 THRESH_BINARY입니다.

_, thresh = cv2.threshold(BL, 20, 255, cv2.THRESH_BINARY)

모든 구멍을 채우기 위해 임계값 이미지를 확장해야 합니다. 이것은 우리가 더 나은 윤곽을 찾는 데 도움이 될 것입니다. dilate() 메소드는 몇 가지 매개변수를 사용합니다. 첫 번째 매개변수는 정의된 임계값이고 두 번째 매개변수는 커널 크기이지만 None으로 전달합니다.

세 번째 인수는 3으로 반복 횟수입니다. 작동하지 않으면 반복 횟수를 늘리거나 줄일 수 있습니다.

DL = cv2.dilate(thresh, None, iterations=3)

다음 단계에서는 등고선을 찾고 findContours() 메서드는 두 가지 결과를 제공합니다. 하나는 등고선이고 다른 하나는 계층구조이지만 두 번째 결과는 사용하지 않을 것입니다. 확장된 이미지에서 윤곽선을 찾을 것입니다.

따라서 첫 번째 매개변수에 확장된 이미지를 전달하고 다음은 가장 일반적으로 사용되는 RETR_TREE 모드입니다. 다음 매개변수는 CHAIN_APPROX_SIMPLE 메소드입니다.

CTS, _ = cv2.findContours(DL, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

다음 단계에서는 직사각형을 그리려고 하므로 for 루프를 사용하여 모든 윤곽선을 반복합니다. CTS는 목록이고 이 목록을 반복하므로 첫 번째 단계는 boundingRect() 메서드를 사용하여 등고선의 모든 좌표를 저장하는 것입니다.

다음 단계에서는 등고선 영역을 찾아 이 영역이 특정 값보다 작으면 직사각형을 그리지 않습니다. for 루프 내에서 윤곽 영역이 700보다 작으면 반복을 계속하도록 정의합니다. 그렇지 않으면 직사각형을 그립니다.

사각형을 그리려면 cv2.rectangle() 메서드를 사용해야 하며 여기에서 첫 번째 인수는 F1이 될 소스가 됩니다. 두 번째 매개변수는 포인트 1 (x,y)입니다. 세 번째 매개변수는 포인트 2이고, 다음 매개변수는 색상 값인 튜플, 다음 매개변수는 두께입니다.

for CT in CTS:
    (x, y, w, h) = cv2.boundingRect(CT)

    if cv2.contourArea(CT) < 900:
        continue
    cv2.rectangle(F1, (x, y), (x + w, y + h), (0, 255, 0), 2)

약간의 움직임이 관찰되면 이미지에 텍스트를 배치합니다. cv2.putText() 메소드를 사용할 것입니다. 이 메서드는 F1을 사용하고 두 번째 매개변수는 텍스트가 되며 다음 인수 매개변수는 이 텍스트를 넣을 원점이 됩니다.

다음 매개변수는 FONT_HERSHEY_SIMPLEX 글꼴입니다. 다음 매개변수는 글꼴 크기입니다. 다음은 글꼴의 색상입니다. 그런 다음 마지막 매개변수는 텍스트의 두께가 됩니다.

cv2.putText(
    F1,
    "Status: {}".format("Movement"),
    (10, 20),
    cv2.FONT_HERSHEY_SIMPLEX,
    1,
    (0, 0, 255),
    3,
)

이제 루프 외부에 일부 코드를 작성합니다. 먼저 출력 이미지를 작성하여 출력을 저장하고 윤곽을 적용한 후 결과인 F1을 표시합니다.

다음 줄에서 변수 F2에서 새 프레임을 읽고 새 프레임을 읽기 전에 F2 값을 F1에 할당합니다. 이런 식으로 두 프레임의 차이점을 읽고 찾습니다.

OP.write(IMG)
cv2.imshow("feed", F1)
F1 = F2
ret, F2 = CAP.read()

완전한 소스 코드:

import cv2
import numpy as np

CAP = cv2.VideoCapture("input.avi")
FR_W = int(CAP.get(cv2.CAP_PROP_FRAME_WIDTH))

FR_H = int(CAP.get(cv2.CAP_PROP_FRAME_HEIGHT))

FRC = cv2.VideoWriter_fourcc("X", "V", "I", "D")

OP = cv2.VideoWriter("output.avi", FRC, 5.0, (1280, 720))

ret, F1 = CAP.read()
ret, F2 = CAP.read()
print(F1.shape)
while CAP.isOpened():
    if ret == False:
        print(ret)
        break
    DF = cv2.absdiff(F1, F2)
    Gray_Scale = cv2.cvtColor(DF, cv2.COLOR_BGR2GRAY)
    BL = cv2.GaussianBlur(Gray_Scale, (5, 5), 0)
    _, thresh = cv2.threshold(BL, 20, 255, cv2.THRESH_BINARY)
    DL = cv2.dilate(thresh, None, iterations=3)
    CTS, _ = cv2.findContours(DL, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    for CT in CTS:
        (x, y, w, h) = cv2.boundingRect(CT)

        if cv2.contourArea(CT) < 900:
            continue
        cv2.rectangle(F1, (x, y), (x + w, y + h), (0, 255, 0), 2)
        cv2.putText(
            F1,
            "Status: {}".format("Movement"),
            (10, 20),
            cv2.FONT_HERSHEY_SIMPLEX,
            1,
            (0, 0, 255),
            3,
        )

    IMG = cv2.resize(F1, (1280, 720))
    OP.write(IMG)
    cv2.imshow("feed", F1)
    F1 = F2
    ret, F2 = CAP.read()

    if cv2.waitKey(40) == 27:
        break

cv2.destroyAllWindows()
CAP.release()
OP.release()

사람들이 모두 움직이고 있기 때문에 상태가 움직임을 보이는 것을 볼 수 있습니다. 움직이는 사람 주위에 그려진 직사각형도 볼 수 있습니다.

OpenCV 추적

Salman Mehmood avatar Salman Mehmood avatar

Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.

LinkedIn

관련 문장 - Python OpenCV