所以我有这个扑翼机器人,我在机翼上画了一些圆圈,我认为这些圆圈很容易跟踪。当机翼在每一帧中移动时,与其他帧相比,某些圆圈可能会显得更模糊或椭圆。 我的目标是生成一个字典,其中的键表示圆的唯一 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
参考下面的代码尝试一下。
将 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