OpenCV 기반의 트래픽 흐름 통계 및 속도 감지 코드 구현 방법을 단계별로 알려드립니다.

         이 장에서는 차량 속도 추정 및 교통 흐름 통계를 위한 간단한 GUI 애플리케이션을 구현합니다. Haar 캐스케이드 감지기와 관련 추적기를 사용하여 비디오에서 차량을 감지 및 추적하고 이미지 처리 및 수학적 계산을 통해 차량 속도를 추정합니다.

        1. 먼저 코드에는 cv2가 필요합니다: 이미지 처리 및 컴퓨터 비전 작업용, dlib: 객체 추적 및 감지용, time: 프레임 속도 및 시간 간격 계산용, 스레딩: 멀티스레드 작업 처리용, math: 수학적 계산용 , 등.

        2. 그런 다음 선택한 비디오 파일 경로와 최대 속도를 저장하는 데 사용되는 전역 변수 video_path 및 maximum_speed가 정의됩니다.

        3. 다음으로 carCascade = cv2.CascadeClassifier('myhaar.xml')를 통해 차량 감지기 모델을 가져옵니다. 그런 다음 전역 변수 video와 비디오의 너비 및 높이와 같은 일부 상수가 정의됩니다.

carCascade = cv2.CascadeClassifier('myhaar.xml')
video = None
WIDTH = 1280
HEIGHT = 720

        ​ 3. 차량 속도를 추정하는 estimateSpeed(location1, location2, fps) 함수를 구현하고, 두 위치 지점 사이의 픽셀 거리, 미터당 픽셀 비율 및 프레임 속도를 기반으로 차량 속도를 계산합니다.

def estimateSpeed(location1, location2, fps):
    d_pixels = math.sqrt(math.pow(location2[0] - location1[0], 2) + math.pow(location2[1] - location1[1], 2))
    ppm = 8.8
    d_meters = d_pixels / ppm
    if fps == 0.0:
        fps = 18
    speed = d_meters * fps * 3.6
    return speed

        코드에서 location1과 location2는 차량 위치를 나타내는 매개변수입니다. 이는 이미지에서 차량의 좌표(x, y)를 나타내는 두 요소를 포함하는 튜플 또는 목록입니다. fps는 프레임 속도(초당 프레임 수)로, 비디오 재생의 프레임 속도를 나타냅니다. d_pixels는 두 위치 사이의 픽셀 거리를 계산하는 변수입니다. 유클리드 거리는 두 위치의 x 및 y 좌표의 차이를 사용하여 계산됩니다. ppm은 픽셀당 미터(미터당 픽셀) 단위의 값입니다. 이는 이미지의 픽셀 거리와 실제 거리 사이의 비례 관계를 나타냅니다. 여기서는 각 픽셀이 8.8cm를 나타낸다고 가정합니다. d_meters는 픽셀 거리를 미터로 변환하는 값입니다. 픽셀 거리를ppm으로 나누어 얻습니다. 프레임 속도 fps가 0.0(제공되지 않거나 잘못된 값)인 경우 기본값인 18로 설정합니다. 속도는 시간당 킬로미터 단위의 예상 속도입니다. 거리(미터 단위)에 프레임 속도(초 단위)를 곱한 다음 3.6을 곱하여 계산합니다(시간을 초로 변환). 예상 속도를 반환합니다.
        요약하면 이 함수는 두 위치 사이의 픽셀 거리, 프레임 속도 및 픽셀 대 미터 비율을 기반으로 차량의 속도(시간당 킬로미터)를 추정합니다. 

        4. track_multiple_objects() 함수를 구현하는 것은 다중 대상 추적을 달성하는 핵심 부분입니다. Haar 캐스케이드 감지기를 사용하여 이미지에서 차량을 감지하고 dlib의 상관 추적기를 사용하여 각 차량을 추적합니다. 이 기능은 무한 루프를 사용하여 비디오에서 프레임을 읽은 다음 차량 감지 및 추적을 수행합니다. 각 프레임에서 함수는 추적된 차량의 위치와 질량을 업데이트하고 차량의 속도를 계산합니다. 최고 속도와 실시간 교통 흐름에 대한 라벨도 업데이트되며, 추적 결과를 보여주는 이미지도 업데이트됩니다.

