【图像处理】-007 几何变换-平移、镜像、转置

2024-01-15 11:20

本文主要是介绍【图像处理】-007 几何变换-平移、镜像、转置,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

几何变换-平移、镜像、转置

文章目录

  • 1 向前映射与向后映射
    • 1.1 向前映射
    • 1.2 向后映射
    • 1.3 适用性
  • 2 几何变换的数学描述
  • 3 平移
    • 3.1 平移矩阵
    • 3.2 OpenCV实现
    • 3.3 Matlab实现
  • 4 镜像
    • 4.1 变换矩阵
    • 4.2 OpenCV实现
    • 4.3 Matlab实现
  • 5 转置
    • 5.1 转置矩阵
    • 5.2 OpenCV实现
    • 5.3 Matlab实现

  图像的几何变换是在不改变图像内容的前提下对图像像素进行相对空间位置移动的一种处理方式,主要包括平移、镜像、转置、缩放和旋转。

1 向前映射与向后映射

1.1 向前映射

  图像几何变换用于改变图像中像素与像素之间的空间关系,从而重构图像的空间结构,达到处理图像的目的。图像几何变换就是建立一种源图像像素与变换后图像像素之间的映射关系。通过这种映射关系能够知道源图像任意像素点变换后的坐标,或者变换后图像像素在源图像中的坐标位置,数学描述如下:
{ x = U ( x 0 , y 0 ) y = V ( x 0 , y 0 ) \begin{cases} x&=&U(x_{0},y_{0})\\ &&&&\\ y&=&V(x_{0},y_{0})& \end{cases} xy==U(x0,y0)V(x0,y0)
其中, x x x y y y表示输出图像像素的坐标, x 0 x_0 x0 y 0 y_0 y0表示输入图像像素的坐标,而 U U U V V V表示两种映射关系,通过输入的 x 0 x_0 x0 y 0 y_0 y0来确定相应的 x x x y y y

  只要给出了图像上任意像素的坐标,都能通过对应的映射关系获得几何变换后的像素坐标位置。这种将输入映射到输出的过程成为向前映射
  通过向前映射能够确定源图像在经过变换后各像素的坐标由于多个输入坐标可以对应同一个输出坐标,所以向前映射是一个满射。

在这里插入图片描述

  向前映射主要存在以下问题:

  • a) 浮点数坐标
      数字图像像素坐标是用离散的非负整数表示的,但通过向前映射函数变换后可能产生浮点数的坐标,此时难以确定输出像素的坐标。
  • b) 映射不完全和映射重叠
    • (1) 映射不完全
         映射不完全指输入图像的像素总数小于输出图像的像素总数,这会使得输出图像的部分像素与原始图像没有映射关系。
    • (2) 映射重叠
        映射重叠指输入图像中的多个像素,经过变换之后对应到输出图像中的同一个位置,此时难以确定输出像素应该使用那个像素值。

