当前位置:文档之家› c语言实现图像的旋转与平移

c语言实现图像的旋转与平移

c语言实现图像的旋转与平移
c语言实现图像的旋转与平移

实验二图象的几何变换参考资料

1平移

平移(translation)变换是几何变换中最简单的一种。初始坐标为(x ,y )的点经过平移(t ,t )(以向

0 0 x y

右,向下为正方向)后,坐标变为(x ,y )。这两点之间的关系是x =x +t,y =y +t。

1 1 1 0 x 1 0 y

下面给出Translation的源代码。算法的思想是先将所有区域填成白色,然后找平移后显示

区域的左上角点(x ,y )和右下角点(x ,y ),分几种情况进行处理。

0 0 1 1

先看x方向(width指图象的宽度)

(1)

(2) t x≤-width:很显然,图象完全移出了屏幕,不用做任何处理;

-width

(3) 0< t

x x x (4) t x≥width:图象完全移出了屏幕,不用做任何处理。

y方向是对应的(height表示图象的高度):

(1)

(2)

(3)

(4) t y≤-height,图象完全移出了屏幕,不用做任何处理;

-height

y y y

0

y y y

t y≥height,图象完全移出了屏幕,不用做任何处理。

这种做法利用了位图存储的连续性,即同一行的象素在内存中是相邻的。利用memcpy函数,从(x ,y )点开始,一次可以拷贝一整行(宽度为x-x ),然后将内存指针移到(x ,y +1)处,拷

0 0 1 0 0 0

贝下一行。这样拷贝(y -y )行就完成了全部操作,避免了一个一个象素的计算,提高了效率。

1 0

Translation的源代码如下:

int xOffset=0,yOffset=0;

BOOL Translation(HWND hWnd)

{

DLGPROC

dlgInputBox = NULL; OffBits,BufSize;

lpImgData;

DWORD LPBITMAPINFOHEADER LPSTR

lpPtr; HLOCAL hTempImgData;

lpTempImgData;

lpTempPtr; LPBITMAPINFOHEADER LPSTR

int

SrcX0,SrcY0,SrcX1,SrcY1; DstX0,DstY0,DstX1,DstY1; RectWidth,RectHeight; xVisible,yVisible; hDc; int

int

BOOL

HDC

HFILE

int hf; i;

//出现对话框,输入 x 偏移量 xOffset ,和 y 偏移量 yOffset

dlgInputBox = (DLGPROC) MakeProcInstance ( (FARPROC)InputBox,ghInst );

DialogBox (ghInst, "INPUTBOX", hWnd, dlgInputBox);

FreeProcInstance ( (FARPROC) dlgInputBox );

//OffBits 为 BITMAPINFOHEADER 结构长度加调色板的大小

OffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER);

BufSize=OffBits+bi.biHeight*LineBytes;//要开的缓冲区的大小

//为新产生的位图分配缓冲区内存

if((hTempImgData=LocalAlloc(LHND,BufSize))==NULL)

{

MessageBox(hWnd,"Error alloc memory!","Error Message",MB_OK|

MB_ICONEXCLAMATION);

return FALSE; //失败,返回

}

//lpImgData为指向原来位图数据的指针

lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);

//lpTempImgData为指向新产生位图数据的指针

lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData); lpPtr=(char *)lpImgData;

lpTempPtr=(char *)lpTempImgData;

//将新的缓冲区中的每个字节都填成255,这样以后未处理的象素就是白色memset(lpTempPtr,(BYTE)255,BufSize);

//两幅图之间的头信息,包括调色板都是相同的,所以直接拷贝头和调色板memcpy(lpTempPtr,lpPtr,OffBits);

//xVisible为FALSE时,表示x方向已经移出了可显示的范围

xVisible=TRUE;

if( xOffset<= -bi.biWidth )

xVisible=FALSE;

else if( xOffset<=0){

DstX0=0; //表示移动后,有图区域的左上角点的x坐标

DstX1=bi.biWidth+xOffset; //表示移动后,有图区域的右下角点的x坐标}

else if ( xOffset

DstX0=xOffset;

DstX1=bi.biWidth;

}

else

xVisible=FALSE;

SrcX0=DstX0-xOffset; //对应DstX0在原图中的x坐标

SrcX1=DstX1-xOffset; //对应DstX1在原图中的x坐标

RectWidth=DstX1-DstX0; //有图区域的宽度

//yVisible为FALSE时,表示y方向已经移出了可显示的范围

yVisible=TRUE;

if( yOffset<= -bi.biHeight )

yVisible=FALSE;

else if( yOffset<=0){

DstY0=0; //表示移动后,有图区域的左上角点的y坐标

DstY1=bi.biHeight+yOffset; //表示移动后,有图区域的右下角点的y坐标}

else if ( yOffset

DstY0=yOffset;

DstY1=bi.biHeight;

}

else

yVisible=FALSE;

SrcY0=DstY0-yOffset; //对应DstY0在原图中的y坐标

SrcY1=DstY1-yOffset; //对应DstY1在原图中的y坐标

RectHeight=DstY1-DstY0; //有图区域的高度

if( xVisible && yVisible){ //x,y方向都没有完全移出可显示的范围

for(i=0;i

//lpPtr指向要拷贝的那一行的最左边的象素对应在原图中的位

//置。特别要注意的是,由于.bmp是上下颠倒的,偏移是

//(BufSize-LineBytes-(i+SrcY0)*LineBytes)+SrcX0,而不是

//(i+SrcY0)*LineBytes)+SrcX0,你试着举个例子就明白了。

lpPtr=(char*)lpImgData+(BufSize-LineBytes-

(i+SrcY0)*LineBytes)+SrcX0;

//lpTempPtr指向要拷贝的那一行的最左边的象素对应在新图中//的位置。同样要注意上面// 的问题。

lpTempPtr=(char*)lpTempImgData+

(BufSize-LineBytes-(i+DstY0)*LineBytes)+DstX0;

//拷贝一行(宽度为 RectWidth)

memcpy(lpTempPtr,lpPtr,RectWidth);

}

}

hDc=GetDC(hWnd);

if(hBitmap!=NULL)

DeleteObject(hBitmap); //释放原来的位图句柄

//产生新的位图

hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpTempImgData, (LONG)CBM_INIT,

(LPSTR)lpTempImgData+

sizeof(BITMAPINFOHEADER) +

NumColors*sizeof(RGBQUAD),

(LPBITMAPINFO)lpTempImgData,

DIB_RGB_COLORS);

//将平移后的图象存成文件

hf=_lcreat("c:\\translation.bmp",0);

_lwrite(hf,(LPSTR)&bf,sizeof(BITMAPFILEHEADER));

_lwrite(hf,(LPSTR)lpTempImgData,BufSize);

_lclose(hf);

//释放资源和内存

ReleaseDC(hWnd,hDc);

LocalUnlock(hTempImgData);

LocalFree(hTempImgData);

GlobalUnlock(hImgData);

return TRUE;

}