def track_multiple_objects():
    rectangleColor = (0, 255, 0)
    frameCounter = 0
    currentCarID = 0
    fps = 0

    carTracker = {}
    carLocation1 = {}
    carLocation2 = {}
    speed = [None] * 1000

    def update_highest_speed(speed):
        global highest_speed
        highest_speed = max(highest_speed, speed)
        speed_label.config(text="最高时速度:{} km/hr".format(highest_speed))

    def update_video_frame(image):
        image = Image.fromarray(image)
        image = image.resize((640, 480))
        photo = ImageTk.PhotoImage(image)
        video_label.config(image=photo)
        video_label.image = photo

        # 其他代码...

    total_cars = 0  # 车辆总数
    prev_total_cars = 0  # 上一帧的车辆总数

    while True:
        start_time = time.time()
        rc, image = video.read()
        if not rc:
            break

        image = cv2.resize(image, (WIDTH, HEIGHT))
        resultImage = image.copy()

        frameCounter = frameCounter + 1

        carIDtoDelete = []

        # 更新已跟踪车辆的位置和质量
        for carID in carTracker.keys():
            trackingQuality = carTracker[carID].update(image)

            if trackingQuality < 7:
                carIDtoDelete.append(carID)

        for carID in carIDtoDelete:
            carTracker.pop(carID, None)
            carLocation1.pop(carID, None)
            carLocation2.pop(carID, None)

        if not (frameCounter % 10):
            gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
            cars = carCascade.detectMultiScale(gray, 1.1, 13, 18, (24, 24))

            for (_x, _y, _w, _h) in cars:
                x = int(_x)
                y = int(_y)
                w = int(_w)
                h = int(_h)

                x_bar = x + 0.5 * w
                y_bar = y + 0.5 * h

                matchCarID = None

                for carID in carTracker.keys():
                    trackedPosition = carTracker[carID].get_position()

                    t_x = int(trackedPosition.left())
                    t_y = int(trackedPosition.top())
                    t_w = int(trackedPosition.width())
                    t_h = int(trackedPosition.height())

                    t_x_bar = t_x + 0.5 * t_w
                    t_y_bar = t_y + 0.5 * t_h

                    if (
                            (t_x <= x_bar <= (t_x + t_w))
                            and (t_y <= y_bar <= (t_y + t_h))
                            and (x <= t_x_bar <= (x + w))
                            and (y <= t_y_bar <= (y + h))
                    ):
                        matchCarID = carID

                if matchCarID is None:
                    tracker = dlib.correlation_tracker()
                    tracker.start_track(image, dlib.rectangle(x, y, x + w, y + h))

                    carTracker[currentCarID] = tracker
                    carLocation1[currentCarID] = [x, y, w, h]

                    currentCarID = currentCarID + 1

        for carID in carTracker.keys():
            trackedPosition = carTracker[carID].get_position()

            t_x = int(trackedPosition.left())
            t_y = int(trackedPosition.top())
            t_w = int(trackedPosition.width())
            t_h = int(trackedPosition.height())

            cv2.rectangle(resultImage, (t_x, t_y), (t_x + t_w, t_y + t_h), rectangleColor, 4)

            carLocation2[carID] = [t_x, t_y, t_w, t_h]

        end_time = time.time()

        if not (end_time == start_time):
            fps = 1.0 / (end_time - start_time)

        for i in carLocation1.keys():
            if frameCounter % 1 == 0:
                [x1, y1, w1, h1] = carLocation1[i]
                [x2, y2, w2, h2] = carLocation2[i]

                carLocation1[i] = [x2, y2, w2, h2]

                if [x1, y1, w1, h1] != [x2, y2, w2, h2]:
                    if speed[i] is None or speed[i] == 0:
                        speed[i] = estimateSpeed([x1, y1, w1, h1], [x2, y2, w2, h2], fps)

                    if speed[i] != 0 and speed[i] < 150:
                        update_highest_speed(speed[i])

                    cv2.putText(resultImage,str(int(speed[i])) + " km/hr", (int(x1 + w1 / 2), int(y1 - 10)),cv2.FONT_HERSHEY_SIMPLEX, 0.75,(0, 255, 0),2,)

        # 更新车流量
        prev_total_cars = total_cars
        total_cars = len(carTracker)

        # 更新实时车流量标签
        traffic_label.config(text="实时车流量:{}".format(total_cars))

        update_video_frame(resultImage)

    video.release()

        ​ ​ 우선 본 코드에는 차량 추적을 위한 일부 변수와 데이터 구조가 정의되어 있습니다. RectangleColor는 차량 경계 상자의 색상이고, FrameCounter는 프레임 수를 계산하는 데 사용되며, currentCarID는 현재 차량의 ID를 나타내고, fps는 프레임 속도를 나타냅니다. carTracker는 각 자동차의 추적기 개체를 저장하는 데 사용되는 사전입니다. carLocation1과 carLocation2는 각각 자동차의 현재 및 이전 프레임 위치 정보를 저장하는 데 사용되는 사전입니다. speed 는 각 차량의 속도를 저장하는 목록입니다. update_highest_speed()는 최고 속도 표시를 업데이트하는 데 사용되는 내부 함수입니다. update_video_frame()은 비디오 프레임 표시를 업데이트하는 데 사용되는 내부 함수입니다. total_cars와 prev_total_cars는 교통 흐름을 계산하는 데 사용되는 변수입니다. 메인 루프에 들어가서 먼저 비디오의 프레임을 읽습니다. 이미지를 읽을 수 없으면 루프를 종료합니다. 이미지 크기 조정 및 복사본 생성을 포함하여 읽기 이미지를 전처리합니다. 프레임 카운터 값을 늘립니다. 삭제해야 하는 차량의 ID를 저장하려면 빈 목록 carIDtoDelete를 만듭니다. 추적된 차량을 탐색하고 위치 정보와 품질을 업데이트하세요. 자동차의 추적 품질이 임계값(7)보다 낮으면 해당 ID가 carIDtoDelete 목록에 추가됩니다. carIDtoDelete 목록을 탐색하고 carTracker, carLocation1 및 carLocation2에서 해당 차량을 삭제합니다. 10프레임마다 이미지의 차량이 감지됩니다. 계단식 분류기(carCascade)를 사용하여 회색조 이미지에서 객체 감지를 수행하고 감지된 차량의 경계 상자를 반환합니다. 감지된 차량 경계 상자를 통과하여 추적된 차량과 일치시킵니다. 일치하는 차량이 발견되면 차량의 추적기 개체, 위치 정보 및 ID를 업데이트합니다. 일치하는 차량이 없으면 새 추적기 개체를 만들어 carTracker에 추가하고 위치 정보와 ID를 업데이트합니다. carTracker에서 각 자동차를 반복하고 위치 정보를 얻은 다음 결과 이미지에 차량 경계 상자를 그립니다. 각 차량의 위치 정보와 프레임 레이트를 기반으로 차량의 속도를 추정하여 속도 목록에 저장합니다. 속도가 0이 아니고 150보다 작으면 최대 속도를 업데이트합니다. 결과 이미지에 각 차량의 속도를 표시합니다.

        5. open_file() 함수를 구현하여 파일 대화 상자를 열고 비디오 파일을 선택합니다. 비디오 파일을 선택하면 비디오를 처리하기 위한 새 스레드가 시작됩니다.

