如何使用 python 改进斑点检测?

问题描述 投票:0回答:1

所以我有这个扑翼机器人,我在机翼上画了一些圆圈,我认为这些圆圈很容易跟踪。当机翼在每一帧中移动时,与其他帧相比,某些圆圈可能会显得更模糊或椭圆。 我的目标是生成一个字典,其中的键表示圆的唯一 ID,值是每个帧的 (x,y) 坐标列表。因此对于

k
圆圈和
n
框架:

result = {
 1: [(x11,y11),(x12,y12),...,(x1n,y1n)],
 2: [(x21,y21),(x22,y22),...,(x2n,y2n)],
 ...,
 k: [(xk1,yk1),(xk2,yk2),...,(xkn,ykn)]
}

目前,我使用

cv2.SimpleBlobDetector_create
,它确实找到了每帧中的 some 圆,并且我通过测量前一帧中每个圆的欧几里得距离来匹配两个连续圆。 当然,由于并非总能找到所有圆圈,因此我在想要填充的数据中找到了这些漏洞。

我该如何填补这些空白?

作为参考,我添加了两个可能的框架

虽然我认为代码没有增加太多价值,但我也将其添加到此处:

def blob_trajectory(camera_dirname: str,
                    crop_params_filename='crop_params.pkl',
                    first_image_name='Img000001.jpg',
                    photos_sub_dirname='photos',
                    cropped_dirname='cropped',
                    **kwargs):
    params = cv2.SimpleBlobDetector_Params()
    params.minThreshold = kwargs["min_thres"]
    params.maxThreshold = kwargs["max_thres"]
    params.filterByCircularity = 1
    params.minCircularity = kwargs["min_circ"]
    params.maxCircularity = kwargs["max_circ"]
    params.filterByConvexity = 1
    params.minInertiaRatio = kwargs["min_conv"]
    params.maxInertiaRatio = kwargs["max_conv"]
    params.filterByArea = 1
    params.minArea = kwargs["min_area"]  # number of pixels
    params.maxArea = kwargs["max_area"]
    detector = cv2.SimpleBlobDetector_create(params)
    images_path = os.path.join(camera_dirname, photos_sub_dirname)
    cropped_path = os.path.join(camera_dirname, cropped_dirname)
    frame0 = cv2.imread(os.path.join(cropped_path, 'frame_0000.png'), cv2.COLOR_BGR2GRAY)
    prev_blobs = detector.detect(frame0)
    blob_trajectories = {}
    for image_name in os.listdir(images_path)[1:]:
        frame = cv2.imread(os.path.join(cropped_path, image_name), cv2.COLOR_BGR2GRAY)
        curr_blobs = detector.detect(frame)
        for i, kp in enumerate(prev_blobs):
            kp.class_id = i
        distances = np.zeros((len(prev_blobs), len(curr_blobs)))
        for i, kp1 in enumerate(prev_blobs):
            for j, kp2 in enumerate(curr_blobs):
                distances[i, j] = np.linalg.norm(np.array(kp1.pt) - np.array(kp2.pt))
        row_ind, col_ind = scipy.optimize.linear_sum_assignment(distances)
        for i, j in zip(row_ind, col_ind):
            if distances[i, j] < 10:
                curr_blobs[i].class_id = prev_blobs[j].class_id
        for kp in prev_blobs:
            blob_id = kp.class_id
            if blob_id not in blob_trajectories:
                blob_trajectories[blob_id] = []
            blob_trajectories[blob_id].append(kp.pt)
        im_with_blobs = cv2.drawKeypoints(frame, curr_blobs, np.array([]), (255, 0, 0),
                                          cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
        plt.imshow(im_with_blobs)
        plt.show()
        prev_blobs = curr_blobs
    return blob_trajectories
python opencv computer-vision object-detection tracking
1个回答
0
投票

参考下面的代码尝试一下。

将 blob_trajectories 的初始化移到循环之外,以确保字典在每次迭代中不会重置。

这些修改应该可以帮助您生成一个字典,其中的键表示圆的唯一 ID,值作为每个帧的 (x, y) 坐标列表。该代码将通过基于欧几里德距离匹配它们来跟踪跨帧的圆。它还将处理丢失或新检测到的圆圈并相应地更新轨迹。

请记住根据您的具体要求调整斑点检测参数 (kwargs),并尝试不同的参数值以优化结果。

def blob_trajectory(camera_dirname: str,
                    crop_params_filename='crop_params.pkl',
                    first_image_name='Img000001.jpg',
                    photos_sub_dirname='photos',
                    cropped_dirname='cropped',
                    **kwargs):
    params = cv2.SimpleBlobDetector_Params()
    params.minThreshold = kwargs["min_thres"]
    params.maxThreshold = kwargs["max_thres"]
    params.filterByCircularity = 1
    params.minCircularity = kwargs["min_circ"]
    params.maxCircularity = kwargs["max_circ"]
    params.filterByConvexity = 1
    params.minInertiaRatio = kwargs["min_conv"]
    params.maxInertiaRatio = kwargs["max_conv"]
    params.filterByArea = 1
    params.minArea = kwargs["min_area"]  # number of pixels
    params.maxArea = kwargs["max_area"]
    detector = cv2.SimpleBlobDetector_create(params)
    images_path = os.path.join(camera_dirname, photos_sub_dirname)
    cropped_path = os.path.join(camera_dirname, cropped_dirname)

    # Initialize the dictionary to store blob trajectories
    blob_trajectories = {}

    # Read the first frame and detect blobs
    frame0 = cv2.imread(os.path.join(cropped_path, first_image_name), cv2.COLOR_BGR2GRAY)
    prev_blobs = detector.detect(frame0)
    for i, kp in enumerate(prev_blobs):
        kp.class_id = i

    # Add initial blobs to trajectories
    for kp in prev_blobs:
        blob_id = kp.class_id
        if blob_id not in blob_trajectories:
            blob_trajectories[blob_id] = []
        blob_trajectories[blob_id].append(kp.pt)

    # Process subsequent frames
    for image_name in os.listdir(images_path)[1:]:
        frame = cv2.imread(os.path.join(cropped_path, image_name), cv2.COLOR_BGR2GRAY)
        curr_blobs = detector.detect(frame)

        # Compute distances between blobs in previous and current frames
        distances = np.zeros((len(prev_blobs), len(curr_blobs)))
        for i, kp1 in enumerate(prev_blobs):
            for j, kp2 in enumerate(curr_blobs):
                distances[i, j] = np.linalg.norm(np.array(kp1.pt) - np.array(kp2.pt))

        # Perform matching using Hungarian algorithm (linear_sum_assignment)
        row_ind, col_ind = scipy.optimize.linear_sum_assignment(distances)

        # Update blob IDs based on matching results
        for i, j in zip(row_ind, col_ind):
            if distances[i, j] < 10:
                curr_blobs[j].class_id = prev_blobs[i].class_id

        # Add new blobs to trajectories
        for kp in curr_blobs:
            blob_id = kp.class_id
            if blob_id not in blob_trajectories:
                blob_trajectories[blob_id] = []
            blob_trajectories[blob_id].append(kp.pt)

        # Visualize blobs on the current frame
        im_with_blobs = cv2.drawKeypoints(frame, curr_blobs, np.array([]), (255, 0, 0),
                                          cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
        plt.imshow(im_with_blobs)
        plt.show()

        # Update previous blobs for the next iteration
        prev_blobs = curr_blobs

    return blob_trajectories
© www.soinside.com 2019 - 2024. All rights reserved.