在有效区域内生成 n 个随机 2D 点

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

我想在有效掩码内生成固定数量的随机均匀分布的 xy 点。 生成的点应该是连续的,即可以是“像素之间”。 我正在寻找一个有效的解决方案,因为这将是 pytorch 训练循环的一部分。

假设我需要 100 个有效点,我当前的解决方案如下所示:

  1. 生成 500 个随机点
  2. 对每个点进行采样并检查值是否>0.5(在有效区域内)
  3. 扔掉所有无效点以及所有多余点,这样我最终得到 100

一定有更有效的解决方案,对吧?

这是一些演示问题的示例代码:

import numpy as np
import cv2
import torch
import torch.nn.functional as F

# Create example mask
valid_mask = np.ones((300, 400), dtype=np.uint8) * 255
center = (valid_mask.shape[1] // 2, valid_mask.shape[0] // 2)
angle = 30
rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0)
rotated_image = cv2.warpAffine(valid_mask, rotation_matrix, (valid_mask.shape[1], valid_mask.shape[0]), flags=cv2.INTER_NEAREST)

# display image
cv2.imshow('mask', rotated_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

# generate 500 random points
num_points = 500
points = np.random.rand(num_points, 2) * 2 - 1  # Scale to [-1, 1]

# Convert image and points to tensors
rotated_image_tensor = torch.tensor(rotated_image, dtype=torch.float32).unsqueeze(0).unsqueeze(0) / 255  # Shape (1, 1, H, W)
points_tensor = torch.tensor(points, dtype=torch.float32).unsqueeze(0).unsqueeze(0)  # Shape (1, 1, N, 2)

# Use grid_sample to sample from the image at each point
sampled_values = F.grid_sample(rotated_image_tensor, points_tensor, mode='bilinear', padding_mode='zeros', align_corners=False)

# Squeeze to remove unnecessary dimensions and get actual values
sampled_values = sampled_values.squeeze().numpy()

# Filter points where the sampled value is greater than 0.01
valid_points = points[sampled_values > 0.5]
print(len(valid_points))

# Display valid points
rotated_image = cv2.cvtColor(rotated_image, cv2.COLOR_GRAY2BGR)
for point in valid_points:
    x, y = point
    x = int((x + 1) * rotated_image.shape[1] / 2)
    y = int((y + 1) * rotated_image.shape[0] / 2)
    cv2.circle(rotated_image, (x, y), 1, (0, 255, 0), -1)

cv2.imshow('mask', rotated_image)
cv2.waitKey(0)

如有任何帮助,我们将不胜感激。

python numpy random pytorch
1个回答
0
投票

您可以直接将掩码视为多项分布的权重并从中采样。这是一个最小的例子:

import numpy as np
import matplotlib.pyplot as plt
import torch

generator = torch.Generator()
generator.manual_seed(98237)

# Create example mask
mask = torch.zeros((256, 256))
mask[32:187, 53:123] = 1.
mask[150:220, 89:198] = 1.

n_samples = 10_000

# define the probability density function and sample
pdf = mask / mask.sum()

coords = torch.multinomial(pdf.flatten(), n_samples, replacement=True, generator=generator)

x, y = torch.unravel_index(coords, pdf.shape)
x_dithered = x + torch.rand(x.shape, generator=generator) - 0.5
y_dithered= y + torch.rand(y.shape, generator=generator) - 0.5

# Create a 2D histogram of the samples
hist = np.histogram2d(x_dithered, y_dithered, bins=(np.arange(0, 256), np.arange(0, 256)))[0]

fig, axes = plt.subplots(1, 2, figsize=(10, 5))
axes[0].imshow(mask, origin="lower", cmap="gray")
axes[0].set_title("Mask")

axes[1].imshow(hist, origin="lower", cmap="viridis")
axes[1].set_title("Samples")

这给出了:

enter image description here

这里的技巧是将掩码转换为一维概率质量函数(PMF),然后对整数索引进行采样。接下来使用解开将它们转换回二维数组索引,并添加均匀分布的噪声以“涂抹”单个像素支持内的位置。

这种方法可以推广到任意 PMF,而不仅仅是掩模。

我希望这有帮助!

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