如何正确获取矩形图像对角线像素?消除采样重复的方法
解决图像对角线像素采样的重复问题
问题分析
你当前的实现通过计算对角线长度作为迭代步数,再按比例映射行列坐标,但浮点运算的舍入误差导致多个迭代步对应同一个像素,产生重复。这种按距离均匀采样的方式并不适配栅格图像的离散像素特性。
解决方案:Bresenham直线算法
Bresenham算法是计算机图形学中专门用于在栅格上生成直线的经典算法,它能精准选取最接近直线的离散像素,且每个像素仅被采样一次,完全适配你获取对角线像素的需求,同时支持任意分辨率的矩形图像。
Rust实现(适配image crate)
针对你需要的右上角到左下角对角线(起点:(num_cols-1, 0),终点:(0, num_rows-1)),实现代码如下:
use image::GenericImageView; fn get_diagonal_pixels(img: &impl GenericImageView) -> Vec<(u32, u32)> { let num_cols = img.width(); let num_rows = img.height(); // 对角线起点(右上角)和终点(左下角) let mut x = num_cols - 1; let mut y = 0; let dx = 0i32 - (num_cols - 1) as i32; // x从宽-1到0,变化量为负 let dy = (num_rows - 1) as i32 - 0i32; // y从0到高-1,变化量为正 let mut err = dx + dy; // 误差项初始化 let mut diagonal = vec![(x, y)]; while x != 0 || y != num_rows - 1 { let e2 = 2 * err; // 判断是否需要调整x坐标 if e2 >= dx { err += dx; x = x.saturating_sub(1); // 避免下溢,确保x最终到0 } // 判断是否需要调整y坐标 if e2 <= dy { err += dy; y = y.saturating_add(1); // 避免上溢,确保y最终到num_rows-1 } diagonal.push((x, y)); } diagonal }
代码说明
- 坐标适配:遵循image crate的坐标系(左上角为
(0,0)),明确对角线的起止点为右上角和左下角。 - 无浮点误差:全程使用整数运算控制误差项,避免舍入问题导致的重复像素。
- 唯一像素保证:每一步迭代仅生成一个新的像素坐标,要么单独调整x/y,要么同时调整,确保所有坐标唯一。
替换原有代码后的使用示例
// 加载图像 let img = image::open("your_image.png").unwrap(); let diag_pixels = get_diagonal_pixels(&img); // 提取亮度值(以RGB图像为例,计算标准灰度值) let diag_brightness: Vec<f32> = diag_pixels .iter() .map(|&(x, y)| { let pixel = img.get_pixel(x, y); 0.299 * pixel[0] as f32 + 0.587 * pixel[1] as f32 + 0.114 * pixel[2] as f32 }) .collect();
内容的提问来源于stack exchange,提问作者Ximtor
相关产品推荐
相关产品推荐