2旋转

首先给出变换矩阵。在我们熟悉的坐标系中,将一个点顺时针旋转a角后的坐标变换,r为

该点到原点的距离,在旋转过程中,r保持不变;b为r与x轴之间的夹角。

旋转前:x =rcosb;y =rsinb

0 0

旋转a角度后:

x1=rcos(b-a)=rcosbcosa+rsinbsina=x cosa+y sina;

0 0

y1=rsin(b-a)=rsinbcosa-rcosbsina=-x sina+y cosa;

0 0

上面的公式中,坐标系xoy是以图象的中心为原点,向右为x轴正方向,向上为y轴正方向。设图象的宽为w,高为h。

把变换分成三步:

1.将坐标系o’变成o;

2.将该点顺时针旋转a角;

3.将坐标系o变回o’,这样,我们就得到了变换矩阵,是上面三个矩阵的级联。

w,h,w new,h new分别表示原图(old)和新图(new)的宽、高。w new=max(|x -x |,|x -x |);

old old 4 1 3 2

h new=max(|y -y |,|y -y |)。

4 1 3 2

源程序如下:

#define PI 3.1415926535

#define RADIAN(angle) ((angle)*PI/180.0) //角度到弧度转化的宏

BOOL Rotation(HWND hWnd)

{

DLGPROC dlgInputBox = NULL;

DWORD OffBits,SrcBufSize,DstBufSize,DstLineBytes;

LPBITMAPINFOHEADER lpImgData;

LPSTR

lpPtr; HLOCAL hTempImgData;

lpTempImgData;

lpTempPtr; LPBITMAPINFOHEADER LPSTR

float

SrcX1,SrcY1,SrcX2,SrcY2; SrcX3,SrcY3,SrcX4,SrcY4; DstX1,DstY1,DstX2,DstY2; DstX3,DstY3,DstX4,DstY4; Wold,Hold,Wnew,Hnew; hDc; float

float

float

DWORD

HDC

HFILE

hf; DWORD

x0,y0,x1,y1; float

cosa,sina; //cos(a),sin(a); num1,num2; float

BITMAPFILEHEADER

BITMAPINFOHEADER DstBf; DstBi;

//出现对话框,输入旋转角度(顺时针方向)

dlgInputBox = (DLGPROC) MakeProcInstance ( (FARPROC)InputBox,ghInst );

DialogBox (ghInst, "INPUTBOX", hWnd, dlgInputBox);

FreeProcInstance ( (FARPROC) dlgInputBox );

//角度到弧度的转化

RotateAngle=(float)RADIAN(RotateAngle); cosa=(float)cos((double)RotateAngle);

sina=(float)sin((double)RotateAngle);

//原图的宽度和高度

Wold=bi.biWidth;

Hold=bi.biHeight;

//原图的四个角的坐标

SrcX1=(float)(-0.5*Wold);

SrcY1=(float)(0.5*Hold);

SrcX2=(float)(0.5*Wold);

SrcY2=(float)(0.5*Hold);

SrcX3=(float)(-0.5*Wold);

SrcY3=(float)(-0.5*Hold);

SrcX4=(float)(0.5*Wold);

SrcY4=(float)(-0.5*Hold);

//新图四个角的坐标

DstX1=cosa*SrcX1+sina*SrcY1;

DstY1=-sina*SrcX1+cosa*SrcY1;

DstX2=cosa*SrcX2+sina*SrcY2;

DstY2=-sina*SrcX2+cosa*SrcY2;

DstX3=cosa*SrcX3+sina*SrcY3;

DstY3=-sina*SrcX3+cosa*SrcY3;

DstX4=cosa*SrcX4+sina*SrcY4;

DstY4=-sina*SrcX4+cosa*SrcY4;

//计算新图的宽度,高度

Wnew = (DWORD)(max(fabs(DstX4-DstX1), fabs(DstX3-DstX2))+0.5); Hnew = (DWORD)(max(fabs(DstY4-DstY1), fabs(DstY3-DstY2))+0.5); //计算矩阵(2.9)中的两个常数,这样不用以后每次都计算了

num1=(float)( -0.5*Wnew*cosa-0.5*Hnew*sina+0.5*Wold);

num2=(float)(0.5*Wnew*sina-0.5*Hnew*cosa+0.5*Hold);

//OffBits为BITMAPINFOHEADER结构长度加调色板的大小OffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER);

SrcBufSize=OffBits+bi.biHeight*LineBytes;

//显示时,采用新图的宽度和高度,

ImgWidth=Wnew;

ImgHeight=Hnew;

//新图每行占用的字节

DstLineBytes=(DWORD)WIDTHBYTES(Wnew*bi.biBitCount); DstBufSize=(DWORD)(sizeof(BITMAPINFOHEADER)+ NumColors*sizeof(RGBQUAD)+

(DWORD)DstLineBytes*Hnew); //要开的缓冲区的大小

//为新产生的位图分配缓冲区内存

if((hTempImgData=LocalAlloc(LHND,DstBufSize))==NULL)

{

MessageBox(hWnd,"Error alloc memory!","Error Message",

MB_OK|MB_ICONEXCLAMATION);

return FALSE; //失败,返回

}

//lpImgData为指向原来位图数据的指针

lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);

