小言_互联网的博客

OpenCV开发笔记(三十六):红胖子8分钟带你深入了解缩放与图像金字塔(图文并茂+浅显易懂+程序源码)

504人阅读  评论(0)

若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/105191466
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究

目录

前言

Demo

技术点

图像缩放

概述

函数原型

图像金字塔

概述

向上采样(放大)函数原型

向下采样(缩小)函数原型

Demo源码

工程模板:对应版本号v1.31.0


红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中...(点击传送门)

OpenCV开发专栏(点击传送门)

 

    OpenCV开发笔记(三十六):红胖子8分钟带你深入了解缩放与图像金字塔(图文并茂+浅显易懂+程序源码)

 

前言

      红胖子来也!!!

      图像缩放使用cv::resize函数,与其类似的还有图像金字塔也可对图像进行缩放。

 

Demo

      由Demo效果可以看出,resize能很大程度上保证质量,但是多次操作还是会有失真,不仅如此,在其他ide也会有这个现象。

 

技术点

在缩放图像里面,原始图像需要缓存一份,多次操作缩放最终是由原始图像乘以比例系数得到结果图像。

 

图像缩放

概述

      图像缩放直接提供了函数,通过测试,其实际的缩放效果对原图像的保存是优于金字塔相关操作的,具体可以查看前面Demo运行效果的对比。

      此处有一点要注意,使用resize进行图像缩放,线性差值方式是默认的方式,如果对图像进行放大,那么最好使用CV_INTER_AREA区域差值来做。

函数原型


  
  1. void resize( InputArray src,
  2. OutputArray dst,
  3. Size dsize,
  4. double fx = 0,
  5. double fy = 0,
  6. int interpolation = INTER_LINEAR );
  • 参数一:InputArray类型的src,一般是cv::Mat;
  • 参数二:OutputArray类型的dst;它具有大小dsize(当它为非零时)或从src.size()、fx和fy获得;dst的类型与src相同。即:当参数三传入空,则fx和fy为系数计算输出的图像尺寸;
  • 参数三:Size类型的dsize,缩放后输出的图像尺寸;
  • 参数四:double类型的fx,默认为0,为0时,参数三生效;
  • 参数五:double类型的fx,默认为0,为0时,参数三生效;
  • 参数六:缩放时,采用的实现方式;

 

图像金字塔

概述

      图像金字塔是图像多尺度表达的一种,最主要用于图像的分割。

拉普拉斯金字塔是用来向上采样的(放大),原理如下图:

高斯金字塔是用来向下采样的(缩小),原理如下图:

向上采样(放大)函数原型


  
  1. void pyrUp( InputArray src,
  2. OutputArray dst,
  3. const Size& dstsize = Size(),
  4. int borderType = BORDER_DEFAULT );
  • 参数一:InputArray类型的src,为cv::Mat;
  • 参数二:OutPutArray类型的dst,为cv::Mat;
  • 参数三:Size类型的dsize,缩放后输出的图像尺寸;
  • 参数四:int类型的borderType,边界处理类型;

向下采样(缩小)函数原型


  
  1. void pyrDown( InputArray src,
  2. OutputArray dst,
  3. const Size& dstsize = Size(),
  4. int borderType = BORDER_DEFAULT );
  • 参数一:InputArray类型的src,为cv::Mat;
  • 参数二:OutPutArray类型的dst,为cv::Mat;
  • 参数三:Size类型的dsize,缩放后输出的图像尺寸;
  • 参数四:int类型的borderType,边界处理类型;

 

