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

若该文为原创文章,未经允许不得转载
原博主博客地址: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


OpenCV开发专栏

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

前言

      红胖子来也!!!

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

 

Demo

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

 

技术点

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

 

图像缩放

概述

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

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

函数原型

void resize( InputArray src,
          OutputArray dst,
          Size dsize,
          double fx = 0,
          double fy = 0,
          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时,参数三生效;
  • 参数六:缩放时,采用的实现方式;

 

图像金字塔

概述

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

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

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

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

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

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

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

Demo源码

void OpenCVManager::testResizeAndPyrUpAndPyrDown()
{
    QString fileName1 = "E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/1.jpg";
    cv::Mat srcMat = cv::imread(fileName1.toStdString());

#define FIRST_ZOOM_IN (1)   // 先放大还是先缩小

#if !FIRST_ZOOM_IN
    int width = 300;
    int height = 200;

    cv::resize(srcMat, srcMat, cv::Size(width, height));

    cv::String windowName = _windowTitle.toStdString();
    cvui::init(windowName);

    cv::Mat windowMat = cv::Mat(cv::Size(srcMat.cols * 6, srcMat.rows * 4),
                                srcMat.type());
#else
    int width = 300;
    int height = 200;

    cv::resize(srcMat, srcMat, cv::Size(width * 2, height * 2));

    cv::String windowName = _windowTitle.toStdString();
    cvui::init(windowName);
    cv::Mat windowMat = cv::Mat(cv::Size(srcMat.cols * 3, srcMat.rows * 2),
                                srcMat.type());
#endif

    while(true)
    {
        windowMat = cv::Scalar(0, 0, 0);

        cv::Mat mat;
        cv::Mat dstMat;

#if !FIRST_ZOOM_IN
        // 原图先copy到左边
        cv::Mat leftMat = windowMat(cv::Range(0, srcMat.rows),
                                    cv::Range(0, srcMat.cols));
        cv::addWeighted(leftMat, 0.0f, srcMat, 1.0f, 0.0f, leftMat);

        cvui::printf(windowMat, srcMat.cols * 0, srcMat.rows * 1, "1 ->resize 2 -> resize 0.5 -> resize 2");
        cvui::printf(windowMat, srcMat.cols * 0, srcMat.rows * 3, "1 ->pyrUp 2 -> pyrDown 0.5 -> pyrUp 2");
        {
            // 使用resize放大
            cv::resize(srcMat, dstMat, cv::Size(), 2.0, 2.0);
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 2),
                            cv::Range(srcMat.cols * 1, srcMat.cols * 3));
            qDebug() << __FILE__<<__LINE__<<dstMat.cols << dstMat.rows << mat.cols << mat.rows;
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);

            // 使用resize缩小
            cv::resize(dstMat, dstMat, cv::Size(), 0.5, 0.5);
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 1),
                            cv::Range(srcMat.cols * 3, srcMat.cols * 4));
            qDebug() << __FILE__<<__LINE__<<dstMat.cols << dstMat.rows << mat.cols << mat.rows;
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);

            // 使用resize放大
            cv::resize(dstMat, dstMat, cv::Size(), 2.0, 2.0);
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 2),
                            cv::Range(srcMat.cols * 4, srcMat.cols * 6));
            qDebug() << __FILE__<<__LINE__<<dstMat.cols << dstMat.rows << mat.cols << mat.rows;
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
        }

        {
            // 使用pyrUp放大
            cv::pyrUp(srcMat, dstMat);
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 4),
                            cv::Range(srcMat.cols * 1, srcMat.cols * 3));
            qDebug() << __FILE__<<__LINE__<<dstMat.cols << dstMat.rows << mat.cols << mat.rows;
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);

            // 使用pyrDown缩小
            cv::pyrDown(dstMat, dstMat);
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3),
                            cv::Range(srcMat.cols * 3, srcMat.cols * 4));
            qDebug() << __FILE__<<__LINE__<<dstMat.cols << dstMat.rows << mat.cols << mat.rows;
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);

            // 使用pyrUp放大
            cv::pyrUp(dstMat, dstMat);
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 4),
                            cv::Range(srcMat.cols * 4, srcMat.cols * 6));
            qDebug() << __FILE__<<__LINE__<<dstMat.cols << dstMat.rows << mat.cols << mat.rows;
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
        }
#else
        // 先恢复到600*400
        // 原图先copy到左边
        cv::Mat leftMat = windowMat(cv::Range(0, srcMat.rows),
                                    cv::Range(0, srcMat.cols));
        cv::addWeighted(leftMat, 0.0f, srcMat, 1.0f, 0.0f, leftMat);
        cvui::printf(windowMat, srcMat.cols * 1, srcMat.rows * 0.5, "1 ->resize 0.5 -> resize 2 -> resize 0.5");
        cvui::printf(windowMat, srcMat.cols * 1, srcMat.rows * 1.5, "1 ->pyrDown 0.5 -> pyrUp 2 -> pyrDown 0.5");
        {
            // 使用resize缩小
            cv::resize(srcMat, dstMat, cv::Size(), 0.5, 0.5);
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 0.5),
                            cv::Range(srcMat.cols * 1, srcMat.cols * 1.5));
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);

            // 使用resize放大
            cv::resize(dstMat, dstMat, cv::Size(), 2.0, 2.0);
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 1),
                            cv::Range(srcMat.cols * 1.5, srcMat.cols * 2.5));
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);

            // 使用resize缩小
            cv::resize(dstMat, dstMat, cv::Size(), 0.5, 0.5);
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 0.5),
                            cv::Range(srcMat.cols * 2.5, srcMat.cols * 3));
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
        }

        {
            // 使用pyrDown缩小
            cv::pyrDown(srcMat, dstMat);
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 1.5),
                            cv::Range(srcMat.cols * 1, srcMat.cols * 1.5));
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);

            // 使用pyrUp放大
            cv::pyrUp(dstMat, dstMat);
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),
                            cv::Range(srcMat.cols * 1.5, srcMat.cols * 2.5));
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);

            // 使用pyrDown缩小
            cv::pyrDown(dstMat, dstMat);
            // copy
            mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 1.5),
                            cv::Range(srcMat.cols * 2.5, srcMat.cols * 3));
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
        }
#endif
        // 更新
        cvui::update();
        // 显示
        cv::imshow(windowName, windowMat);
        // esc键退出
        if(cv::waitKey(25) == 27)
        {
            break;
        }
    }
}

工程模板:对应版本号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

发布了254 篇原创文章 · 获赞 346 · 访问量 49万+

猜你喜欢

转载自blog.csdn.net/qq21497936/article/details/105191466