Teach you step by step how to implement it - traffic flow statistics and speed detection code based on OpenCV

         This chapter will implement a simple GUI application for vehicle speed estimation and traffic flow statistics. It uses Haar cascade detectors and related trackers to detect and track vehicles in videos, and estimates the speed of vehicles through image processing and mathematical calculations. speed.

        1. First, the code requires cv2: for image processing and computer vision tasks; dlib: for object tracking and detection; time: for calculating frame rate and time intervals; threading: for handling multi-threaded operations; math: for In mathematical calculations, etc.

        2. Then, the global variables video_path and highest_speed are defined, which are used to store the selected video file path and maximum speed.

        3. Next, import the vehicle detector model through carCascade = cv2.CascadeClassifier('myhaar.xml'). Then the global variable video and some constants are defined, such as the width and height of the video.

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

        ​ ​ 3. Implement the estimateSpeed(location1, location2, fps) function to estimate the vehicle speed, and calculate the vehicle speed based on the pixel distance between two location points, the pixel per meter ratio and the frame rate.

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

        In the code: location1 and location2 are parameters representing the vehicle location. They are tuples or lists containing two elements, representing the coordinates (x, y) of the vehicle in the image. fps is the frame rate (Frames Per Second), indicating the frame rate of video playback. d_pixels is a variable that calculates the pixel distance between two locations. The Euclidean distance is calculated by using the difference in the x and y coordinates of the two locations. ppm is the value in meters per pixel (Pixels Per Meter). It represents the proportional relationship between the pixel distance in the image and the actual distance. Here, assume each pixel represents 8.8 centimeters. d_meters is a value that converts pixel distances into meters. Obtained by dividing the pixel distance by ppm. If framerate fps is 0.0 (not provided or invalid value), set it to the default value of 18. speed is the estimated speed in kilometers per hour. Calculated by multiplying the distance (in meters) by the frame rate (in seconds) and then multiplying by 3.6 (to convert hours to seconds). Returns the estimated speed.
        In summary, this function estimates the vehicle's speed (in kilometers per hour) based on the pixel distance between two locations, the frame rate, and the pixel-to-meter ratio. 

        4. Implementing the track_multiple_objects() function is the core part of achieving multiple target tracking. It uses Haar cascade detectors to detect vehicles in images and dlib’s correlation tracker to track each vehicle. The function uses an infinite loop to read frames from the video and then perform vehicle detection and tracking. In each frame, the function updates the position and mass of the tracked vehicle and calculates the vehicle's speed. Labels for maximum speed and real-time traffic flow are also updated, and images showing tracking results are also updated.

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

        ​ ​ ​ First of all, some variables and data structures are defined in this code for tracking vehicles. rectangleColor is the color of the vehicle bounding box, frameCounter is used to calculate the number of frames, currentCarID represents the ID of the current vehicle, and fps represents the frame rate. carTracker is a dictionary used to store tracker objects for each car. carLocation1 and carLocation2 are dictionaries respectively used to store the current and previous frame location information of each car. speed is a list that stores the speed of each vehicle. update_highest_speed() is an internal function used to update the display of the highest speed. update_video_frame() is an internal function used to update the display of video frames. total_cars and prev_total_cars are variables used to calculate traffic flow. Entering the main loop, first read a frame of the video. If the image cannot be read, exit the loop. Preprocess the read image, including resizing the image and creating a copy. Increase the frame counter value. Create an empty list carIDtoDelete to store the IDs of vehicles that need to be deleted. Traverse the tracked vehicles and update their location information and quality. If a car's tracking quality is below the threshold (7), its ID is added to the carIDtoDelete list. Traverse the carIDtoDelete list and delete the corresponding vehicles from carTracker, carLocation1 and carLocation2. Every 10 frames, vehicles in the image are detected. Perform object detection on grayscale images using a cascade classifier (carCascade) and return the bounding boxes of the detected vehicles. Traverse the detected vehicle bounding boxes and match them with tracked vehicles. If a matching vehicle is found, update the vehicle's tracker object, location information, and ID. If no matching vehicle is found, create a new tracker object, add it to the carTracker, and update the location information and ID. Iterate through each car in the carTracker, get its location information, and draw the vehicle bounding box on the resulting image. Based on the location information and frame rate of each vehicle, the vehicle's speed is estimated and stored in the speed list. If the speed is not 0 and less than 150, update the maximum speed. Display the speed of each vehicle on the resulting image

        5. Implement the open_file() function to open the file dialog box and select the video file. After selecting a video file, a new thread will be started to process the video.

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. Implement the process_video() function to be executed in a new thread. It first opens the selected video file through cv2.VideoCapture, and then calls the track_multiple_objects() function to process the video.

        ​ ​ 7. Implement the update_highest_speed(speed) function to update the global variable of the highest speed and update the label showing the highest speed.

        ​ ​ 8. Implement the update_video_frame(image) function to update the label that displays the video frame. It converts the image to a format available to Tkinter and makes appropriate adjustments.

        9. Finally, the code creates a Tkinter window and adds buttons, traffic volume labels, maximum speed labels, and video display labels to the window. Use window.mainloop() to start the event loop of the GUI window to keep the application running. The implemented interface is as follows:

Click the Select Video button and we can select videos in any format for detection:

 The output interface after selecting the video is as follows:

Traffic flow detection and speed estimation

 Entire code download link:

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

Running environment dependency packages:

opencv-python==4.1.0.25
numpy==1.17.2
dlib==19.8.1
future==0.17.1
Pillow==8.4.0

Guess you like

Origin blog.csdn.net/weixin_40651515/article/details/131113901