//lpTempImgData为指向新产生位图数据的指针

lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData); lpPtr=(char *)lpImgData;

lpTempPtr=(char *)lpTempImgData;

//将新的缓冲区中的每个字节都填成255,这样以后未处理的象素就是白色memset(lpTempPtr,(BYTE)255,DstBufSize);

//拷贝头和调色板信息

memcpy(lpTempPtr,lpPtr,OffBits);

//得到新的BITMAPFILEDER和 BITMAPINFOHERDER

memcpy((char *)&DstBf,(char *)&bf,sizeof(BITMAPFILEHEADER)); memcpy((char *)&DstBi,(char *)&bi,sizeof(BITMAPINFOHEADER));

//做一些必要的改变,这一点特别要注意

DstBf.bfSize=DstBufSize+sizeof(BITMAPFILEHEADER);

DstBi.biWidth=Wnew;

DstBi.biHeight=Hnew;

//用新的BITMAPINFOHERDER覆盖原来的那个

memcpy(lpTempPtr,(char *)&DstBi,sizeof(BITMAPINFOHEADER));

for(y1=0;y1

for(x1=0;x1

//x0,y0为对应的原图上的坐标

x0= (DWORD)(x1*cosa+y1*sina+num1);

y0= (DWORD)(-1.0f*x1*sina+y1*cosa+num2);

if( (x0>=0) && (x0=0) && (y0

//在原图范围内

{

lpPtr=(char*)lpImgData+

(SrcBufSize-LineBytes-y0*LineBytes)+x0;

lpTempPtr=(char*)lpTempImgData+

(DstBufSize-DstLineBytes-y1*DstLineBytes)+x1;

*lpTempPtr=*lpPtr; //进行象素的复制

}

}

hDc=GetDC(hWnd);

if(hBitmap!=NULL)

DeleteObject(hBitmap); //释放原来的位图句柄

hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpTempImgData, (LONG)CBM_INIT,

(LPSTR)lpTempImgData+

sizeof(BITMAPINFOHEADER) +

NumColors*sizeof(RGBQUAD),

(LPBITMAPINFO)lpTempImgData,

DIB_RGB_COLORS);

//将旋转后的图象存成文件

hf=_lcreat("c:\\rotation.bmp",0);

_lwrite(hf,(LPSTR)&DstBf,sizeof(BITMAPFILEHEADER));

_lwrite(hf,(LPSTR)lpTempImgData,DstBufSize);

_lclose(hf);

//释放资源和内存

ReleaseDC(hWnd,hDc);

LocalUnlock(hTempImgData);

LocalFree(hTempImgData);

GlobalUnlock(hImgData);

return TRUE;

}

3缩放

假设放大因子为ratio,(为了避免新图过大或过小,我们在程序中限制0.25≤ratio≤4)。缩放变换的源代码如下。

float ZoomRatio=0.25f; //缩放比例,初始化为 0.25

BOOL Zoom(HWND hWnd)

{

DLGPROC dlgInputBox = NULL;

DWORD OffBits,SrcBufSize,DstBufSize,DstLineBytes;

LPBITMAPINFOHEADER LPSTR lpImgData;

lpPtr;

HLOCAL hTempImgData; LPBITMAPINFOHEADER lpTempImgData; LPSTR lpTempPtr;

DWORD HDC Wold,Hold,Wnew,Hnew;

hDc;

hf;

HFILE

DWORD x0,y0,x1,y1;

num1;

float

BITMAPFILEHEADER

BITMAPINFOHEADER //出现对话框,输入缩放比例DstBf; DstBi;

dlgInputBox = (DLGPROC) MakeProcInstance ( (FARPROC)InputBox, ghInst ); DialogBox (ghInst, "INPUTBOX", hWnd, dlgInputBox);

FreeProcInstance ( (FARPROC) dlgInputBox );

num1=(float)(1.0/ZoomRatio);

//原图宽度和高度

Wold=bi.biWidth;

Hold=bi.biHeight;

//新图宽度和高度

Wnew = (DWORD)(Wold*ZoomRatio+0.5);

Hnew = (DWORD)(Hold*ZoomRatio+0.5);

OffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER);

SrcBufSize=OffBits+bi.biHeight*LineBytes;

ImgWidth=Wnew;

ImgHeight=Hnew;

DstLineBytes=(DWORD)WIDTHBYTES(Wnew*bi.biBitCount);

DstBufSize=(DWORD)(sizeof(BITMAPINFOHEADER)+

NumColors*sizeof(RGBQUAD)+

(DWORD)DstLineBytes*Hnew);

if((hTempImgData=LocalAlloc(LHND,DstBufSize))==NULL)

{

MessageBox(hWnd,"Error alloc memory!","Error Message",MB_OK| MB_ICONEXCLAMATION);

return FALSE;

}

lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);

lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData);

lpPtr=(char *)lpImgData;

lpTempPtr=(char *)lpTempImgData;

memset(lpTempPtr,(BYTE)255,DstBufSize);

memcpy(lpTempPtr,lpPtr,OffBits);

//头信息中做一些必要的改变,这一点非常重要

memcpy((char *)&DstBf,(char *)&bf,sizeof(BITMAPFILEHEADER));

memcpy((char *)&DstBi,(char *)&bi,sizeof(BITMAPINFOHEADER));

DstBf.bfSize=DstBufSize+sizeof(BITMAPFILEHEADER);

DstBi.biWidth=Wnew;

DstBi.biHeight=Hnew;

memcpy(lpTempPtr,(char *)&DstBi,sizeof(BITMAPINFOHEADER));

