7.1图像平移

news2024/11/16 23:43:24

目录

实验原理

示例代码1

运行结果1

示例代码2

运行结果2


实验原理

OpenCV中,图像平移是一种基本的几何变换,指的是将图像中的每一个像素点沿着水平方向或垂直方向移动一定的距离。图像平移不改变图像的大小和形状,只是改变了图像的位置。在计算机视觉和图像处理领域,平移操作可以用于数据增强、图像对齐等任务。

在OpenCV中,可以通过仿射变换(Affine Transformation)来实现图像的平移。

图像平移的原理图像平移实际上是一种特殊的仿射变换,其中不涉及旋转或缩放,只是简单地将图像沿水平或垂直方向移动一段固定的距离。

仿射变换的应用仿射变换可以用于多种几何变换,

例如:

•平移:只需要修改矩阵中的tx和ty值即可。

•旋转:需要构造一个包含旋转角度的矩阵。

•缩放:通过调整矩阵中的a和d值来控制水平和垂直方向的缩放比例。

•倾斜:通过调整矩阵中的b和c值来控制剪切(shear)效果。

要使用OpenCV进行图像平移,可以通过以下步骤实现:

1.定义平移矩阵: 

2.应用平移变换

使用 cv::warpAffine 函数可以应用这个变换到图像上。首先需要创建一个与上述形式一致的平移矩阵,然后使用该函数完成平移操作。

cv::warpAffine 是 OpenCV 库中用于执行仿射变换的一个函数,它可以实现图像的旋转、缩放、剪切以及平移等操作。其函数原型如下:

void warpAffine(
    InputArray src,            // 输入图像
    OutputArray dst,           // 输出图像
    InputArray M,              // 2x3 的变换矩阵  仿射变换矩阵
    Size dsize,                // 输出图像的大小
    int flags = INTER_LINEAR,  // 插值方法,默认为双线性插值
    int borderMode = BORDER_CONSTANT, // 边界模式
    const Scalar& borderValue = Scalar() // 边界填充值
);

函数参数说明:
•src:输入图像,可以是任何类型的单通道或多通道图像。
•dst:输出图像,与输入图像具有相同的类型,大小由dsize参数指定。
•M:仿射变换矩阵,通常是一个2x3的浮点矩阵。这个矩阵包含仿射变换所需的六个参数。
•dsize:输出图像的大小。可以指定为Size(width, height)形式或者使用 src.size() 保持与源图像相同的大小。
•flags:插值方法,默认为INTER_LINEAR(双线性插值)。
    其他可选的插值方法包括: 
    •INTER_NEAREST:最近邻插值。
    •INTER_LINEAR:双线性插值。
    •INTER_CUBIC:三次样条插值。
    •INTER_LANCZOS4:兰茨科斯插值。
•borderMode:边界处理模式,默认为BORDER_CONSTANT(用常数值填充边界)。
    其他可选的边界处理模式包括: 
    •BORDER_CONSTANT:用常数值填充边界。
    •BORDER_REPLICATE:边界像素值向外复制。
    •BORDER_REFLECT:边界像素值向内反射。反射边界,如12345反射为45454。
    •BORDER_WRAP:边界像素值循环。循环边界,如12345循环为34512。
    •borderValue:边界填充值,默认为黑色(全零向量)。
   只有在borderMode为BORDER_CONSTANT时有效。

总结

图像平移是通过仿射变换来实现的,它涉及到将图像中的每一个像素按照一定的方向和距离移动到新的位置。在OpenCV中,可以通过构建一个2x3的仿射变换矩阵,并使用cv::warpAffine函数来实现图像的平移。通过调整平移参数tx和ty,可以控制图像在水平方向和垂直方向的平移量。此外,还可以通过指定不同的边界处理方式来处理平移后超出原图像范围的情况。

示例代码1

#include "pch.h"
#include <opencv2/opencv.hpp>
#include <iostream>