def open_file():
    global video_path, video
    file_types = [("视频文件", "*.mp4;*.avi;*.mkv")]  # 允许上传的视频文件类型
    video_path = filedialog.askopenfilename(title="选择视频文件", filetypes=file_types)
    if video_path:
        video = cv2.VideoCapture(video_path)
        t = threading.Thread(target=process_video)
        t.start()

       ​ 6. 새 스레드에서 실행할 process_video() 함수를 구현합니다.먼저 cv2.VideoCapture를 통해 선택한 비디오 파일을 연 다음 track_multiple_objects() 함수를 호출하여 비디오를 처리합니다.

        ​ 7. 최고 속도의 전역 변수를 업데이트하고 최고 속도를 표시하는 라벨을 업데이트하려면 update_highest_speed(speed) 함수를 구현하세요.

        ​ 8. 비디오 프레임을 표시하는 레이블을 업데이트하기 위해 update_video_frame(image) 함수를 구현합니다. 이미지를 Tkinter에서 사용할 수 있는 형식으로 변환하고 적절하게 조정합니다.

        9. 마지막으로 코드는 Tkinter 창을 생성하고 버튼, 교통량 레이블, 최대 속도 레이블 및 비디오 표시 레이블을 창에 추가합니다. 애플리케이션 실행을 유지하려면 window.mainloop()을 사용하여 GUI 창의 이벤트 루프를 시작하세요. 구현된 인터페이스는 다음과 같습니다.

비디오 선택 버튼을 클릭하면 탐지를 위해 모든 형식의 비디오를 선택할 수 있습니다.

 비디오를 선택한 후의 출력 인터페이스는 다음과 같습니다:

교통 흐름 감지 및 속도 추정

 전체 코드 다운로드 링크:

https://download.csdn.net/download/weixin_40651515/87882938

실행 환경 종속성 패키지:

opencv-python==4.1.0.25
numpy==1.17.2
dlib==19.8.1
미래==0.17.1
베개==8.4.0

추천

출처blog.csdn.net/weixin_40651515/article/details/131113901