【图像处理】

阅读: 评论:0

【图像处理】

【图像处理】

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

文章目录

  • 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} ⎩⎪⎨⎪⎧​x0​y0​​==​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]⎣⎡​a1​a3​a5​​a2​a4​a6​​001​⎦⎤​
  这就是向前映射的矩阵表示法。

[ 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]⎣⎡​b1​b3​b5​​b2​b4​b6​​001​⎦⎤​
  这是向后映射的矩阵表示。
  可以看出,向后映射的矩阵表示正好是向前映射的矩阵表示的逆变换。

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]⎣⎡​10−dx​01−dy​001​⎦⎤​

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​==​width−x0​−1y0​​​​
那么水平镜像的向后映射矩阵表示为:
[ 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]⎣⎡​−10width−1​010​001​⎦⎤​
  对于垂直镜像,同样可以得到它的变换关系和矩阵表达式:
{ 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​==​x0​height−y0​−1​​​
那么水平镜像的向后映射矩阵表示为:
[ 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]⎣⎡​100​0−1height−1​001​⎦⎤​

4.2 OpenCV实现

//创建水平镜像变换矩阵
void CreateMirrorXMatrix(cv::Mat& img, cv::Mat& mat)
{int width = ls;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 = ws;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]⎣⎡​010​100​001​⎦⎤​

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::ws, ls),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('转置结果图');

本文发布于:2024-01-29 02:03:15,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170646499611930.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:图像处理
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23