(opencv)图像几何变换——缩放

图像缩放是指将图像的尺寸变小或变大的过程,也就是减少或增加源图像数据的像素个数。图像缩放一定程度上会造成信息的丢失,因此需要考虑适宜的方法进行操作。

下面介绍两种常用的图像缩放方法的原理及实现

1.基于等间隔提取图像缩放

等间隔提取图像缩放是通过对源图像进行均匀采样来完成的。对于源图像数据f(x,y),其分辨率为M*N,如果将其分辨率改变成m*n,对于等间隔采样而言,其宽度缩放因子k1=m/M,高度缩放因子k2=n/N,对于图像而言,图像缩放在其水平方向的等间隔采样为k1,垂直方向上的等间隔采样为k2。若满足k1=k2,源图像数据将等比例缩放,否则源图像数据的宽度和高度将发生不同程度的缩放,造成图像变形扭曲现象

2.基于区域子块图像缩放 

区域子块提取图像缩放是通过对源图像进行区域子块划分,然后提取子块中像素值作为采样像素以构成新图像来实现的。提取子块像素值常用的方法有计算子块像素的中值与计算子块像素的均值。对源图像进行区域划分同样也有多种不同方法,常用方法是根据缩放因子等比例提取子块与自适应因子提取子块,假设源图像数据f(x,y)的分辨率为8*8,图像g(x,y)的分辨率为2*2,则区域子块提取方式如下:

 

子块区域提取后g(x,y)为下式

 

 下面分别实现这两种方式对图像进行缩放

#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
using namespace std;
using namespace cv;

//基于等间隔提取图像缩放
Mat imgReduction1(Mat& src, float kx, float ky)
{
	//获取输出图像分辨率
	int nRows = cvRound(src.rows * kx);
	int nCols = cvRound(src.cols * ky);
	Mat result(nRows, nCols, src.type());
	for (int i = 0; i < nRows; ++i)
	{
		for (int j = 0; j < nCols; ++j)
		{
			//根据水平因子计算坐标
			int x = static_cast<int>((i + 1) / kx + 0.5) - 1;
			//根据垂直因子计算坐标
			int y = static_cast<int>((j + 1) / ky + 0.5) - 1;

			result.at<Vec3b>(i, j) = src.at<Vec3b>(x, y);
		}
	}
	return result;
}

Vec3b areaAverage(const Mat& src, Point_<int> leftPoint, Point_<int> rightPoint)
{
	int temp1 = 0, temp2 = 0, temp3 = 0;
	//计算区域子块像素点个数
	int nPix = (rightPoint.x - leftPoint.x + 1) * (rightPoint.y - leftPoint.y + 1);
	//对于区域子块各个通道对像素值求和
	for (int i = leftPoint.x; i <= rightPoint.x; i++)
	{
		for (int j = leftPoint.y; j <= rightPoint.y; j++)
		{
			temp1 += src.at<Vec3b>(i, j)[0];
			temp2 += src.at<Vec3b>(i, j)[1];
			temp3 += src.at<Vec3b>(i, j)[2];
		}
	}
	//对每个通道求均值
	Vec3b vecTemp;
	vecTemp[0] = temp1 / nPix;
	vecTemp[1] = temp2 / nPix;
	vecTemp[2] = temp3 / nPix;
	return vecTemp;
}

//基于区域子块图像缩放
Mat imgReduction2(const Mat& src, double kx, double ky)
{
	//获取输出图像分辨率
	int nRows = cvRound(src.rows * kx);
	int nCols = cvRound(src.cols * ky);
	Mat result(nRows, nCols, src.type());

	//区域子块的左上角行列坐标
	int leftRowCoordinate = 0;
	int leftColCoordinate = 0;
	for (int i = 0; i < nRows; ++i)
	{
		//根据水平因子计算坐标
		int x = static_cast<int>((i + 1) / kx + 0.5) - 1;
		for (int j = 0; j < nCols; ++j)
		{
			//根据垂直因子计算坐标
			int y = static_cast<int>((j + 1) / kx + 0.5) - 1;
			//求解区域子块的均值
			result.at<Vec3b>(i, j) = areaAverage(src,
				Point_<int>(leftRowCoordinate, leftColCoordinate), Point_<int>(x, y));
			//更新下子块左上角的列坐标,行坐标不变
			leftColCoordinate = y + 1;
		}
		leftColCoordinate = 0;
		//更新下子块左上角的行坐标
		leftRowCoordinate = x + 1;
	}
	return result;
}
int main()
{
	Mat src = imread("C:\\Users\\32498\\Pictures\\16.png");
	if (!src.data)
	{
		return -1;
	}
	imshow("src", src);
	Mat dst1 = imgReduction1(src, 0.5, 0.5);
	imshow("dst1", dst1);
	Mat dst2 = imgReduction2(src, 0.5, 0.5);
	imshow("dst2", dst2);
	waitKey();
	return 0;

}

 

 对代码进行一些注释

  • cvRound():返回跟参数最接近的整数值,即四舍五入;