for(y1=0;y1

for(x1=0;x1

x0= (DWORD)(x1*num1);

y0= (DWORD)(y1*num1);

if( (x0>=0) && (x0=0) && (y0

{

lpPtr=(char*)lpImgData+

(SrcBufSize-LineBytes-y0*LineBytes)+x0;

lpTempPtr=(char *)lpTempImgData+

(DstBufSize-DstLineBytes-y1*DstLineBytes)+x1;

*lpTempPtr=*lpPtr;

}

}

hDc=GetDC(hWnd);

if(hBitmap!=NULL)

DeleteObject(hBitmap);

hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpTempImgData,

(LONG)CBM_INIT,

(LPSTR)lpTempImgData+

sizeof(BITMAPINFOHEADER)+

NumColors*sizeof(RGBQUAD),

(LPBITMAPINFO)lpTempImgData, DIB_RGB_COLORS);

hf=_lcreat("c:\\zoom.bmp",0);

_lwrite(hf,(LPSTR)&DstBf,sizeof(BITMAPFILEHEADER));

_lwrite(hf,(LPSTR)lpTempImgData,DstBufSize);

_lclose(hf);

ReleaseDC(hWnd,hDc);

LocalUnlock(hTempImgData);

LocalFree(hTempImgData);

GlobalUnlock(hImgData);

return TRUE;

}

由于放大图象时产生了新的象素,以及浮点数的操作,得到的坐标可能并不是整数。我们采用的做法是找与之最临近的点。

数字图像处理_旋转与幅度谱(含MATLAB代码)

数字图像处理实验一 15生医 一、实验内容 产生右图所示图像 f1(m,n),其中图像大小为256 ×256,中间亮条为128×32,暗处=0,亮处=100。 对其进行FFT: ①同屏显示原图f1(m,n)和FFT(f1)的幅度谱图; ②若令f2(m,n)=(-1)^(m+n)f1(m,n),重复 以上过程,比较二者幅度谱的异同,简述理由; ③若将f2(m,n)顺时针旋转90度得到f3(m,n),试显示FFT(f3)的 幅度谱,并与FFT(f2)的幅度谱进行比较; ④若将f1(m,n) 顺时针旋转90度得到f4(m,n),令f5(m,n) = f1(m,n) + f4(m,n),试显示FFT(f5)的幅度谱,指出其与 FFT(f1)和FFT(f4)的关系; ⑤若令f6(m,n)=f2(m,n)+f3(m,n),试显示FFT(f6)的幅度谱,并指出其与 FFT(f2)和FFT(f3)的关系,比较FFT(f6)和FFT(f5)的幅度谱。 二、运行环境 MATLAB R2014a 三、运行结果及分析 1.同屏显示原图f1(m,n)和FFT(f1)的幅度谱图:

50100150200250 100150200250 50100150200250 100150200250 2.令f2(m,n)=(-1)^(m+n )f1(m,n),对其进行FFT ,比较f2与f1幅度谱的异同,简述理由: 50100150200250 100150200250 50100150200250 100150200250 异同及理由:①空域:f2由于前边乘了系数(-1)^(m+n ),导致灰度值有正有负,而在MATLAB 的imshow 函数中默认把负值变为0(有些情况是取反),所以形成了如左图所示的黑白花纹。②频域:FFT(2)

用MATLAB编程实现数字图像旋转

用MATLAB编程实现数字图像旋转 摘要:文章论述了用Matlab编程实现数字图像旋转的基本方法,从计算机几何坐标中的图像旋转矩阵表示着手,给出了图像旋转变换的推导过程,用简单综合插值方法,基本解决了数字图像旋转后出现的空洞问题,并通过Matlab编程工具进行实验验证。 关键词:数字图像旋转;移动变换;旋转矩阵变换;简单综合插值。 数字图像处理是指将图像信号转换成数字信号并利用计算机对其进行处理的过程。目前,数字图像处理的信息大多是二维信息。由于数据量大,因此对计算机的计算速度、存储容量等要求较高。随着微型计算机性能的提高,原来以大型机、小型机为主机的图像处理系统演变为以微机为主机的结构,其应用也迅速普及,当前图像处理技术在工业自动化、工业检测、遥感探测、军事、航空、生物医学等各个方面都发挥着十分重要的作用。 图像旋转是一种常用的数字图像处理技术,传统的图像旋转都是在二维空间中进行的,由于旋转后图像像素点坐标不再是整数,故旋转后必须对像素点灰度进行一维插值运算或二维插值运算,尤其是当对旋转后的图像质量要求较高时,需要采用高阶插值运算。 文章从通用的图像旋转矩阵着手,给出了图像旋转变及换简单综合插值的推导过程,并用Matlab编程工具进行实验验证图像旋转结果。 1Matlab简介 MATLAB是矩阵实验室(Matrix Laboratory)之意。除具备卓越的数值计算能力外,它还提供了专业水平的符号计算,可视化建模仿真和实时控制等功能。MATLAB的基本数据单位是矩阵,它的指令表达式与数学,工程中常用的形式十分相似,故用MATLAB来解算问题要比用C、C#等语言来解算相同的事情简捷得多。 2图像旋转矩阵

真正实现C语言绘制数学函数图像

用C语言画函数图像 横纵坐标单位长度比校正(3:5) 真正的余弦函数 #include #include int sishewuru(float a); void main() { int n = 450; float a[500], b[500]; int i,j; a[0] = b[0] = 0; for (i = 1; i < n; i++)

a[i] = a[i - 1] + 0.01; b[i] = cos(a[i]); } int A[500],B[500]; for (i = 0; i < n; i++) { //printf("sin(%f)=%f\n", a[i], b[i]); a[i] = 100 * a[i]; b[i] = 55 * b[i]; A[i] = sishewuru(a[i]); B[i] = sishewuru(b[i])+60; //printf("sin(%d)=%d\n", A[i], B[i]); } for ( i = 100; i >=0; i--) { for ( j = 0; j < n; j++) { if (i==B[j]) { printf("*"); } else { printf(" "); } } printf("\n"); } } int sishewuru(float a) { int m; if (a-floor(a)<0.5) { m = a; return m; } else { m = a + 1; return m; } }

1.调节输出框大小,字符显示大小 2.确定函数的定义域 3.确定定义域上的步长 4.计算函数值 5.确定函数值放大系数 6.确定定义域恰好落在显示的区间内 7.确定坐标的单位长度与字符实际长度之间的换算关系 8.确定打点的顺序与坐标的关系 定义域在),(ππ-的正弦函数图像 定义域在),(ππ-的正切函数图像

c语言字符串左旋转

假设原数组序列为abcd1234,要求变换成的数组序列为1234abcd,即循环右移了4 位。 比较之后,不难看出,其中有两段的顺序是不变的:1234 和abcd,可把这两段看成两个整 体。右移K 位的过程就是把数组的两部分交换一下。 变换的过程通过以下步骤完成: 逆序排列abcd:abcd1234 →dcba1234; 逆序排列1234:dcba1234 →dcba4321; 全部逆序:dcba4321 →1234abcd。 伪代码可以参考清单2-35。 //代码清单2-35 Reverse(int* arr, int b, int e) { for(; b < e; b++, e--) { int temp = arr[e]; arr[e] = arr[b]; arr[b] = temp; } } RightShift(int* arr, int N, int k) {

K %= N; Reverse(arr, 0, N – K - 1); Reverse(arr, N - K, N - 1); 8 Reverse(arr, 0, N - 1); } 这样,我们就可以在线性时间内实现右移操作了。 就拿abcdef 这个例子来说(非常简短的三句,请细看,一看就懂): 1、首先分为俩部分,X:abc,Y:def; 2、X->X^T,abc->cba,Y->Y^T,def->fed。 3、(X^TY^T)^T=YX,cbafed->defabc,即整个翻转。 #include 5. #include 6. 7. void rotate(char *start, char *end) 8. { 9. while(start != NULL && end !=NULL && start