1.2 向后映射

  向后映射的数学表示如下:
{ x 0 = U ′ ( x , y y 0 = V ′ ( x , y ) \begin{cases} x_0&=&U^{'}(x,y\\ &&&&\\ y_0&=&V^{'}(x,y)& \end{cases} x0y0==U(x,yV(x,y)
其中, x x x y y y表示输出图像像素的坐标, x 0 x_0 x0 y 0 y_0 y0表示输入图像像素的坐标,而 U ′ U^{'} U V ′ V^{'} V表示两种映射关系,通过输出的 x x x y y y来确定相应的 x 0 x_0 x0 y 0 y_0 y0

向后映射与向前映射相反,通过输出图像像素坐标反过来推算该像素在源图像的坐标位置,输出图像的每一个像素都能通过映射找到对应的位置,而不会产生映射不完全和映射重叠的问题。

在这里插入图片描述

1.3 适用性

  向前映射有效率偏低、映射不完全等缺点,但在一些不改变图像大小的几何变换中,向前映射仍然可用。向后映射主要运用图像的旋转和缩放中,这些几何变换都改变了图像的大小,运用向后映射可以有效的解决大小改变产生的各类映射问题。

2 几何变换的数学描述

  由于几何变换都具有统一的形式,可以记为:

[ x y 1 ] = [ x 0 y 0 1 ] [ a 1 a 2 0 a 3 a 4 0 a 5 a 6 1 ] [x \space y \space 1]=[x_{0} \space y_{0} \space 1]\begin{bmatrix} a_1&a_2&0\\ a_3&a_4&0\\ a_5&a_6&1\\ \end{bmatrix} [x y 1]=[x0 y0 1]a1a3a5a2a4a6001
  这就是向前映射的矩阵表示法。

[ x 0 y 0 1 ] = [ x y 1 ] [ b 1 b 2 0 b 3 b 4 0 b 5 b 6 1 ] [x_0 \space y_0 \space 1]=[x \space y \space 1]\begin{bmatrix} b_1&b_2&0\\ b_3&b_4&0\\ b_5&b_6&1\\ \end{bmatrix} [x0 y0 1]=[x y 1]b1b3b5b2b4b6001
  这是向后映射的矩阵表示。
  可以看出,向后映射的矩阵表示正好是向前映射的矩阵表示的逆变换。

3 平移

3.1 平移矩阵

  图像的平移变换是将图像中所有像素的坐标分别加上或减去指定的水平偏移量和垂直偏移量,从而使整张图出现位移效果。
  设 d x dx dx为水平偏移量, d y dy dy为垂直偏移量,则平移变换的向后映射关系为:

[ x 0 y 0 1 ] = [ x y 1 ] [ 1 0 0 0 1 0 − d x − d y 1 ] [x_0 \space y_0 \space 1]=[x \space y \space 1]\begin{bmatrix} 1&0&0\\ 0&1&0\\ -dx&-dy&1\\ \end{bmatrix} [x0 y0 1]=[x y 1]10dx01dy001

3.2 OpenCV实现

  对于图像平移操作,这里我借助OpenCV所提供的进行图像矩阵变换的函数cv::warpAffine函数来实现,该函数能够根据输入图像和变换矩阵,得出变换后的图像结果。所以,我们将重点放在如何生成变换矩阵上。

void CreateTranslateMatrix(float fXOffset, float fYOffset, cv::Mat& mat)
{mat = cv::Mat::zeros(2, 3, CV_32F);mat.at<float>(0, 0) = 1;mat.at<float>(0, 2) = -fXOffset; //水平平移量mat.at<float>(1, 1) = 1;mat.at<float>(1, 2) = -fYOffset; //竖直平移量
}//具体使用cv::Mat mat_translate;float fXOffset = 5;float fYOffset = 10;CreateTranslateMatrix(-50, 100, mat_translate);cv::Mat res_translate;cv::warpAffine(srcimg, res_translate, mat_translate, srcimg.size(),cv::INTER_LINEAR|cv::WARP_INVERSE_MAP);cv::imshow("res_translate", res_translate);

注意,cv::warpAffine要求变换矩阵为2×3的矩阵。
将原图向右水平平移50像素,向下垂直平移100像素之后的结果如下图所示。
在这里插入图片描述

3.3 Matlab实现

%% 图像平移
xoffset = 100;
yoffset = 50;
res_translate = zeros(size(srcimg));
res_translate = uint8(res_translate);
for i = 1:1:heightfor j = 1:1:widthx =j - xoffset;y = i - yoffset;if x > 0 && x <=width  && y > 0 && y <= heightres_translate(i,j,:)=srcimg(y,x,:);endend
end
figure(1),imshow(res_translate);

将原图向右水平平移50像素,向下垂直平移100像素之后的结果如下图所示。
在这里插入图片描述

4 镜像

4.1 变换矩阵

  图像镜像效果分为水平镜像和垂直镜像,水平镜像是将图像以图像垂直中线为周,将图像的所有像素对换;垂直镜像是将图像以图像水平中线为轴,将图像所有像素对换。
  设图像宽度为 w i d t h width width,高度为 h e i g h t height height,那么图像水平镜像的向前映射关系为
{ x = w i d t h − x 0 − 1 y = y 0 \begin{cases} x&amp;=&amp;width-x_{0}-1\\ &amp;&amp;&amp;&amp;\\ y&amp;=&amp;y_0&amp; \end{cases} xy==widthx01y0
那么水平镜像的向后映射矩阵表示为:
[ x 0 y 0 1 ] = [ x y 1 ] [ − 1 0 0 0 1 0 w i d t h − 1 0 1 ] [x_0 \space y_0 \space 1]=[x \space y \space 1]\begin{bmatrix} -1&amp;0&amp;0\\ 0&amp;1&amp;0\\ width-1&amp;0&amp;1\\ \end{bmatrix} [x0 y0 1]=[x y 1]10width1010001
  对于垂直镜像,同样可以得到它的变换关系和矩阵表达式:
{ x = x 0 y = h e i g h t − y 0 − 1 \begin{cases} x&amp;=&amp;x_{0}\\ &amp;&amp;&amp;&amp;\\ y&amp;=&amp;height-y_0-1&amp; \end{cases} xy==x0heighty01
那么水平镜像的向后映射矩阵表示为:
[ x 0 y 0 1 ] = [ x y 1 ] [ 1 0 0 0 − 1 0 0 h e i g h t − 1 1 ] [x_0 \space y_0 \space 1]=[x \space y \space 1]\begin{bmatrix} 1&amp;0&amp;0\\ 0&amp;-1&amp;0\\ 0&amp;height-1&amp;1\\ \end{bmatrix} [x0 y0 1]=[x y 1]10001height1001

4.2 OpenCV实现

//创建水平镜像变换矩阵
void CreateMirrorXMatrix(cv::Mat& img, cv::Mat& mat)
{int width = img.cols;mat = cv::Mat::zeros(2, 3, CV_32F);mat.at<float>(0, 0) = -1;mat.at<float>(0, 2) = width-1; mat.at<float>(1, 1) = 1;mat.at<float>(1, 2) = 0; 
}
//创建垂直镜像变换矩阵
void CreateMirrorYMatrix(cv::Mat& img, cv::Mat& mat)
{int height = img.rows;mat = cv::Mat::zeros(2, 3, CV_32F);mat.at<float>(0, 0) = 1;mat.at<float>(0, 2) = 0;mat.at<float>(1, 1) = -1;mat.at<float>(1, 2) = height-1;
}//调用过程如下cv::Mat mat_XMirror;CreateMirrorXMatrix(srcimg, mat_XMirror);cv::Mat res_XMirror;cv::warpAffine(srcimg, res_XMirror, mat_XMirror, srcimg.size(),cv::INTER_LINEAR|cv::WARP_INVERSE_MAP);cv::imshow("res_XMirror", res_XMirror);cv::Mat mat_YMirror;CreateMirrorYMatrix(srcimg, mat_YMirror);cv::Mat res_YMirror;cv::warpAffine(srcimg, res_YMirror, mat_YMirror, srcimg.size(),cv::INTER_LINEAR|cv::WARP_INVERSE_MAP);cv::imshow("res_YMirror", res_YMirror);

在这里插入图片描述

4.3 Matlab实现

%% 镜像
res_XMirror =srcimg;
for i = 1:1:widthif i < width-itemp = res_XMirror(:,i,:);res_XMirror(:,i,:)=res_XMirror(:,width - i,:);res_XMirror(:,width - i,:)=temp;elsebreak;end
end
figure(3),imshow(res_XMirror),title('水平镜像结果图');
res_YMirror =srcimg;
for i = 1:1:heightif i < height-itemp = res_YMirror(i,:,:);res_YMirror(i,:,:)=res_YMirror(height-i,:,:);res_YMirror(height-i,:,:)=temp;elsebreak;end
end
figure(4),imshow(res_YMirror),title('垂直镜像结果图');

在这里插入图片描述

5 转置

5.1 转置矩阵

  图像转置是将图像的横坐标和纵坐标交换位置,转置的操作会使图像的宽度和高度互换。映射矩阵如下:
[ x 0 y 0 1 ] = [ x y 1 ] [ 0 1 0 1 0 0 0 0 1 ] [x_0 \space y_0 \space 1]=[x \space y \space 1]\begin{bmatrix} 0&amp;1&amp;0\\ 1&amp;0&amp;0\\ 0&amp;0&amp;1\\ \end{bmatrix} [x0 y0 1]=[x y 1]010100001

5.2 OpenCV实现

两种实现方式,第一种,按照常规套路,创建转置变换矩阵,然后进行变换。注意调用cv::warpAffine时的第四个参数,该参数指定了输出图像的大小,转置操作需要对原图的长宽互换。

//创建图像转矩矩阵
void CreateTransPositionMatrix(cv::Mat& mat)
{mat = cv::Mat::zeros(2, 3, CV_32F);mat.at<float>(0, 0) = 0;mat.at<float>(0, 1) = 1;mat.at<float>(1, 0) = 1;mat.at<float>(1, 1) = 0;
}cv::Mat mat_transposition;CreateTransPositionMatrix(mat_transposition);cv::Mat res_transposition1;cv::warpAffine(srcimg, res_transposition1, mat_transposition, cv::Size(srcimg.rows, srcimg.cols),cv::INTER_LINEAR|cv::WARP_INVERSE_MAP);

第二种,直接将表示图像的矩阵转置。

	cv::Mat res_transposition2;res_transposition2 = srcimg.t();

在这里插入图片描述

5.3 Matlab实现

  对于多通道图像,无法直接使用MATLAB的转置功能,因此分通道进行转置。

%% 转置
res_transposition = zeros(width,height,3);
res_transposition(:,:,1) = srcimg(:,:,1)';
res_transposition(:,:,2) = srcimg(:,:,2)';
res_transposition(:,:,3) = srcimg(:,:,3)';
res_transposition = uint8(res_transposition);
figure(5),imshow(res_transposition),title('转置结果图');

在这里插入图片描述

这篇关于【图像处理】-007 几何变换-平移、镜像、转置的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/608717

相关文章

参会邀请 | 第二届机器视觉、图像处理与影像技术国际会议(MVIPIT 2024)

第二届机器视觉、图像处理与影像技术国际会议(MVIPIT 2024)将于2024年9月13日-15日在中国张家口召开。 MVIPIT 2024聚焦机器视觉、图像处理与影像技术,旨在为专家、学者和研究人员提供一个国际平台,分享研究成果,讨论问题和挑战,探索前沿技术。诚邀高校、科研院所、企业等有关方面的专家学者参加会议。 9月13日(周五):签到日 9月14日(周六):会议日 9月15日(周日

OpenStack镜像制作系列5—Linux镜像

本系列文章主要对如何制作OpenStack镜像的过程进行描述记录 CSDN:OpenStack镜像制作教程指导(全) OpenStack镜像制作系列1—环境准备 OpenStack镜像制作系列2—Windows7镜像 OpenStack镜像制作系列3—Windows10镜像 OpenStack镜像制作系列4—Windows Server2019镜像 OpenStack镜像制作

OpenStack镜像制作系列4—Windows Server2019镜像

本系列文章主要对如何制作OpenStack镜像的过程进行描述记录  CSDN:OpenStack镜像制作教程指导(全) OpenStack镜像制作系列1—环境准备 OpenStack镜像制作系列2—Windows7镜像 OpenStack镜像制作系列3—Windows10镜像 OpenStack镜像制作系列4—Windows Server2019镜像 OpenStack镜像制作系

OpenStack镜像制作系列2—Windows7镜像

本系列文章主要对如何制作OpenStack镜像的过程进行描述记录 CSDN:OpenStack镜像制作教程指导(全) OpenStack镜像制作系列1—环境准备 OpenStack镜像制作系列2—Windows7镜像 OpenStack镜像制作系列3—Windows10镜像 OpenStack镜像制作系列4—Windows Server2019镜像 OpenStack镜像制作系列

OpenStack镜像制作系列1—环境准备

本系列文章主要对如何制作OpenStack镜像的过程进行描述记录 CSDN:OpenStack镜像制作教程指导(全) OpenStack镜像制作系列1—环境准备 OpenStack镜像制作系列2—Windows7镜像 OpenStack镜像制作系列3—Windows10镜像 OpenStack镜像制作系列4—Windows Server2019镜像 OpenStack镜像制作

CSDN:OpenStack镜像制作教程指导(全)

本系列文章主要对如何制作OpenStack镜像的过程进行描述记录,涉及基本环境准备、常见类型操作系统的镜像制作。 让你可以从零开始安装一个操作系统,并支持个性化制作OpenStack镜像。 CSDN:OpenStack镜像制作教程指导(全) OpenStack镜像制作系列1—环境准备 OpenStack镜像制作系列2—Windows7镜像 OpenStack镜像制作系列3—Windows

OpenStack Victoria版——4.控制节点-Glance镜像服务组件

4.控制节点-Glance镜像服务组件 更多步骤:OpenStack Victoria版安装部署系列教程 OpenStack部署系列文章 OpenStack Victoria版 安装部署系列教程 OpenStack Ussuri版 离线安装部署系列教程(全) OpenStack Train版 离线安装部署系列教程(全) 欢迎留言沟通,共同进步。 文章目录 创建glanc

docker学习系列(四)制作基础的base项目镜像--jdk+tomcat

前面已经完成了docker的安装以及使用,现在我们要将自己的javaweb项目与docker结合 1.1准备jdk+tomcat软件 ​​我下载了apache-tomcat-7.0.68.tar.gz和jdk-7u79-linux-x64.tar.gz,存储于Linux机器的本地目录/usr/ect/wt/下(利用xshell上传)。利用linux命令 tar -zxvf apache-tom

Linux下构建Docker镜像

Docker在Linux构建镜像 Docker是一种轻量级的容器化技术,可以让开发者将应用程序及其所有依赖项打包到一个独立的容器中,从而实现跨平台和快速部署,在Linux系统上,我们可以使用D0cker来构建自己的镜像,并且可以通过简单的命令来管理这些镜像。 Docker基本概念 在使用Docker构建镜像之前,我们需要了解一些基本概念: 镜像(lmage):镜像是一个只读的模板,包含了运行容器

SuperMap iManger 单个镜像更新流程

1. 下载镜像 docker pull registry.cn-beijing.aliyuncs.com/supermap/common-dashboard-api:11.1.1-240802-amd64 label 没区分架构,在 x64 环境 pull arm64 镜像 通过 --platform=arm64 参数可以实现 docker pull mariadb:10.5.26