Demo源码


  
  1. void OpenCVManager::testResizeAndPyrUpAndPyrDown()
  2. {
  3. QString fileName1 = "E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/1.jpg";
  4. cv::Mat srcMat = cv::imread(fileName1.toStdString());
  5. #define FIRST_ZOOM_IN (1) // 先放大还是先缩小
  6. #if !FIRST_ZOOM_IN
  7. int width = 300;
  8. int height = 200;
  9. cv::resize(srcMat, srcMat, cv::Size(width, height));
  10. cv::String windowName = _windowTitle.toStdString();
  11. cvui::init(windowName);
  12. cv::Mat windowMat = cv::Mat(cv::Size(srcMat.cols * 6, srcMat.rows * 4),
  13. srcMat.type());
  14. #else
  15. int width = 300;
  16. int height = 200;
  17. cv::resize(srcMat, srcMat, cv::Size(width * 2, height * 2));
  18. cv::String windowName = _windowTitle.toStdString();
  19. cvui::init(windowName);
  20. cv::Mat windowMat = cv::Mat(cv::Size(srcMat.cols * 3, srcMat.rows * 2),
  21. srcMat.type());
  22. #endif
  23. while( true)
  24. {
  25. windowMat = cv::Scalar( 0, 0, 0);
  26. cv::Mat mat;
  27. cv::Mat dstMat;
  28. #if !FIRST_ZOOM_IN
  29. // 原图先copy到左边
  30. cv::Mat leftMat = windowMat(cv::Range( 0, srcMat.rows),
  31. cv::Range( 0, srcMat.cols));
  32. cv::addWeighted(leftMat, 0.0f, srcMat, 1.0f, 0.0f, leftMat);
  33. cvui:: printf(windowMat, srcMat.cols * 0, srcMat.rows * 1, "1 ->resize 2 -> resize 0.5 -> resize 2");
  34. cvui:: printf(windowMat, srcMat.cols * 0, srcMat.rows * 3, "1 ->pyrUp 2 -> pyrDown 0.5 -> pyrUp 2");
  35. {
  36. // 使用resize放大
  37. cv::resize(srcMat, dstMat, cv::Size(), 2.0, 2.0);
  38. // copy
  39. mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 2),
  40. cv::Range(srcMat.cols * 1, srcMat.cols * 3));
  41. qDebug() << __FILE__<<__LINE__<<dstMat.cols << dstMat.rows << mat.cols << mat.rows;
  42. cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
  43. // 使用resize缩小
  44. cv::resize(dstMat, dstMat, cv::Size(), 0.5, 0.5);
  45. // copy
  46. mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 1),
  47. cv::Range(srcMat.cols * 3, srcMat.cols * 4));
  48. qDebug() << __FILE__<<__LINE__<<dstMat.cols << dstMat.rows << mat.cols << mat.rows;
  49. cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
  50. // 使用resize放大
  51. cv::resize(dstMat, dstMat, cv::Size(), 2.0, 2.0);
  52. // copy
  53. mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 2),
  54. cv::Range(srcMat.cols * 4, srcMat.cols * 6));
  55. qDebug() << __FILE__<<__LINE__<<dstMat.cols << dstMat.rows << mat.cols << mat.rows;
  56. cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
  57. }
  58. {
  59. // 使用pyrUp放大
  60. cv::pyrUp(srcMat, dstMat);
  61. // copy
  62. mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 4),
  63. cv::Range(srcMat.cols * 1, srcMat.cols * 3));
  64. qDebug() << __FILE__<<__LINE__<<dstMat.cols << dstMat.rows << mat.cols << mat.rows;
  65. cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
  66. // 使用pyrDown缩小
  67. cv::pyrDown(dstMat, dstMat);
  68. // copy
  69. mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),
  70. cv::Range(srcMat.cols * 3, srcMat.cols * 4));
  71. qDebug() << __FILE__<<__LINE__<<dstMat.cols << dstMat.rows << mat.cols << mat.rows;
  72. cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
  73. // 使用pyrUp放大
  74. cv::pyrUp(dstMat, dstMat);
  75. // copy
  76. mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 4),
  77. cv::Range(srcMat.cols * 4, srcMat.cols * 6));
  78. qDebug() << __FILE__<<__LINE__<<dstMat.cols << dstMat.rows << mat.cols << mat.rows;
  79. cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
  80. }
  81. #else
  82. // 先恢复到600*400
  83. // 原图先copy到左边
  84. cv::Mat leftMat = windowMat(cv::Range( 0, srcMat.rows),
  85. cv::Range( 0, srcMat.cols));
  86. cv::addWeighted(leftMat, 0.0f, srcMat, 1.0f, 0.0f, leftMat);
  87. cvui:: printf(windowMat, srcMat.cols * 1, srcMat.rows * 0.5, "1 ->resize 0.5 -> resize 2 -> resize 0.5");
  88. cvui:: printf(windowMat, srcMat.cols * 1, srcMat.rows * 1.5, "1 ->pyrDown 0.5 -> pyrUp 2 -> pyrDown 0.5");
  89. {
  90. // 使用resize缩小
  91. cv::resize(srcMat, dstMat, cv::Size(), 0.5, 0.5);
  92. // copy
  93. mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 0.5),
  94. cv::Range(srcMat.cols * 1, srcMat.cols * 1.5));
  95. cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
  96. // 使用resize放大
  97. cv::resize(dstMat, dstMat, cv::Size(), 2.0, 2.0);
  98. // copy
  99. mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 1),
  100. cv::Range(srcMat.cols * 1.5, srcMat.cols * 2.5));
  101. cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
  102. // 使用resize缩小
  103. cv::resize(dstMat, dstMat, cv::Size(), 0.5, 0.5);
  104. // copy
  105. mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 0.5),
  106. cv::Range(srcMat.cols * 2.5, srcMat.cols * 3));
  107. cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
  108. }
  109. {
  110. // 使用pyrDown缩小
  111. cv::pyrDown(srcMat, dstMat);
  112. // copy
  113. mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 1.5),
  114. cv::Range(srcMat.cols * 1, srcMat.cols * 1.5));
  115. cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
  116. // 使用pyrUp放大
  117. cv::pyrUp(dstMat, dstMat);
  118. // copy
  119. mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),
  120. cv::Range(srcMat.cols * 1.5, srcMat.cols * 2.5));
  121. cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
  122. // 使用pyrDown缩小
  123. cv::pyrDown(dstMat, dstMat);
  124. // copy
  125. mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 1.5),
  126. cv::Range(srcMat.cols * 2.5, srcMat.cols * 3));
  127. cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
  128. }
  129. #endif
  130. // 更新
  131. cvui::update();
  132. // 显示
  133. cv::imshow(windowName, windowMat);
  134. // esc键退出
  135. if(cv::waitKey( 25) == 27)
  136. {
  137. break;
  138. }
  139. }
  140. }

 

工程模板:对应版本号v1.31.0

      对应版本号v1.31.0

 

原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/105191466

 


转载:https://blog.csdn.net/qq21497936/article/details/105191466
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场