Skip to content

Commit 0a4ba1f

Browse files
author
admin
committed
optimized code
1 parent 4a0f56d commit 0a4ba1f

File tree

3 files changed

+398
-11
lines changed

3 files changed

+398
-11
lines changed

src/with_opencv_image.rs

Lines changed: 167 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::with_opencv::{MatExt, OpenCvElement};
22
use crate::{FromCv, IntoCv, TryFromCv, TryIntoCv};
3-
use anyhow::{Error, Result};
3+
use anyhow::{Context, Error, Result};
44
use opencv::prelude::*;
55
use std::ops::Deref;
66

@@ -245,12 +245,62 @@ where
245245
}
246246
}
247247

248+
/// RgbImage 转换为 OpenCV Mat
249+
#[allow(dead_code)]
250+
fn image_to_mat(img: &image::RgbImage) -> Result<Mat> {
251+
let width = img.width() as i32;
252+
let height = img.height() as i32;
253+
254+
// 创建 RGB Mat
255+
let rgb_mat = unsafe {
256+
Mat::new_rows_cols_with_data_unsafe_def(
257+
height,
258+
width,
259+
opencv::core::CV_8UC3,
260+
img.as_raw().as_ptr() as *mut _,
261+
)
262+
.context("Failed to create RGB Mat")?
263+
};
264+
265+
// 转换为 openCV 默认 BGR 格式
266+
let mut bgr_mat = Mat::default();
267+
opencv::imgproc::cvt_color_def(&rgb_mat, &mut bgr_mat, opencv::imgproc::COLOR_RGB2BGR)
268+
.context("Failed to convert RGB to BGR")?;
269+
270+
Ok(bgr_mat)
271+
}
272+
273+
/// OpenCV Mat 转换为 RgbImage
274+
#[allow(dead_code)]
275+
fn mat_to_image(mat: &Mat) -> Result<image::RgbImage> {
276+
if mat.empty() {
277+
return Err(anyhow::anyhow!("Input Mat is empty"));
278+
}
279+
280+
// 转换为 RGB
281+
let mut rgb_mat = Mat::default();
282+
opencv::imgproc::cvt_color_def(mat, &mut rgb_mat, opencv::imgproc::COLOR_BGR2RGB)
283+
.context("Failed to convert BGR to RGB")?;
284+
285+
let width = rgb_mat.cols() as u32;
286+
let height = rgb_mat.rows() as u32;
287+
288+
// 获取连续数据
289+
let buffer = rgb_mat
290+
.data_bytes()
291+
.context("Failed to get mat data")?
292+
.to_vec();
293+
294+
image::RgbImage::from_raw(width, height, buffer)
295+
.context("Failed to create RgbImage from Mat data")
296+
}
297+
248298
#[cfg(test)]
249299
mod tests {
300+
use super::*;
250301
use crate::with_opencv::MatExt;
251302
use crate::TryIntoCv;
252-
use anyhow::Result;
253-
use itertools::iproduct;
303+
use anyhow::{Context, Result};
254304
use opencv::prelude::*;
255305

256306
#[test]
@@ -264,7 +314,7 @@ mod tests {
264314
let image: image::GrayImage = (&mat).try_into_cv()?;
265315
let mat2: Mat = (&image).try_into_cv()?;
266316

267-
iproduct!(0..HEIGHT, 0..WIDTH).try_for_each(|(row, col)| {
317+
itertools::iproduct!(0..HEIGHT, 0..WIDTH).try_for_each(|(row, col)| {
268318
let p1: u8 = *mat.at_2d(row as i32, col as i32)?;
269319
let p2 = image[(col as u32, row as u32)].0[0];
270320
let p3: u8 = *mat2.at_2d(row as i32, col as i32)?;
@@ -279,7 +329,7 @@ mod tests {
279329
let image: image::RgbImage = (&mat).try_into_cv()?;
280330
let mat2: Mat = (&image).try_into_cv()?;
281331

282-
iproduct!(0..HEIGHT, 0..WIDTH).try_for_each(|(row, col)| {
332+
itertools::iproduct!(0..HEIGHT, 0..WIDTH).try_for_each(|(row, col)| {
283333
let p1: opencv::core::Point3_<u8> = *mat.at_2d(row as i32, col as i32)?;
284334
let p2: image::Rgb<u8> = image[(col as u32, row as u32)];
285335
let p3: opencv::core::Point3_<u8> = *mat2.at_2d(row as i32, col as i32)?;
@@ -298,4 +348,116 @@ mod tests {
298348

299349
Ok(())
300350
}
351+
352+
fn create_rgb_image() -> image::RgbImage {
353+
let width = 320;
354+
let height = 240;
355+
let mut img = image::RgbImage::new(width, height);
356+
357+
// 创建一个简单的渐变图案
358+
for y in 0..height {
359+
for x in 0..width {
360+
let r = (x as f32 / width as f32 * 255.0) as u8;
361+
let g = (y as f32 / height as f32 * 255.0) as u8;
362+
let b = ((x + y) as f32 / (width + height) as f32 * 255.0) as u8;
363+
img.put_pixel(x, y, image::Rgb([r, g, b]));
364+
}
365+
}
366+
img
367+
}
368+
369+
fn create_test_mat() -> Result<Mat> {
370+
let width = 320;
371+
let height = 240;
372+
373+
// 创建一个 3 通道的空白图像
374+
let mut mat = unsafe {
375+
Mat::new_rows_cols(height, width, opencv::core::CV_8UC3)
376+
.context("Failed to create Mat")?
377+
};
378+
379+
// 创建渐变效果
380+
for y in 0..height {
381+
for x in 0..width {
382+
let b = (y * 255 / height) as u8;
383+
let g = (x * 255 / width) as u8;
384+
let r = ((x + y) * 255 / (width + height)) as u8;
385+
386+
// 使用 Vec3b 设置像素值
387+
let color = opencv::core::Vec3b::from([b, g, r]);
388+
mat.at_2d_mut::<opencv::core::Vec3b>(y, x)
389+
.context("Failed to set pixel value")?
390+
.copy_from_slice(&color.0);
391+
}
392+
}
393+
394+
// 添加一些测试图形
395+
// 1. 画一个矩形
396+
opencv::imgproc::rectangle_points(
397+
&mut mat,
398+
opencv::core::Point::new(50, 50),
399+
opencv::core::Point::new(100, 100),
400+
opencv::core::Scalar::new(0.0, 0.0, 255.0, 0.0), // 红色
401+
2, // 线宽
402+
opencv::imgproc::LINE_8,
403+
0,
404+
)
405+
.context("Failed to draw rectangle")?;
406+
407+
// 2. 画一个圆
408+
opencv::imgproc::circle(
409+
&mut mat,
410+
opencv::core::Point::new(width / 2, height / 2),
411+
40,
412+
opencv::core::Scalar::new(0.0, 255.0, 0.0, 0.0), // 绿色
413+
2, // 线宽
414+
opencv::imgproc::LINE_8,
415+
0,
416+
)
417+
.context("Failed to draw circle")?;
418+
419+
// 3. 画一条线
420+
opencv::imgproc::line(
421+
&mut mat,
422+
opencv::core::Point::new(0, 0),
423+
opencv::core::Point::new(width - 1, height - 1),
424+
opencv::core::Scalar::new(255.0, 0.0, 0.0, 0.0), // 蓝色
425+
2, // 线宽
426+
opencv::imgproc::LINE_8,
427+
0,
428+
)
429+
.context("Failed to draw line")?;
430+
431+
Ok(mat)
432+
}
433+
434+
#[test]
435+
fn test_mat_to_image() -> Result<()> {
436+
let mat = create_test_mat()?;
437+
438+
let img = mat_to_image(&mat)?;
439+
440+
assert_eq!(img.width(), mat.cols() as u32);
441+
assert_eq!(img.height(), mat.rows() as u32);
442+
443+
img.save("/tmp/test_mat_to_image.png")
444+
.expect("mat_to_image error");
445+
446+
Ok(())
447+
}
448+
449+
#[test]
450+
fn test_image_to_mat() -> Result<()> {
451+
let img = create_rgb_image();
452+
453+
let mat = image_to_mat(&img)?;
454+
455+
assert_eq!(mat.cols(), img.width() as i32);
456+
assert_eq!(mat.rows(), img.height() as i32);
457+
assert_eq!(mat.channels(), 3);
458+
459+
println!("test_image_to_mat depth:{}", mat.depth());
460+
461+
Ok(())
462+
}
301463
}

0 commit comments

Comments
 (0)