若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/105191466
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究
目录
红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中...(点击传送门)
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
转载:https://blog.csdn.net/qq21497936/article/details/105191466