若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/101168828
目录
OpenCV开发专栏
《OpenCV开发笔记(〇):使用mingw530_32编译openCV3.4.1源码,搭建Qt5.9.3的openCV开发环境》
《OpenCV开发笔记(三):OpenCV图像的概念和基本操作》
《OpenCV开发笔记(四):OpenCV图片和视频数据的读取与存储》
《OpenCV开发笔记(五):OpenCV读取与操作摄像头》
《OpenCV开发笔记(六):OpenCV基础数据结构、颜色转换函数和颜色空间》
《OpenCV开发笔记(八):OpenCV常用操作之计时、缩放、旋转、镜像》
《OpenCV开发笔记(九):OpenCV区域图像(ROI)和整体、局部图像混合》
《OpenCV开发笔记(十):OpenCV图像颜色通道分离和图像颜色多通道混合》
持续补充中…
OpenCV开发笔记(八):OpenCV常用操作之计时、缩放、旋转、镜像
前言
图片浏览器的一些常规操作。
常用操作
在OpenCV开发过程中用于测试性能计时的:计时(计算处理的时间)。
在一般的图像处理中有的几个操作:缩放(放大、缩小),旋转(90度的倍数)、镜像(x轴反向、y轴反向)。
注意:意角度的旋转使用cv::Mat不太合适,开发过程中会用到其他ui框架,所以使用其他ui框架做旋转是比较合适的。
Demo
计时函数
OpenCV提供了两个渐变的计时函数:getTickCount()和getTickFrequency()。
- getTickCount():getTickCount()函数返回CPU自某个事件(如启动电脑)以来走过的时钟周期数。
- getTickFrequency():getTickFrequency()函数返回CPU一秒钟所走的时钟周期数。
测试结果如下:
cv::getTickFrequency()获取的频率为10,000,000,得到cpu的周期为一千万次每秒。
访问图像中像素的三类方法
cv::Mat访问的三类方法:
- 方法一:at函数
- 方法二:使用迭代器
- 方法三:通过数据指针
具体可查看:《OpenCV开发笔记(三):OpenCV图像的概念和基本操作》中的像素值的读写。
旋转(90度的整数倍)
旋转90°的整数就是对矩阵位置进行变换,如下图:
旋转函数1:cv::transpose()
该函数无任何函数,直接对矩阵进行顺时钟旋转90°,函数原型如下:
CV_EXPORTS_W void transpose(InputArray src, OutputArray dst);
旋转函数2:cv::rotate()
该函数旋转函数,三个枚举可以旋转90°,180°,270°,逆时针旋转90°就是顺时钟270°,函数原型如下:
CV_EXPORTS_W void rotate(InputArray src, OutputArray dst, int rotateCode);
- 参数一:输入mat
- 参数二:输出mat
- 参数三:旋转枚举,如下:
enum RotateFlags {
ROTATE_90_CLOCKWISE = 0, //Rotate 90 degrees clockwise
ROTATE_180 = 1, //Rotate 180 degrees clockwise
ROTATE_90_COUNTERCLOCKWISE = 2, //Rotate 270 degrees clockwise
};
代码示例:
cv::rotate(srcMat, srcMat, cv::ROTATE_90_CLOCKWISE);
镜像(x轴翻转,y轴翻转)
镜像就是对X轴和Y轴的值翻转对调,如下图:
翻转函数:cv::flip
该函数为翻转函数,函数圆形如下:
CV_EXPORTS_W void flip(InputArray src, OutputArray dst, int flipCode);
- 参数一:输入mat
- 参数二:输出mat
- 参数三:只有3种值,小于0,等于0,大于0,分别对应xy轴翻转、x轴翻转、y轴翻转。
代码示例:
cv::flip(srcMat, srcMat, 0);
缩放
缩放函数:cv::resize
该函数为缩放函数,特别注意:函数缩放会失真,尤其是以缩放后的图像继续缩放会原来大小,所以笔者建议,缩放用缓存,缓存存放原图,每次以原图缩放。
该函数原形如下:
CV_EXPORTS_W void resize( InputArray src, OutputArray dst,
Size dsize, double fx = 0, double fy = 0,
int interpolation = INTER_LINEAR );
- 参数一:输入mat
- 参数二:输出mat
- 参数三:缩放后的大小
- 参数四:x缩放比例,一般默认0就可以
- 参数五:y缩放比例,一般默认0就可以
- 参数六:差值,一般默认即可
此处额外介绍下差值的枚举:
enum InterpolationFlags{
INTER_NEAREST = 0, // 最临近差值
INTER_LINEAR = 1, // 双线性差值
INTER_CUBIC = 2, // 双立方差值
INTER_AREA = 3,
INTER_LANCZOS4 = 4, // 附近像素及原像素加权取值
INTER_LINEAR_EXACT = 5,
INTER_MAX = 7,
WARP_FILL_OUTLIERS = 8,
WARP_INVERSE_MAP = 16
};
Demo源码
void OpenCVManager::testCommonOperate()
{
#define TEST_GET_TICK_COUNT (1)
#define TEST_ROTATE_90 (1)
#if TEST_GET_TICK_COUNT // 测试计时函数
for(int index = 0; index < 10; index++)
{
int64 tickCount = cv::getTickCount();
qDebug() << __FUNCTION__ << __LINE__ << "===================== test cv::getTickCount(), now times:" << index;
qDebug() << __FUNCTION__ << __LINE__ << "cv::getTickCount() =" << tickCount;
// Qt的线程睡眠函数
QThread::msleep(200 * index);
int64 tickCount2 = cv::getTickCount();
qDebug() << __FUNCTION__ << __LINE__ << "cv::getTickCount() =" << tickCount2;
int64 ms = ((double)tickCount2 - tickCount) * 1000.0f/ cv::getTickFrequency();
qDebug() << __FUNCTION__ << __LINE__ << "cv::getTickFrequency() =" << (int64)cv::getTickFrequency() << ", ms:" << ms;
}
#endif
#if TEST_ROTATE_90
cv::Mat srcMat;
QString fileName = "D:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/1.jpg";
srcMat = cv::imread(fileName.toStdString());
if(!srcMat.data)
{
qDebug() << __FILE__ << __LINE__ << "Failed to load image:" << fileName;
return;
}
cv::imshow("OpenCVDemo v1.5.0 QQ:21497936 blog:blog.csdn.net/qq21497936", srcMat);
float scaleStep = 0.05f;
while(true)
{
int key = cv::waitKey();
if(key == '1') // 逆时钟旋转90度
{
int64 tickCount = cv::getTickCount();
qDebug() << __FUNCTION__ << __LINE__ << "cv::getTickCount() =" << tickCount;
cv::rotate(srcMat, srcMat, cv::ROTATE_90_COUNTERCLOCKWISE);
int64 tickCount2 = cv::getTickCount();
qDebug() << __FUNCTION__ << __LINE__ << "cv::getTickCount() =" << tickCount2;
int64 ms = ((double)tickCount2 - tickCount) * 1000.0f/ cv::getTickFrequency();
qDebug() << __FUNCTION__ << __LINE__ << "take time ms:" << ms;
cv::imshow("OpenCVDemo v1.5.0 QQ:21497936 blog:blog.csdn.net/qq21497936", srcMat);
}else if(key == '2') // 顺时钟旋转90度
{
int64 tickCount = cv::getTickCount();
qDebug() << __FUNCTION__ << __LINE__ << "cv::getTickCount() =" << tickCount;
cv::rotate(srcMat, srcMat, cv::ROTATE_90_CLOCKWISE);
int64 tickCount2 = cv::getTickCount();
qDebug() << __FUNCTION__ << __LINE__ << "cv::getTickCount() =" << tickCount2;
int64 ms = ((double)tickCount2 - tickCount) * 1000.0f/ cv::getTickFrequency();
qDebug() << __FUNCTION__ << __LINE__ << "take time ms:" << ms;
cv::imshow("OpenCVDemo v1.5.0 QQ:21497936 blog:blog.csdn.net/qq21497936", srcMat);
}else if(key == '3') // x轴翻转(镜像)
{
int64 tickCount = cv::getTickCount();
qDebug() << __FUNCTION__ << __LINE__ << "cv::getTickCount() =" << tickCount;
cv::flip(srcMat, srcMat, 0);
int64 tickCount2 = cv::getTickCount();
qDebug() << __FUNCTION__ << __LINE__ << "cv::getTickCount() =" << tickCount2;
int64 ms = ((double)tickCount2 - tickCount) * 1000.0f/ cv::getTickFrequency();
qDebug() << __FUNCTION__ << __LINE__ << "take time ms:" << ms;
cv::imshow("OpenCVDemo v1.5.0 QQ:21497936 blog:blog.csdn.net/qq21497936", srcMat);
}else if(key == '4') // y轴翻转(镜像)
{
int64 tickCount = cv::getTickCount();
qDebug() << __FUNCTION__ << __LINE__ << "cv::getTickCount() =" << tickCount;
cv::flip(srcMat, srcMat, 1);
int64 tickCount2 = cv::getTickCount();
qDebug() << __FUNCTION__ << __LINE__ << "cv::getTickCount() =" << tickCount2;
int64 ms = ((double)tickCount2 - tickCount) * 1000.0f/ cv::getTickFrequency();
qDebug() << __FUNCTION__ << __LINE__ << "take time ms:" << ms;
cv::imshow("OpenCVDemo v1.5.0 QQ:21497936 blog:blog.csdn.net/qq21497936", srcMat);
}else if(key == '5') // 缩小
{
int64 tickCount = cv::getTickCount();
qDebug() << __FUNCTION__ << __LINE__ << "cv::getTickCount() =" << tickCount;
cv::resize(srcMat, srcMat, cv::Size((int)(srcMat.cols * (1.0f - scaleStep)),
(int)(srcMat.rows * (1.0f - scaleStep))));
int64 tickCount2 = cv::getTickCount();
qDebug() << __FUNCTION__ << __LINE__ << "cv::getTickCount() =" << tickCount2;
int64 ms = ((double)tickCount2 - tickCount) * 1000.0f/ cv::getTickFrequency();
qDebug() << __FUNCTION__ << __LINE__ << "take time ms:" << ms;
cv::imshow("OpenCVDemo v1.5.0 QQ:21497936 blog:blog.csdn.net/qq21497936", srcMat);
}else if(key == '6') // 放大
{
int64 tickCount = cv::getTickCount();
qDebug() << __FUNCTION__ << __LINE__ << "cv::getTickCount() =" << tickCount;
cv::resize(srcMat, srcMat, cv::Size((int)(srcMat.cols * (1.0f + scaleStep)),
(int)(srcMat.rows * (1.0f + scaleStep))));
int64 tickCount2 = cv::getTickCount();
qDebug() << __FUNCTION__ << __LINE__ << "cv::getTickCount() =" << tickCount2;
int64 ms = ((double)tickCount2 - tickCount) * 1000.0f/ cv::getTickFrequency();
qDebug() << __FUNCTION__ << __LINE__ << "take time ms:" << ms;
cv::imshow("OpenCVDemo v1.5.0 QQ:21497936 blog:blog.csdn.net/qq21497936", srcMat);
}
if(key == 27)
{
break;
}
}
#endif
}
工程模板:对应版本号v1.5.0
对应版本号v1.5.0
原博主博客地址:https://blog.csdn.net/qq21497936
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/101168828
转载:https://blog.csdn.net/qq21497936/article/details/101168828