zoukankan      html  css  js  c++  java
  • 图像的几何变换(一)

    图像的几何变换是指改变图像的几何位置、几何形状、几何尺寸等几何特征。

     

    一.图像的平移

    图像平移是将一幅图像中所有的点都按照指定的平移量在水平、垂直方向移动,平移后的图像与原图像相同。

    利用齐次坐标,变换前后图像上的点P0(x0,y0)和P(x,y)之间的关系可以用如下的矩阵变换表示为

    平移变换的几点说明:

    ①平移后图像上的每一点都可以在原图像中找到对应的点。对于不在原图像中的点,可以直接将它的像素值统一设置为0或这255(对于灰度图就是黑色或者白色);

    ②若图像平移后并没被放大,说明移出的部分被截断,原图像中有像素点被移出显示区域。

    ③若不想丢失被移出的部分图像,则将新生成的图像扩大。

    代码如下:

    clear all;
    close all;
    I = imread('lenna.jpg');
    
    delta_x = 10;                                       % 水平方向的偏移量
    delta_y = 10;                                       % 垂直方向的偏移量
    [M N] = size(I);                                    % 原图像的宽度和高度
    I2 = zeros(M, N);
    for x = 1 : M
        if x + delta_x <= M
            for y = 1 : N
                if y + delta_y <= N
                   I2(x + delta_x, y + delta_y) = I(x, y);
                end
            end
        end
    end
    subplot(1, 2, 1), imshow(I);
    subplot(1, 2, 2), imshow(uint8(I2));
    

    平移后的图像显示如下:

    二.图像的旋转

    一般图像的旋转是以图像的中心为原点,旋转一定的角度,即将图像上的所有像素都旋转一个相同的角度。

    图像的旋转变换也可以用矩阵变换表示。设点P0(x0, y0)旋转θ角后的对应点为P(x, y),则变换公式为:

    逆时针旋转或者是顺时针旋转

    利用公式进行图像旋转变换时,需要注意如下两点:

    ①为了避免图像信息的丢失,图像旋转后必须进行平移变换。

    ②图像旋转之后,会出现许多空洞点,我们必须对这些空洞点进行填充处理,否则图像旋转后的效果不好,一般也将这种操作称作为插值处理。

    上述的旋转是绕坐标轴原点(0,0)进行的,如果是绕某一个指定点旋转,则先要将坐标系平移到该点,再进行旋转,然后将旋转后的图像平移回原坐标系。因此,我们得到绕任一点(x0,y0)的旋转变换公式为:

    x’ = (x-x0)·cos(θ) + (y-y0)·sin(θ) + x0

    y’ = -(x-x0)·sin(θ) + (y-y0)·cos(θ) + y0

    代码如下:

    clear all;
    close all;
    I = imread('lenna.jpg');
    
    H = 1;                      % 矩阵pix第一个元素,即高度
    W = 2;                      % 矩阵pix第二个元素,即宽度
    
    [M N] = size(I);                                                        % M为原图像的高度,N为原图像的宽度
    theta = 30 / 180 * pi;                                                  % 旋转角度为顺时针方向30度
    rot = [cos(theta) -sin(theta) 0; sin(theta) cos(theta) 0; 0 0 1];       % 变换矩阵
    inv_rot = inv(rot);                                                     % 变换矩阵的逆运算
    pix1 = [1 1 1] * rot;                                                   % 变换后图像左上点的坐标
    pix2 = [1 N 1] * rot;                                                   % 变换后图像右上点的坐标
    pix3 = [M 1 1] * rot;                                                   % 变换后图像左下点的坐标
    pix4 = [M N 1] * rot;                                                   % 变换后图像右下点的坐标
    
    height = round(max([abs(pix1(H) - pix4(H)) abs(pix2(H) - pix3(H))])  + 0.5);        % 变换后图像的高度
    width = round(max([abs(pix1(W) - pix4(W)) abs(pix2(W) - pix3(W))])  + 0.5);         % 变换后图像的宽度
    delta_y = abs(min([pix1(H) pix2(H) pix3(H) pix4(H)]));                              % y方向负轴超出的偏移量
    delta_x = abs(min([pix1(W) pix2(W) pix3(W) pix4(W)]));                              % y方向负轴超出的偏移量
    
    I2 = zeros(height, width);
    for y = 1 - delta_y : height - delta_y
       for x = 1 - delta_x : width - delta_x
          pix = [y x 1] * inv_rot;
          if pix(H) > 0.5 && pix(W) > 0.5 && pix(H) < M && pix(W) < N
              I2(y + delta_y, x + delta_x) = I(round(pix(H)), round(pix(W)));
          end
       end
    end
    
    subplot(1, 2, 1), imshow(I), title('原图像');
    subplot(1, 2, 2), imshow(uint8(I2)), title('旋转后的图像');
    

    旋转后的图像显示如下:

    三.图像的比例缩放

    图像的比例缩放变换是指给定的图像在x轴方向按比例缩放fx倍,在y轴方向缩放fy倍,从而获得一幅新的图象。比例缩放前后两点P0(x0,y0)、P(x,y)之间的关系用矩阵形式可以表现为:

    在图像放大的正变换中,会出现很多的空格。因此,需要对放大后所多出来的空格填入适当的像素值。一般采用最邻近插值和线性插值法。

    图像缩小代码如下:

    clear all;
    close all;
    
    I = imread('lenna.jpg');
    [M N] = size(I);
    
    width = int32(0.5 * N)                                    % 将图像宽度缩小为原来的1/2
    height = int32(0.5 * M)                                   % 将图像高度缩小为原来的1/2
    
    I2 = uint8(zeros(height, width));
    widthScale = floor(N / width);
    heightScale = floor(M / height);
    
    for y = 1 : height
       for x = 1 : width
           oldX = x * widthScale;
           oldY = y * heightScale;
           I2(y, x) = I(oldY, oldX);
       end
    end
    
    a1 = subplot(1, 2, 1);
    imshow(I), title('原图像');
    a2 = subplot(1, 2, 2);
    imshow(I2), title('缩小后的图像');
    set(a2, 'XLim', get(a1, 'XLim'), 'YLim', get(a1, 'YLim'));          % 将两个sunplot的x,y轴单位长度设为一样
    

    缩小后的图像显示如下:

    图像放大代码如下:

    clear all;
    close all;
    
    I = imread('lenna.jpg');
    [M N] = size(I);
    
    width = 2 * N;                                          % 将图像宽度放大为原来的2倍
    height = 2 * M;                                         % 将图像高度放大为原来的2倍
    
    I2 = uint8(zeros(height, width));
    widthScale = width / N;
    heightScale = height / M;
    
    for y = 1 : height
       for x = 1 : width
           oldX = round(x / widthScale);
           oldY = round(y / heightScale);
           if oldX == 0 oldX = 1; end
           if oldY == 0 oldY = 1; end
           if oldX > N oldX = N; end
           if oldY > M oldY = M; end
           I2(y, x) = I(oldY, oldX);
       end
    end
    
    a1 = subplot(1, 2, 1);
    imshow(I), title('原图像');
    a2 = subplot(1, 2, 2);
    imshow(I2), title('放大后的图像');
    set(a1, 'XLim', get(a2, 'XLim'), 'YLim', get(a2, 'YLim'));          % 将两个sunplot的x,y轴单位长度设为一样
    

    放大后的图像显示如下:

  • 相关阅读:
    php中的imagettftext函数
    CMD命令
    Python基础学习笔记三
    java多线程中等待线程与被阻塞线程的区别
    转:hibernate中的N+1问题
    转:Mina2.0框架源码剖析(六)
    转:在Spring中配置Hibernate的事务
    转:Mina2.0框架源码剖析(八)
    转:Mina2.0框架源码剖析(五)
    转:JAVA集合框架思考
  • 原文地址:https://www.cnblogs.com/minisculestep/p/4865209.html
Copyright © 2011-2022 走看看