数字图像处理9-图像的平移与旋转

这次作业的内容是要完成让图片绕任意一点旋转的效果,同时要了解图像旋转的原理。为了达到这一目的,我在老师的示例代码上进行了改进,并自己计算出新的变换矩阵,达到了作业中要求的效果。这里我们先来看一下旋转的效果。 旋转中心(0,0),旋转60°旋转中心(0,0),旋转120° 旋转中心(100,0),旋转120°旋转中心(0,600),旋转120° 图像的大小是690*728,旋转的角度为顺时针,因此可以看到四副图中的结果都是符合预期的。之后我们来通过代码,详细的分析这一变化实现的过程。代码如下: close all; f = imread('try.jpg'); theta = 2* pi / 3; x0=0; y0=600; T = [cos(theta) sin(theta) 0 -sin(theta) cos(theta) 0 0 0 1]; t1=[ 1 0 0

0 1 0 -x0 -y0 1]; t2=[1 0 0 0 1 0 x0 y0 1]; T=t1*T*t2; tform = maketform('affine',T); [g, xdata, ydata] = imtransform(f,tform, 'FillValue',255); imshow(g,'XData',xdata,'YData',ydata); hold on; imshow(f); axis auto; axis on; 读入图像后,先设定了三个参数,x0y0就是旋转中心的坐标,而theta就是旋转角(顺时针)。这里要详细说明一下这几个矩阵的作用,并且推导出其生成的过程。首先最主要的矩阵T,是负责旋转的矩阵。以下这个图片摘自网络,可以说较为完整的解释了这个矩阵的来历。

C语言图形开发库函数graphics

函数名: fillellipse 功能: 画出并填充一椭圆 用法: void far fillellipse(int x, int y, int xradius, int yradius); 程序例: #include #include int main(void) { int gdriver = DETECT, gmode; int xcenter, ycenter, i; initgraph(&gdriver,&gmode,""); xcenter = getmaxx() / 2; ycenter = getmaxy() / 2; for (i=0; i<13; i++) { setfillstyle(i,WHITE); fillellipse(xcenter,ycenter,100,50); getch(); } closegraph(); return 0; } Graphics 类 .NET Framework 类库 Graphics 类 封装一个GDI+ 绘图图面。无法继承此类。 命名空间:System.Drawing 程序集:System.Drawing(在system.drawing.dll 中) 语法 Visual Basic(声明)

Public NotInheritable Class Graphics Inherits MarshalByRefObject Implements IDeviceContext, IDisposable Visual Basic(用法) Dim instance As Graphics C# public sealed class Graphics : MarshalByRefObject, IDeviceContext, IDisposable C++ public ref class Graphics sealed : public MarshalByRefObject, IDeviceContext, IDisposable J# public final class Graphics extends MarshalByRefObject implements IDeviceContext, IDisposable JScript public final class Graphics extends MarshalByRefObject implements IDeviceContext, IDisposable 备注 Graphics类提供将对象绘制到显示设备的方法。Graphics与特定的设备上下文关联。 通过调用从System.Windows.Forms.Control继承的对象的Control.CreateGraphics方法,或通过处理控件的Control.Paint事件并访问System.Windows.Forms.PaintEventArgs类的Graphics属性,可以获取Graphics。 继承层次结构 System.Object System.MarshalByRefObject System.Drawing.Graphics 线程安全 此类型的任何公共静态(Visual Basic 中的Shared)成员都是线程安全的,但不保证所有实例成员都是线程安全的。 平台 Windows 98、Windows 2000 SP4、Windows CE、Windows Millennium Edition、Windows Mobile for Pocket PC、Windows Mobile for Smartphone、Windows Server 2003、Windows XP Media Center Edition、Windows XP Professional x64 Edition、Windows XP SP2、Windows XP Starter Edition

opencv 图像翻转旋转

opencv 图像翻转、旋转 转自: https://www.doczj.com/doc/d914158128.html,/watkinsong/article/details/9189649 1.图像左右翻转、翻转90度 opencv中并没有直接封装图像旋转任意角度的函数,一般我们可以使用仿射变换获得旋转后的图像,这时候可以进行任意角度的旋转,但是如果我们需要将图像旋转90度,例如只是对图像进行左右翻转,或者旋转90度将图像放倒,那么如果还使用仿射变换,显得有些不是很简单,有点过于复杂。实际上可以使用求转置矩阵的方式将图像旋转90度,然后可以沿着指定的坐标轴对旋转后的图像进行翻转变化。使用transpose(src, dst);对目标图像进行转置变换,可以将垂直的图像变为水平放置。然后使用flip()函数对图像进行翻转。整个过程非常简单,可以看下下面的代码就非常清晰的了解了。// ImageFlip.cpp : Defines the entry point for the console application. //#include "stdafx.h" #include "opencv/cv.h" #include "opencv/highgui.h" #include "stdio.h" #include "iostream"using namespace cv;

