图像平移

   图像平移非常简单,如图所示,初始坐标为(x0,y0)的点经过平移(tx,ty)后坐标变为(x1,y1)。这两点之间的关系是x1=x0+ty1=y0+ty

    以矩阵的形式表示为

                

    它的逆变换为:



     平移变换的实现很简单,可以先新建一个与原图像一样大小的新图像,填充背景色。对于新图像中的每一个像素点(x1,y1),根据逆变换公式算出在原图像中的对应坐标(x0,y0),如果(x0,y0)不在原图像范围内,则把(x1,y1)对应的像素值设置为背景色;若(x0,y0)在原图像范围内,则把(x0,y0)的像素值赋给(x1,y1)。因此程序实现的时候,只需要遍历所有像素依次判断即可。

    下面从另一个角度来思考,以x方向的平移为例:

      设 图像宽width, 高height

    (1)当tx>0时,图像向右平移,平移后目标区域左下角横坐标为 xstart=tx, 对应于源图像的x0=0; 右上角横坐标 xend=width-1,对应源图像 x1=(width-1)-th ;

    (2)当tx<0时,图像向左平移,平移后目标区域左下角横坐标为 xstart=0, 对应于源图像的x0= - tx; 右上角横坐标 xend= (width-1)+tx,对应源图像 x1=width-1 ;

      y方向同理可得。    

    (3)然后把原图像中由(x0,y0)→(x1,y1)确定的区域copy到新图像中由(xstart, ystart) → (xend, yend) 确定的区域。

      C代码如下:

/*
* translate.cpp
* 实现图像的平移
* Created on: 2011-10-9
* Author: LiChanghai
*/
// 设定平移不改变图像的大小,平移出去的部分截掉
// 平移后的背景设为0(黑色),图像宽width, 高height
// 设平移向量为t=(tx, ty),由于当|tx|≥width 或 |ty|≥height 时
// 图像完全平移出原来区域,只剩背景色,因此这里假定
// |tx|≤width 且 |ty|≤height
// 设平移后目标区域的左下角坐标为(xstart, ystart)
// 对应于原图像的坐标为(x0, y0)
// 目标区域右上角坐标为(xend, yend)(程序里不需要定义出来)
// 对应于原图像的坐标为 (x1, y1)
#include <string.h>
bool translate(unsigned char *pImage, int width, int height, int biBitCount, int tx, int ty)
{
//定义相关变量
int xstart, x0, x1, ystart, y0, y1, i;

//定义变量,计算图像每行像素所占的字节数(必须是4的倍数)
int lineByte=(width * biBitCount/8+3)/4*4;

//申请新的位图数据存储空间, 并拷贝原图像
unsigned char *pImage2;
pImage2=new unsigned char[lineByte*height];
memcpy(pImage2, pImage, lineByte*height);

//将原图像设置为背景色
memset(pImage, 0, lineByte*height);

//确定平移前后的坐标关系
if(tx>0)
{
xstart=tx; x0=0;
x1=(width-1)-tx;
}
else
{
xstart=0; x0=-tx;
x1=width-1;
}

if(ty>0)
{
ystart=ty; y0=0;
y1=(height-1)-ty;
}
else
{
ystart=0; y0=-ty;
y1=height-1;
}

// copy数据
for(i=0; i<y1-y0+1; i++) //需要复制 y1-y0+1行
memcpy(pImage+(ystart+i)*lineByte+xstart, pImage2+(y0+i)*lineByte+x0, x1-x0+1);

return 1;
}


       这种方式不用遍历每一个像素,因此运算量小。该程序在Eclipse上调试通过。




原文地址:https://www.cnblogs.com/haigege/p/2203822.html