文章目录
一、图像编解码
[dependencies]
image = "*"
imageproc ="*"
- image 该库主要处理数据流中的图像编解码工作,图像的创建与保存,以及一些简单的像素操作。
- imageproc 该库为子库,涉及图像高级操作:包括图像 轮廓查找,角点检测,相似点距离计算,图形绘制,边缘检测,各种滤波,梯度滤波,HOG,积分图像,形态学,矩形框,非极大值抑制,模板匹配 等操作。
Rust下的图像处理库,image-rs 提供了基本的图像处理功能和用于在各种图像格式之间进行转换的方法。所有图像处理功能都对实现GenericImageView
和GenericImage
特性并返回ImageBuffer
的类型进行操作。
image-rs支持的图像格式如下:
Format | Decoding | Encoding |
---|---|---|
PNG | All supported color types | Same as decoding |
JPEG | Baseline and progressive | Baseline JPEG |
GIF | Yes | Yes |
BMP | Yes | RGB(8), RGBA(8), Gray(8), GrayA(8) |
ICO | Yes | Yes |
TIFF | Baseline(no fax support) + LZW + PackBits | RGB(8), RGBA(8), Gray(8) |
WebP | Lossy(Luma channel only) | No |
AVIF | Only 8-bit | Lossy |
PNM | PBM, PGM, PPM, standard PAM | Yes |
DDS | DXT1, DXT3, DXT5 | No |
TGA | Yes | RGB(8), RGBA(8), BGR(8), BGRA(8), Gray(8), GrayA(8) |
farbfeld | Yes | Yes |
从上表我们可以看出image-rs基本支持了应用中常见的图像容器格式类型。
关于ImageDecoder和ImageDecoderExt 所有的图像格式decoders都包含了ImageDecoder
实现,其中主要过程是从图像文件中获取图像的metadata并解码图像。
ImageDecoder
pub trait ImageDecoder: Sized {
type Reader: Read;
fn dimensions(&self) -> (u64, u64); // 返回一个包含图像宽度和高度的元组
fn colortype(&self) -> ColorType; // 返回图像的颜色类型,例如RGB(8)(8位RGB)
fn into_reader(self) -> ImageResult<Self::Reader>; // 返回可用于获取图像字节的阅读器。
fn row_bytes(&self) -> u64 { ... } // 返回图像的一行中的字节数。
fn total_bytes(&self) -> u64 { ... } // 返回图像中的字节总数。
fn scanline_bytes(&self) -> u64 { ... } // 返回可以从此解码器有效读取的最小字节数。
fn read_image(self) -> ImageResult<Vec<u8>> { ... } //返回图像中的所有字节。
fn read_image_with_progress<F: Fn(Progress)>(
self,
progress_callback: F
) -> ImageResult<Vec<u8>> { ... } //与read_image相同,但会定期调用提供的回调以提供有关加载进度的更新。
}
其中一些decoders的比较重要的参数包括:
dimensions
:返回包含图像的宽度和高度的元组数据color_type
:返回由decoder返回的图像的色彩类型read_image
:把图像解码成bytes片
像素类型
image
提供了如下几种像素类型:
Rgb
: 包含Rgb像素Rgba
: 包含Rgba像素(a为alpha,透明通道)Luma
: 灰度像素LumaA
: 包含alpha通道的灰度像素
图像处理函数
blur
:使用高斯模糊来处理图像brighten
:图像高亮处理huerotate
: 旋转色彩空间contrast
: 调整图像的对比度crop
: 剪裁图像filter3x3
:使用3x3的矩阵来处理图像,可用于图像降噪,升噪grayscale
: 灰度化图像flip_horizontal
: 水平翻转图像flip_vertical
: 垂直翻转图像invert
: 对图像的每个像素求反resize
: 改变图像尺寸rotate180
: 图像顺时针旋转180度rotate270
: 图像顺时针旋转270度rotate90
: 图像顺时针unsharpen
: 降低图像锐度
二、GenericImageView与GenericImage
图像中的各个像素在左上角以(0,0)索引。
GenericImageView
和GenericImage
特点
特性提供了检查(GenericImageView
)和操作(GenericImage
)图像的方法,这些参数在图像的像素类型上进行了参数化。
GenericImageView
:获取图像视图属性与像素内容
- Dimensions:返回一个包含图像宽度和高度的元组。
- get_pixel:返回位于(x,y)的像素。
- pixel:返回一个迭代器,迭代该图像的像素。
GenericImage
:操作图像视图
- put_pixel:将像素放置在位置(x,y)。
- copy_from:将所有像素从另一个图像复制到该图像中。
三、ImageBuffer 与 DynamicImage
ImageBuffer
image
提供了两种表示图像数据的主要方式:ImageBuffer文档
由其像素类型参数化的图像,由像素的宽度和高度以及像素向量表示。它提供对像素的直接访问并实现GenericImageView
和GenericImage
特性。
extern crate image;
use image::{GenericImage, GenericImageView, ImageBuffer, RgbImage};
// 构建具有指定宽度和高度的RGB图像缓冲区。
let img: RgbImage = ImageBuffer::new(512, 512);
// Construct a new by repeated calls to the supplied closure.
let mut img = ImageBuffer::from_fn(512, 512, |x, y| {
if x % 2 == 0 {
image::Luma([0u8])
} else {
image::Luma([255u8])
}
});
// 获取图像的宽和高。
let (width, height) = img.dimensions();
//访问坐标像素。 或者使用`GenericImage` trait.的`get_pixel`方法
let pixel = img[(100, 100)];
let pixel = *img.get_pixel(100, 100);
// 指定坐标点的像素赋值.
img.put_pixel(100, 100, pixel);
// 迭代图像中的所有像素。
for pixel in img.pixels() {
// Do something with pixel.
}
DynamicImage
DynamicImage是所有受支持ImageBuffer<P>
类型的枚举。其确切的图像类型在运行时确定。它是打开图像时返回的类型。
为了方便起见,DynamicImage
重新实现了所有图像处理功能。
DynamicImage
实现RGBA像素的GenericImageView
和GenericImage
特征。
SubImage
SubImage 以矩形坐标为界的另一幅图像的视图。给定的坐标设置矩形左上角的位置。这用于在图像的子区域上执行图像处理功能。
extern crate image;
use image::{GenericImageView, ImageBuffer, RgbImage, imageops};
let mut img: RgbImage = ImageBuffer::new(512, 512);
let subimg = imageops::crop(&mut img, 0, 0, 100, 100);
assert!(subimg.dimensions() == (100, 100));
四、示例
打开和保存图像
extern crate image;
use image::GenericImageView;
fn main() {
// image::open 通过文件路径打开图片并返回`DynamicImage`对象。
let img = image::open("tests/images/jpg/progressive/cat.jpg").unwrap();
// 获取图像属性
println!("dimensions {:?}", img.dimensions());
println!("{:?}", img.color());
// 保存
img.save("test.png").unwrap();
// 获取图像缓冲(网络请求获得)并保存
let buffer: &[u8] = unimplemented!(); // Generate the image data
image::save_buffer("image.png", buffer, 800, 600, image::ColorType::Rgb8).unwrap()
}
测试示例:
use image;
use image::GenericImageView;
// Uage: cargo run 1.jpg 2.jpg
fn main() {
let img_inputpath = std::env::args().nth(1).expect("no pattern given");
let img_outputpath = std::env::args().nth(2).expect("no path given");
let img = image::open(img_inputpath).unwrap();
let (width,height) = img.dimensions();
println!("图像:宽={},高={} ",width,height);
img.save(img_outputpath).unwrap();
}
image
提供open
从路径打开图像的功能。图像格式由路径的文件扩展名确定。一个io
模块为阅读器提供了更多控制权。
Generating Fractals例子
在dependencies
中添加引用
[dependencies]
image = "0.23.4"
num-complex = "0.2.4"
修改源文件main.rs
如下
extern crate image;
extern crate num_complex;
fn main() {
let imgx = 800;
let imgy = 800;
let scalex = 3.0 / imgx as f32;
let scaley = 3.0 / imgy as f32;
// Create a new ImgBuf with width: imgx and height: imgy
let mut imgbuf = image::ImageBuffer::new(imgx, imgy);
// Iterate over the coordinates and pixels of the image
for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
let r = (0.3 * x as f32) as u8;
let b = (0.3 * y as f32) as u8;
*pixel = image::Rgb([r, 0, b]);
}
// A redundant loop to demonstrate reading image data
for x in 0..imgx {
for y in 0..imgy {
let cx = y as f32 * scalex - 1.5;
let cy = x as f32 * scaley - 1.5;
let c = num_complex::Complex::new(-0.4, 0.6);
let mut z = num_complex::Complex::new(cx, cy);
let mut i = 0;
while i < 255 && z.norm() <= 2.0 {
z = z * z + c;
i += 1;
}
let pixel = imgbuf.get_pixel_mut(x, y);
let image::Rgb(data) = *pixel;
*pixel = image::Rgb([data[0], i as u8, data[2]]);
}
}
// Save the image as “fractal.png”, the format is deduced from the path
imgbuf.save("fractal.png").unwrap();
}
效果图: