提问人:Ximtor 提问时间:11/15/2023 更新时间:11/16/2023 访问量:72
从矩形图像中获取对角线像素
Get diagonal pixels from rectangular image
问:
我有一张 1920x1080 的输入图像,想要分析对角线上的发光分布。我可以只使用中间一排,并根据需要“拉伸”它作为替代方案,但如果可能的话,我想坚持使用实际的对角线。
我目前的方法是基于毕达哥拉斯选择通过对角线上的维度因子计算的像素。这导致了大约 170 个重复项,我假设是因为四舍五入。
有没有合适的方法可以做到这一点?输入始终采用这种格式,但分辨率可变。
let num_rows = img.height();
let num_cols = img.width();
let diag_steps = ((num_cols.pow(2) + num_rows.pow(2)) as f32)
.sqrt()
.floor() as u32;
let col_factor = num_cols as f32 / diag_steps as f32;
let row_factor = num_rows as f32 / diag_steps as f32;
let mut diag_values = vec![];
for s in 0..diag_steps {
let r = ((s as f32 * row_factor).round() as u32).min(num_rows - 1);
let c = ((s as f32 * col_factor).round() as u32).min(num_cols - 1);
diag_values.push(c, r);
}
这种方法纯粹基于我认为应该有效的方法,我正在使用图像箱来读取/写入图像。我在 SO 上找到了一个相关问题,但答案对我没有帮助,我需要从右上角到左下角穿过中间的实际对角线,而不是设置 Y = X 的对角线。
我还对每个坐标周围的像素进行了平均,以考虑一些噪点,但这对于重复项并不重要。
我尝试对代码块中列出的图像进行采样,并希望沿图像的对角线获得像素。我得到了预期的 2202 像素数量,但由于四舍五入,这些像素包含重复项,我认为这可能会导致以后出现进一步的问题。
答:
0赞
MeetTitan
11/16/2023
#1
您可以按纵横比单步执行,如下所示:
fn greatest_common_factor(rhs: u32, lhs: u32) -> u32 {
todo!("Implement me or import a crate for me")
}
fn simplify_fraction(rhs: u32, lhs: u32) -> (u32, u32) {
let gcf = greatest_common_factor(rhs, lhs);
(rhs / gcf, lhs / gcf)
}
fn top_left_to_bottom_right<I>(image: &I) -> impl Iterator<Item = I::Pixel> + '_
where
I: GenericImageView,
{
let width = image.width();
let height = image.height();
let (run, rise) = simplify_fraction(width, height);
let x = (0..width).into_iter().step_by(run as usize);
//start from top right instead?
//let x = (0..width).into_iter().step_by(run as usize).rev();
let y = (0..height).into_iter().step_by(rise as usize);
let coords = x.zip(y);
coords.map(|(x, y)| image.get_pixel(x, y))
}
这些是落在精确对角线上的确切像素。
这显然有使用整数作为纵横比的缺点。结果是 1920x1080 的图像将具有 16/9 的纵横比。因为我们分别步进 16 和 9 像素,所以我们跳过了一些像素。
此函数为 1920x1080 图像 (gcf) 输出 120 像素。如果这是不可取的,您将需要处理混合数字的子像素操作和计算(例如,什么是 1.5 像素?映像箱是否支持开箱即用?你会将浮点数四舍五入为整数而不关心均匀性吗?然后,您可以在 gcf 点数之间推断点,或将纵横比计算为浮点数的比率,并使用如上所示的斜率。
评论
0赞
Ximtor
11/16/2023
感谢您的详细回答和解释!我只是使用并从 run/rise 而不是 0 开始,结果足以满足我的需求,并且到目前为止效果很好。至少我现在有一个很好的选择,并且有更多的理解!:)num::integer::gdc
评论