与之近似的函数还有

  • cvFloor()  :返回不大于参数的最大整数值,即向下取整;
  • cvCeil()    :返回不小于参数的最小整数值,即向上取整;
Point_<int>(x,y)

 opencv中内置了三种二维平面点坐标类型,这就带来一个问题:即我们在编写图像处理算法的时候有时候并不确定调用者需要哪一种坐标点数据类型,只写一种吧可能无法满足需要,三种都分别实现又费时耗力,且没利用好c++多态泛型的特性。而opencv中的模板类cv::Point_刚好可以解决这个问题,实际上以上三种类型的点都是cv::Point_的具体实例化,在opencv里转到定义就可以查看到

typedef Point_<int> Point2i;
typedef Point_<int64> Point2l;
typedef Point_<float> Point2f;
typedef Point_<double> Point2d;
typedef Point2i Point;

point_ 的定义如下:

template<typename _Tp> class Point_
{
public:
    typedef _Tp value_type;

    //! default constructor
    Point_();
    Point_(_Tp _x, _Tp _y);
    Point_(const Point_& pt);
    Point_(const Size_<_Tp>& sz);
    Point_(const Vec<_Tp, 2>& v);

    Point_& operator = (const Point_& pt);
    //! conversion to another data type
    template<typename _Tp2> operator Point_<_Tp2>() const;

    //! conversion to the old-style C structures
    operator Vec<_Tp, 2>() const;

    //! dot product
    _Tp dot(const Point_& pt) const;
    //! dot product computed in double-precision arithmetics
    double ddot(const Point_& pt) const;
    //! cross-product
    double cross(const Point_& pt) const;
    //! checks whether the point is inside the specified rectangle
    bool inside(const Rect_<_Tp>& r) const;
    _Tp x; //!< x coordinate of the point
    _Tp y; //!< y coordinate of the point
};

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/29806.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

机器视觉初步5-1:图像平滑专题

在计算机视觉领域&#xff0c;图像平滑处理是一个重要的任务&#xff0c;用于降低噪声&#xff0c;提高图像质量。常见的图像平滑算法有均值滤波、中值滤波、高斯滤波等。本文将介绍这些算法的原理&#xff0c;并分别给出使用Python与Halcon实现的代码。&#xff08;当前版本&a…

什么是微软的 Application Framework?

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天来看一下什么是微软的 Application Framework&#xff1f; 到底什么是 Application Framework&#xff1f; 我当年学习这个的时候也困惑了好久&#xff0c;于是一直在搜索这个概念有没有好的解释&#…

ChatGPT时代:ChatGPT全能应用一本通

引言 随着人工智能技术的不断发展和进步&#xff0c;我们进入了ChatGPT时代。ChatGPT是基于GPT架构的大型语言模型&#xff0c;它具备强大的自然语言处理和生成能力&#xff0c;使得我们能够进行更加自由、流畅的对话。作为ChatGPT的全能应用&#xff0c;它可以被视为一本通&a…

【性能优化】性能优化

❤️ Author&#xff1a; 老九 ☕️ 个人博客&#xff1a;老九的CSDN博客 &#x1f64f; 个人名言&#xff1a;不可控之事 乐观面对 &#x1f60d; 系列专栏&#xff1a; 文章目录 性能优化运行效率加载效率减少HTTP请求数量使用CDN缓存压缩文件、混淆样式表放在顶部、js代码放…

广告数仓:采集通道创建

系列文章目录 广告数仓&#xff1a;采集通道创建 文章目录 系列文章目录前言一、环境和模拟数据准备1.hadoop集群2.mysql安装3.生成曝光测试数据 二、广告管理平台数据采集1.安装DataX2.上传脚本生成器3.生成传输脚本4.编写全量传输脚本 三、曝光点击检测数据采集1.安装Zookee…

大数据周会-本周学习内容总结018

开会时间&#xff1a;2023.06.18 15:00 线下会议 01【调研-数据分析&#xff08;质量、ETL、可视化&#xff09;】 ETL&#xff0c;是英文Extract-Transform-Load的缩写&#xff0c;用来描述将数据从来源端经过抽取&#xff08;extract&#xff09;、转换&#xff08;transform…

开源游戏区块链项目分享:Unity开发的独立区块链

Arouse Blockchain [Unity独立区块链] ❗️千万别被误导&#xff0c;上图内容虽然都在项目中可寻&#xff0c;但与目前区块链的业务代码关联不大&#xff0c;仅供宣传作用(总得放些图看着好看)。之所以有以上内容是项目有个目标功能是希望每个用户在区块链上都有一个独一无二的…

如何看待 Facebook 上线支付功能?