int main(int argc, char** argv)
{
	// 加载图像
	cv::Mat img = cv::imread("B3.png");
	if (img.empty())
	{
		std::cout << "Error: Image not found." << std::endl;
		return -1;
	}

	// 定义平移的距离
	int tx = 30; // 沿x轴平移30个像素
	int ty = -70; // 沿y轴平移-70个像素(向上)

	// 创建平移矩阵
	cv::Mat translationMatrix = (cv::Mat_<double>(2, 3) <<
		1, 0, tx,
		0, 1, ty);

	// 应用平移变换
	cv::Mat translatedImg;
	cv::warpAffine(img, translatedImg, translationMatrix, img.size());

	// 显示原图和翻译后的图像
	cv::namedWindow("Original Image", cv::WINDOW_NORMAL);
	cv::imshow("Original Image", img);
	cv::namedWindow("Translated Image", cv::WINDOW_NORMAL);
	cv::imshow("Translated Image", translatedImg);
	cv::waitKey(0);

	return 0;
}

在这个例子中,我们加载了一张图片,
并定义了一个平移矩阵 translationMatrix。
接着我们使用 cv::warpAffine 函数,
输入原始图像、平移矩阵以及输出图像的尺寸(在这里我们保持了原始图像的大小)。
最后,我们显示原图和平移后的图像,并等待用户按键退出。

运行结果1

示例代码2

// test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <iostream>

//#pragma comment(lib, "opencv_world450d.lib")  //引用引入库 

//平移操作,图像大小不变
cv::Mat imageTranslation1(cv::Mat & srcImage, int x0ffset, int y0ffset)
{
	int nRows = srcImage.rows;
	int nCols = srcImage.cols;
	cv::Mat resultImage(srcImage.size(), srcImage.type());
	//遍历图像
	for (int i = 0; i < nRows; i++)
	{
		for (int j = 0; j < nCols; j++)
		{
		
			int x = j - x0ffset;
			int y = i - y0ffset;
			//边界判断
			if (x >= 0 && y >= 0 && x < nCols && y < nRows)
			{
				resultImage.at<cv::Vec3b>(i, j) = srcImage.ptr<cv::Vec3b>(y)[x]; 
			}
		}
	}
	return resultImage;
}
//平移操作,图形大小改变
cv::Mat imageTranslation2(cv::Mat & srcImage, int x0ffset, int y0ffset)
{
	//设置平移尺寸
	int nRows = srcImage.rows + abs(y0ffset);
	int nCols = srcImage.cols + abs(x0ffset);
	cv::Mat resultImage(nRows, nCols, srcImage.type());
	//图像遍历
	for (int i = 0; i < nRows; i++)
	{
		for (int j = 0; j < nCols; j++)
		{
			int x = j - x0ffset;
			int y = i - y0ffset;
			//边界判断
			if (x >= 0 && y >= 0 && x < nCols && y < nRows)
			{
				resultImage.at<cv::Vec3b>(i, j) = srcImage.ptr<cv::Vec3b>(y)[x]; 
			}
		}
	}
	return resultImage;
}

int main()
{
	//读取图像
	cv::Mat srcImage = cv::imread("02.jpeg");
	if (srcImage.empty())
	{
		return -1;
	}

	//显示原图像
	cv::namedWindow("原图", CV_WINDOW_NORMAL);
	cv::imshow("原图", srcImage);
	int x0ffset = 50;
	int y0ffset = 80;
	cv::Mat resultImage1 = imageTranslation1(srcImage, x0ffset, y0ffset);
	cv::namedWindow("移动1", CV_WINDOW_NORMAL);
	cv::imshow("移动1", resultImage1);

	cv::Mat resultImage2 = imageTranslation2(srcImage, x0ffset, y0ffset);
	cv::namedWindow("移动3", CV_WINDOW_NORMAL);
	cv::imshow("移动3", resultImage1);

	x0ffset = -50;
	y0ffset = -80;
	cv::Mat resultImage3 = imageTranslation1(srcImage, x0ffset, y0ffset);
	cv::namedWindow("移动2", CV_WINDOW_NORMAL);
	cv::imshow("移动2", resultImage3);
	cv::waitKey(0);
	return 0;
}

运行结果2

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++位图的实现与详解