using namespace std;int _tmain(int argc, _TCHAR* argv[]) { Mat src = imread("lena.jpg"); Mat dst; transpose(src, dst); Mat dst2; flip(dst, dst2, 1); // flip by y axis Mat dst3; flip(dst, dst3, 0); // flip by x axis Mat dst4; flip(dst, dst4, -1); // flip by both axises imshow("src", src); imshow("dst", dst); imshow("dst2", dst2); imshow("dst3", dst3); imshow("dst4", dst4); cvWaitKey(); return 0; } 实验结果:原始图像: 转置以后: flip(dst, dst2, 1); // flip by y axis2、任意角度旋转、同时缩放(输出图像大小与输入图像大小相同,容易造成图像不全)下面这份代码用于实现对图像的缩放与旋转。

编程实现一幅图像的平移、镜像、旋转、缩小和放大

课程设计任务书 学生姓名:专业班级:通信1003班 指导教师:郭志强工作单位:信息工程学院 题目: 通信工程应用技术 初始条件: (1)使用matlab软件进行操作 (2)选择一个图像进行处理 要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)(1)编程实现一幅图像的平移、镜像、旋转、缩小和放大。 (2)给出所用算法的理论依据和必要的推导过程,给出原始图像和处理后的图像。时间安排: 第15周:安排任务,布置题目; 第15—18周:设计仿真,撰写报告 第19周:完成设计,提交报告,答辩 指导教师签名:年月日 系主任(或责任教师)签名:年月日

目录 摘要.................................................................................................................................................................. I Abstract ........................................................................................................................................................... I I 1 MA TLAB简介 .. (1) 1.1 MA TLAB用途 (1) 2图像选择及变换 (4) 2.1 原始图像选择读取 (4) 2.2 图像放大和缩小 (6) 2.2.1 图像放大缩小的知识 (6) 2.2.2 函数说明及参数选择 (8) 2.2.3 源程序及运行结果 (8) 2.3 图像任意角度的旋转 (10) 2.3.1 函数说明及参数选择 (10) 2.3.2 源程序及运行结果 (10) 2.4 图像的平移 (12) 2.4.1 函数说明及参数选择 (12) 2.4.2 源程序及运行结果 (13) 2.5 图像经过镜像 (13) 3.5.1 函数说明及参数选择 (13) 2.5.2 源程序及运行结果 (14) 4 感悟体会小结 (17) 5 参考文献 (18) 附录 (19) 全部源程序代码: (19)

LED旋转显示屏C语言程序