随着科技的不断进步&#xff0c;电子支付在我们的生活中变得越来越普遍。最近&#xff0c;Facebook宣布推出自己的支付功能&#xff0c;这引起了广泛的关注和讨论。作为世界上最大的社交媒体平台之一&#xff0c;Facebook进入支付领域的举措无疑具有重要意义。那么&#xff0c;…

13年测试老鸟,带你详探服务端的接口测试,测试内卷之路...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 服务器的接口测试…

数据库第三章(SQL)

目录 1.SQL语言 索引 1.SQL语言 sql语言是个非过程性语言 sql的特点 1.综合统一&#xff0c;把增删查改都统一了起来 2.高度非过程化&#xff0c;不关心过程 3.面向集合的操作方式 sql基本语法 drop是删除表 delete是删除表的某个元组 安全方面&#xff1a;grant授权 revo…

EXCEL函数笔记1(数学函数、文本函数、日期函数)

数学函数 取整&#xff1a;INT(number) 取余&#xff1a;MOD(number,除数) 四舍五入&#xff1a;ROUND(number&#xff0c;保留几位小数) 取绝对值&#xff1a;ABS(number) 根号处理&#xff1a;SQRT&#xff08;number&#xff09; 0到1随机数&#xff1a;RAND&#xff08;&am…

【机器学习】十大算法之一 “朴素贝叶斯”

作者主页&#xff1a;爱笑的男孩。的博客_CSDN博客-深度学习,活动,python领域博主爱笑的男孩。擅长深度学习,活动,python,等方面的知识,爱笑的男孩。关注算法,python,计算机视觉,图像处理,深度学习,pytorch,神经网络,opencv领域.https://blog.csdn.net/Code_and516?typeblog个…

【LeetCode】每日一题 -- 1171. 从链表中删去总和值为零的连续节点 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/remove-zero-sum-consecutive-nodes-from-linked-list/ 1. 题解&#xff08;1171. 从链表中删去总和值为零的连续节点&#xff09; 2021年字节二面真题 1.1 暴力解法&#xff1a;穷举 时间复杂度 O(n2)&#xff0c;空间复杂…

【论文】attention is all you need

重点在第三节 attention is all you need摘要1. 绪论2. 背景3. 模型架构3.1 编码器和解码器堆叠 3.2 注意力3.2.1 缩放点积注意力&#xff08;Scaled Dot-Product Attention&#xff09;3.2.2 多头注意力机制3.2.3 模型中注意力的应用 3.3 职位感知前馈网络&#xff08;Positio…

前端中间件Midway的使用

一、 关于midway1. 解决什么痛点2. 期望达到什么效果 二、创建应用并使用1. 创建midway应用2. 认识Midway2.1 目录结构2.2 Controller2.3 路由2.4 获取请求参数2.5 Web中间件2.6 组件使用2.7 服务(service) 三、写到最后 一、 关于midway Midway 是阿里巴巴 - 淘宝前端架构团队…

基于深度学习的高精度安全背心检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度安全背心检测识别系统可用于日常生活中或野外来检测与定位安全背心目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的安全背心目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5…

微服务: 01-rabbitmq的应用场景及安装(docker)

目录 1. rabbitmq前言简介: 1.1 RabbitMQ的几个重要作用&#xff1a; -> 1.1.1 解耦&#xff1a; -> 1.1.2 异步通信&#xff1a; -> 1.1.3 流量削峰&#xff1a; -> 1.1.4 消息传递的可靠性和持久性&#xff1a; 2. rabbitmq的安装(docker版) -> 2.1 …

SpringMVC 学习整理

文章目录 一、SpringMVC 简介1.1 什么是MVC1.2 什么是Spring MVC1.3 Spring MVC的特点 二、SpringMVC 快速入门三、RequestMapping注解说明四、SpringMVC获取请求参数4.1 通过ServletAPI获取请求参数4.2 通过控制器方法的形参获取请求参数4.3 通过RequestParam接收请求参数4.4 …

Rust语言从入门到入坑——(2)Rust在windows上搭建开发环境

文章目录 0 引入1、搭建 Visual Studio Code 开发环境1.1、安装 Rust 编译工具1.2 、VS Code安装 2、官网在线3、总结4、引用 0 引入 开始搭建一个适合在windows上运行的Rust环境。 Rust支持的程序语言很多&#xff1a;可详见官网介绍 1、搭建 Visual Studio Code 开发环境 …

[架构之路-211]- 需求- 软架构前的需求理解:ADMEMS标准化、有序化、结构化、层次化需求矩阵 =》需求框架

目录 前言&#xff1a; 一、什么是ADMES: 首先&#xff0c;需求是分层次的&#xff1a; 其次&#xff0c;需求是有结构的&#xff0c;有维度的 再次&#xff0c;不同层次需求、不同维度需求之间可以相互转化&#xff08;难点、经验积累&#xff09; 最终&#xff0c;标准…
最新文章