1.位图概念 在讲解位图之前我们先来看一道很经典的面试题。 给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一个数是否在这40亿个数中。 我们有以下两种种解决方法&#xff1a; 1. 遍历&#xff0c;时间复杂度O(N)。&#xff0…

如何在红米手机中恢复已删除的照片?(6 种方式可供选择)

凭借出色的相机和实惠的价格&#xff0c;小米红米系列已成为全球知名品牌。但是&#xff0c;最近有些人抱怨他们在 红米设备上丢失了许多珍贵的图片或视频&#xff0c;并希望弄清楚如何从小米手机恢复已删除的照片。好吧&#xff0c;在小米设备上恢复已删除的视频/照片并不难。…

RK3576芯片在智能家居里中型智慧屏产品的应用方案分析

智能家居在近年来得到了快速发展&#xff0c;AI技术不断发展&#xff0c;人机交互十分成熟&#xff0c;各种家电也都迎来了智能化浪潮&#xff0c;智能家居为人们提供了优秀的产品体验&#xff0c;受到主流消费者的青睐&#xff0c;智能家居里的中型智慧屏产品也随之兴起。 瑞芯…

HTTrack

--不破不立 HTTrack 是一个免费开源的网站离线浏览器。通过它可以将整个网站下载到本地的某个目录&#xff0c;包括 html、图片和脚本以及样式文件&#xff0c;并对其中的链接进行重构以便于在本地进行浏览。 1.官网下载地址&#xff1a;https://www.httrack.com/page/2/en/in…

通信工程学习:什么是FMC固定移动融合

FMC&#xff1a;固定移动融合 FMC固定移动融合&#xff0c;即Fixed Mobile Convergence&#xff08;固定移动网络融合&#xff09;&#xff0c;是指通过固定网络与移动网络之间的融通、合作&#xff0c;实现全业务及融合业务的经营。这一技术旨在打破传统固定网络和移动网络之间…

设计模式-面试题(工厂方法模式、策略模式和责任链模式)

开闭原则&#xff1a;扩展开放、修改关闭 工厂设计模式&#xff1a;解耦 简单工厂模式 CoffeeStore和SimpleCoffeeFactory的耦合、SimpleCoffeeFactory和Coffee的耦合 后续如果再加新品种的咖啡&#xff0c;需要修改SimpleCoffeeFactory&#xff0c;这样就违反了开闭原则 简单…

探探我对测试开发的看法?

测试开发岗位主要负责确保软件的可用性和稳定性。 ● 可用性不仅包括功能的正常使用&#xff0c;还涵盖了软件在不同环境下的兼容性&#xff0c;如各种网络环境、不同 CPU 核心环境以及多样化的移动端设备等。 ● 稳定性方面我的理解是&#xff0c;测试人员不仅要从用户角度评判…

Mac无法安装软件怎么解决?mac安装软件提示无法验证开发者怎么办

在使用 macOS 系统时&#xff0c;你可能会遇到一个常见的问题&#xff1a;当你尝试安装或打开某些应用程序时&#xff0c;系统会弹出一个警告&#xff0c;提示“无法验证开发者”。出现这个提示导致自己无法去进行程序安装&#xff0c;接下来我们就来看看如何解决此问题的方法吧…

windows下载nvm并使用合集

下载nvm之前是要把node卸载的&#xff0c;不然会安装不成功 下面我先把nvm地址放上NVM下载 - NVM中文网 按照步骤按照完了一会可以使用一下命令来检查是否安装成功 nvm 安装成功后会出来版本号 下面开始安装node版本&#xff0c;很多朋友一上来直接下载node会报错 问题分析 …

【C++】_list常用方法解析及模拟实现

相信自己的力量&#xff0c;只要对自己始终保持信心&#xff0c;尽自己最大努力去完成任何事&#xff0c;就算事情最终结果是失败了&#xff0c;努力了也不留遗憾。&#x1f493;&#x1f493;&#x1f493; 目录 ✨说在前面 &#x1f34b;知识点一&#xff1a;什么是list&…