#include #include #define uchar unsigned char #define uint unsigned int sbit e=P3^2; sbit k=P1^0; uint p; uchar code tab[]; void delay(uchar n); void main() { uchar a,b,s; while(1) { if(k==0) { delay(5); if(k==0) { while(!k); for(s=0;s<=192;s++) { a=tab[p]; a=_cror_(a,1); b=tab[p+1]; b=_cror_(b,1); SBUF=a; while(!TI);TI=0; SBUF=b; while(!TI);TI=0; e=0;e=1; delay(5);

} p=0; } } } } void delay(uchar n) { uchar i,j; for(i=0;i

用C++实现图像旋转变换

用C++实现图像旋转变换 (代码较长, 本人使用C++实现了一个类似GDI+ Matrix的C++几何变换类TransformMatrix。 略,参见我的BLOG文章《实现完整的图像平面几何变换》)。 我所说的“实现完整的图像平面几何变换”,是指可以通过TransformMatrix::Multiply函数或者更直接的变换矩阵成员设置去实现“完整的”图像 几何变换,除非其不能使用平面几何变换矩阵进行描述(如梯形变换我就没想到怎么实现, 也许其超出了平面几何变换矩阵范畴?),或者不能进行实际的几何变换(不可逆);“实现 完整的图像几何变换”的另一层含义是下面的图像变换执行函数可实现TransformMatrix 所能表示的任意图像几何变换,而不必去写一个个具体的,如缩放、旋转变换函数等。 C/C++ code // 获取子图数据 BOOL GetSubBitmapData(CONST BitmapData *data, INT x, INT y, INT width, INT height, BitmapDa { if (x < 0) { width += x; x = 0; } if (x + width > (INT)data->Width) width = (INT)data->Width - x; if (width <= 0) return FALSE; if (y < 0) { height += y; y = 0; } if (y + height > (INT)data->Height) height = (INT)data->Height - y; if (height <= 0) return FALSE; sub->Width = width; sub->Height = height; sub->Stride = data->Stride; sub->Scan0 = (CHAR*)data->Scan0 + y * data->Stride + (x << 2); return TRUE; } // 执行图像数据几何变换 VOID Transform(BitmapData *dest, INT x, INT y, CONST BitmapData *source, TransformMatrix *m { // 复制几何变换矩阵对象 TransformMatrix m(matrix); // 几何变换矩阵绝对增加平移量x, y m.GetElements().dx += x; m.GetElements().dy += y;

c语言,画矩形并使其旋转

目录 一、题目 (2) 二、问题描述 (2) 三、程序设计说明 (2) 1、应用程序功能的详细说明 (2) 2、应用程序的功能模块描述,各模块间的层次结构以及模块之间的信息交换说明 (3) 3、算法设计 (3) 4、参考文献 (3) 四、程序流程图 (4) 五、源程序代码 (5) 六、运行结果 (7) 七、结束语 (8) 一、题目:在屏幕上画一个矩形要求:每按一次键盘,该矩形转动45度。矩形的大小和转动的方向有键盘输入,并将输入的数据送文件保存,按回车键程序结束(功能延伸:改变数据文件的内容后,再根据数据文件里的数据绘制矩形) 二、题目内容的描述: 1、在屏幕上画一个矩形。 2、每按一次键盘,该矩形转动45度。 3、矩形的大小和转动的方向有键盘输入,并将输入的数据送文件保存,按 回车键程序结束。 4、功能延伸:改变数据文件的内容后,再根据数据文件里的数据绘制矩形。

三、系统设计说明 1、系统用到的功能分析: 程序设计一般由两部分组成:算法设计和数据结构,合理地选择和实现一个程序结构和处理这些数据结构有同样的重要性,主要包括如下: #include /*图形处理函数*/ #include /*插入数学头文件*/ #include /*标准库函数*/ 1、main主函数中调用scanf()函数,实现数据的输入,并通过调用save(),实现文件的保存,通过调用graphics.h画出正立的初始矩形。 2、save()文件写入函数 前面讲到的数据输入和输出是以中端为对象的,当程序关闭后,数据也丢失了,所以为了能随时查阅数据,必须将数据输出到磁盘文件上保存起来,使用时再从磁盘中读入到内存中,这就用到了磁盘文件的读写操作。 3、initgraph()画正立的初始矩形 从主函数传入定义矩形的高与长,还有输入转向命令0或1,控制矩形左转或右转45度。用initgraph(&GraphDriver,&GraphMode,“”)中的库文件来实现画矩形的算法。调用子函数画矩形并实现左右旋转功能。用line()函数按规律连接线条,画出矩形,调用floodfill函数对矩形填色。 4、moveto()实行矩形的左右转动 通过判断输入的数,控制矩形的左转或右转。 5、lineto()画直线函数 用当前颜色当前画线类型和宽度,在所示坐标之间画一条直线不修改光标当前位置。 6、floodfill()图形填充函数 用当前选定的刷子在指定的设备场景中填充一个区域。区域是由颜色color定义。 三、算法设计 1、主函数中调用scanf()函数,实现数据的输入。由输入的数据控制矩形的的大小,还有输入转向命令,控制矩形的左转或右转。

图形旋转的C语言源程序

图形旋转的C语言源程序 /*****************************************************************/ /* CONVOLVE.C - Turbo C 2.0 implementation of image convolution */ /* ---------- by Wesley G. Faler. All code is "as is". There */ /* is NO copyright. Use this code as you will, and if you make */ /* money at it, good for you. */ /*****************************************************************/ #include #include #include #include #include int load_cut(char *fname); int load_convolution_matrix(char *fname); int convolve_image(void); int swap_pictures(void); int minx,maxx,miny,maxy; int LOADPAGE=0; int ENHANCEPAGE=1; int *cmat, *pmat, *vmat; int cmx,cmy,cmnum; struct palettetype palette,newpal; int driver,mode; int cleancut=-1; int init_graphics(void) { driver=DETECT; mode=0; detectgraph(&driver,&mode); if(driver==VGA) mode=VGAMED; initgraph(&driver,&mode,""); getpalette(&palette); getpalette(&newpal); } int cleanup_image(void) { int i,j,num,x,y,k;

c语言实现图像的旋转与平移

实验二图象的几何变换参考资料 1 平移 平移(translation)变换是几何变换中最简单的一种。初始坐标为(x0,y0)的点经过平移(t x,t y)(以向右,向下为正方向)后,坐标变为(x1,y1)。这两点之间的关系是x1=x0+t x ,y1=y0+t y。 下面给出Translation的源代码。算法的思想是先将所有区域填成白色,然后找平移后显示区域的左上角点(x0,y0) 和右下角点(x1,y1) ,分几种情况进行处理。 先看x方向(width指图象的宽度) (1)t x≤-width:很显然,图象完全移出了屏幕,不用做任何处理; (2)-width

C语言图像旋转 放大 移动程序代码

C语言实现图像旋转程序代码 ////cxcore.lib cv.lib cvaux.lib highgui.lib cvcam.lib #include "cv.h" #include "highgui.h" #include #include #define HIGH 3.14159 #include int main( int argc, char** argv ) { char* filename = NULL; int width,height,step,channels; int width_xz,height_xz,step_xz,channels_xz; float drgee,p,q; double a; float x,y; int i,j,m,n,R,G,B; uchar* data; uchar* data_xz; IplImage* pImg; //声明IplImage指针 IplImage* pImg_xz; //声明IplImage指针 filename="D:\\d.jpg"; //图像的地址 pImg = cvLoadImage(filename, 1); //载入图像 pImg_xz = cvCreateImage(cvGetSize(pImg), IPL_DEPTH_8U,3); //创建图像 cvNamedWindow( "原图", 1 ); //创建窗口 cvMoveWindow("原图",100,200); //移动窗口 /////////////////////////图像处理部分/////////////////////////////////// width = pImg->width; height = pImg->height; step = pImg->widthStep/sizeof(uchar); data = (uchar*)pImg->imageData; channels = pImg->nChannels; width_xz = pImg_xz->width; height_xz = pImg_xz->height; step_xz = pImg_xz->widthStep/sizeof(uchar); data_xz = (uchar*)pImg_xz->imageData; channels_xz = pImg_xz->nChannels; width_xz=int(width_xz/2); //取中心位置 height_xz=int(height_xz/2); //取中心位置

C语言图像处理函数大全

C语言图像处理函数大全,完整版 ? ?1.图像平移 图像平移只是改变图像在屏幕上的位置,图像本身并不发生变化。 假设原图像区域左上角坐标为(x0, y0),右下角坐标为(x1, y1),将图像分别沿x和y轴平移dx和dy,则新图像的左上角坐标为(x0 +dx, y0+dy),右下角坐标为(x1+dx, y1+dy)。坐标平移变换公式为:x′ = x +dx y′ = y +dy 在屏幕上实现图像的移动分为四个步骤: ⑴保存原图像到缓冲区。 ⑵擦除原图像。 ⑶计算平移后的新坐标。 ⑷在新的坐标位置重新显示原图像。 其中,擦除原图像的方法与图形变换中擦除原图形的方法一致,在实现中仍采用XOR异或方式画图擦除原图像。对于新坐标值的计算还需要考虑边界情况,不要在图像平移后超出允许的屏幕范围。此外,如果采用C函数getimage()和putimage()来保存和恢复图像,则图像的大小不能超过64K。 2.图像颠倒 图像颠倒是指把定义好的图像区域上下翻转地显示在屏幕上。分析图像颠倒的过程,可发现每行的图像信息都保持不变,而只是改变了行的顺序,将第一行与最后的第n行相互交换,第二行与第n-1行交换……,依此类推,从而实现了图像的颠倒。只需采用按行交换的方式,即可方便地修改缓冲区内容,实现图像的颠倒。基本步骤如下: (1) 用getimage()保存原图像,并擦除原图像。 (2) 计算图像的高度,即行数height;计算图像宽度width;计算保存一行图像信息 height = bottom -top +1; width = right -left +1; linebytes = (width +7) /8 *4; (3)利用行交换缓冲区linebuf在图像内存缓冲区中进行信息交换,即把第一行与最末行交换,第2行与第n-1行交换……,依此类推,直至全部交换完毕。 (4)把交换后的图像缓冲区内容重新显示在屏幕上。 3.图像镜像变换 镜像变换是指将指定区域的图像左右翻转地显示在屏幕。分析镜像变换过程可以发现:每行图像信息的处理方式是相同的,而且行顺序不发生变化,只是每一行的像素信息按从左到右的顺序进行了左右颠倒,从而实现了镜像变换。因此,采用按行逐点变换的方式实现图像的镜像。 首先,对于左上角为(left, top),右下角为(right, bottom)矩形区域图像,给出其中任意点(x0, y0)镜像变换后的新坐标(x′, y′)的坐标变换公式: x = right -x0 +left y′ = y0 根据以上公式,对各个像素点计算新坐标后,直接把它显示在屏幕的相应位置上。 如果完全逐点地进行交换,处理一个像素点就要读取一次像素值,从而降低了变换速度。由于像素点是顺序存放在各个bit位上,每读取一个字节就包含了8个像素点的信息,只需设置不同的位屏值bitmask,

图像旋转MATLAB代码实现

图像旋转MATLAB代码实现插值时采用了最近点法和双线性插值,结果与imrotate函数进行了比较。 myImrotate.m %实现Imrotate函数. clc;clear all;close all; Img=imread('E:\eye.bmp'); Img=double(Img); [h w]=size(Img); alpha=pi/4; %逆时针旋转的角度 wnew=w*cos(alpha)+h*sin(alpha); %新图像的宽width hnew=w*sin(alpha)+h*cos(alpha); %新图像的高heighth wnew=ceil(wnew); %取整 hnew=ceil(hnew); u0=w*sin(alpha); %平移量 T=[cos(alpha),sin(alpha);-sin(alpha),cos(alpha)]; %变换矩阵 Imgnew2=zeros(hnew,wnew);Imgnew1=zeros(hnew,wnew); for u=1:hnew %u和v是新图像坐标,变换到原图像坐标x和y中。 for v=1:wnew tem=T*([u;v]-[u0;0]); x=tem(1); y=tem(2); if x>=1&x<=h&y>=1&y<=w %若变换出的x和y在原图像范围内

x_low=floor(x); x_up=ceil(x); y_low=floor(y); y_up=ceil(y); if (x-x_low)<=(x_up-x) %采用最近点法,选取距离最近点的像素赋给新图像x=x_low; else x=x_up; end if (y-y_low)<=(y_up-y) y=y_low; else y=y_up; end p1=Img(x_low,y_low); %双线性插值,p1到p4是(x,y)周围的四个点p2=Img(x_up,y_low); p3=Img(x_low,y_low); p4=Img(x_up,y_up); s=x-x_low; t=y-y_low; Imgnew1(u,v)=Img(x,y); Imgnew2(u,v)=(1-s)*(1-t)*p1+(1-s)*t*p3+(1-t)*s*p2+s*t*p4;

C语言模拟时钟转动课设报告-附代码

模拟时针转动程序 姓名: 学号: 完成日期:2012年12月

设计目的 加深对讲授内容的理解,尤其是一些语法规定。通过课程设计,自然地、熟练地掌握。熟悉所用的计算机系统的操作方法,也就是熟悉语言程序开发的环境。学会上机调试程序。熟悉C语言图形模式下的编程,掌握利用C语言相关函数开发电子时钟的基本原理。 能模拟机械钟表行走;要准确地利用数字显示时间;在屏幕上显示一个活动时钟;程序界面设计合理,色彩得体大方,显示正确;各指针运动规律正确;数字式时钟的时间显示与指针式时钟显示一致。 总体设计 电子时钟的功能描述

电子时钟流程图 模块描述 动画处理模块在屏幕上显示sin和cos型的动态函数图像,显示运动的问候语。 转时针动处理模块指针式的时钟表盘为椭圆形并且圆周上有分布均匀的12个刻度刻度显示清楚钟面上有长度不相同的指针即时针、分针、秒针指针的运动具有规律性为顺时针。 数字时钟处理模块数字钟显示时间的格式是年月日时分秒小时为24进制,分钟和秒是60进制,指针式的时钟和数字式的时钟显示的时间同步且两个时钟所显示的时间与计算机的系统时间一致。 详细设计 time结构体 strume time { usigned char ti_min; usigned char ti_hour; usigned char ti_hud; usigned char ti_sec; }; time 结构体定义在dos.h文件中,可以保存系统的当前时间。

double h,m,s;这三个变量分别保存小时,分钟,秒。 double x,y,x1,y1,x2,y2;保存数字时钟中小时分钟秒在屏幕中显示的位置。 struct time t[1];定义一个time结构类型的数组。 函数功能的描述 1.def() 函数原型: void def() def()函数是用来输出一组彩带的,通过输入位置和颜色的变化来输出sin型的彩带,且在整个函数中保留结果。 2. abc() 函数原型: void abc() abc()函数是用来在退出系统是输出运动的问候语,函数类型单一且比较简单。 3 .digitclock() 函数原型:void digitclock() digitclock函数用于在(x,y)位置显示clock值,clock值为时分秒。 4. clockhandle() 函数原型:void clockhandle() clockhandle()函数用于完成时针转动和数字时钟的显示,包括时针转动角度的运算,还有对声音的输出。

相关主题
文本预览
相关文档 最新文档