11use crate :: with_opencv:: { MatExt , OpenCvElement } ;
22use crate :: { FromCv , IntoCv , TryFromCv , TryIntoCv } ;
3- use anyhow:: { Error , Result } ;
3+ use anyhow:: { Context , Error , Result } ;
44use opencv:: prelude:: * ;
55use 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) ]
249299mod 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