【EST】:Pt/ZrO2单原子催化剂

摘要&#xff1a;制备稳定的单原子催化剂一直是环境催化领域去除各种污染物的研究热点&#xff0c;但在提高反应性和稳定性方面仍存在挑战。在此&#xff0c;通过在锆氧化物负载的铂催化剂&#xff08;Pt–Na/ZrO2&#xff09;中简单掺杂碱金属&#xff0c;成功制备了与碱金属通…

【C++初阶】:C++入门,引用概念及其性质

文章目录 一、引用的概念二、引用的语法规则1、引用特性2、常引用 二、引用的使用场景1. 引用做参数2. 引用做返回值 三、引用和指针的区别 一、引用的概念 首先明确一下&#xff0c;引用不是定义一个新的变量&#xff0c;而是给已经存在的变量起一个别名&#xff0c;变量和他…

相机内存卡格式化了照片怎么恢复?格式化恢复详解

摄影爱好者们都知道&#xff0c;相机内存卡是记录我们美好瞬间的重要媒介。然而&#xff0c;在使用过程中&#xff0c;有时我们会因操作不当或设备故障&#xff0c;不小心格式化了内存卡&#xff0c;从而导致珍贵的照片丢失。面对这种情况&#xff0c;我们该如何恢复这些被格式…

贪吃蛇项目实现(C语言)——附源码

前言 贪吃蛇是一款十分经典的游戏&#xff0c;其通过控制贪吃蛇的上下左右移动来吃食物&#xff0c;延长自己的身体&#xff0c;也会因为撞到墙体和自身而死亡。下面我们通过C语言来实现贪吃蛇。 1.技术要点 C语言枚举&#xff0c;结构体&#xff0c;链表&#xff0c;动态内…

内网中的RDP利用

学习参考 https://www.freebuf.com/articles/network/276242.html能跟着实操的都实操一下。熟悉一些命令&#xff0c;过程。 实验环境&#xff1a;win2008&#xff0c;192.168.72.139 两个用户&#xff1a; administrator&#xff0c;shizuru RDP服务 确定/开启 RDP服务确…

力扣第79题 单词搜索

前言 记录一下刷题历程 力扣第79题 单词搜索 单词搜索 原题目&#xff1a;给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按照字母顺序&#xff0c;通过相邻…

解决ubuntu安装modelsim20.1 32位库依赖失败问题(附简易安装方法)

先说方法&#xff1a;不用管&#xff0c;直接继续安装软件就行。 注意&#xff0c;选中 libgtk-3-0t64:i386 而非 libgtk-3-0:i386 注意&#xff0c;选中 libcanberra0t64:i386 而非 libcanberra0:i386 注意&#xff0c;选中 libpng16-16t64:i386 而非 libpng16-16:i386 注意&…

白盒测试_学习总结

目录 一、白盒测试的概念理解 二、白盒测试的分类 1、静态分析 2、动态分析 &#xff08;1&#xff09;逻辑覆盖测试 a、语句覆盖 b、判定覆盖 c、条件覆盖 d、判定条件覆盖 e、条件组合覆盖 f、路径覆盖 &#xff08;2&#xff09;基本路径测试法 3、总结 一、白盒…

Arduino基础入门学习——BH1750(GY-302)+ LED模拟自动路灯的实现

BH1750&#xff08;GY-302&#xff09; LED 一、前言三、准备工作四、程序代码五、运行结果六、结束语 一、前言 相信很多人都见过一种路灯&#xff0c;白天的时候它是不亮的&#xff0c;等到了晚上环境变暗时就开始它的照明工作了&#xff0c;不了解的人可能认为是人为操纵它工…

如何编写Prompt,利用AI高效生成图表——图表狐(FoxChart)指南

在数据可视化领域&#xff0c;图表是数据的重要表达方式。为了让更多人能够轻松高校地生成美观、专业的图表&#xff0c;图表狐(FoxChart)应用而生。然而&#xff0c;要想充分发挥AI的潜力&#xff0c;编写合适的Prompt至关重要。本文介绍一些编写Prompt的原则&#xff0c;帮助…