序号:
学号: ********
课 程 设 计
设计课程名称: C语言课程设计
题 目: 数字图像处理—几何变换1
学 生 姓 名: ***
学 院(系): ******* 专 业 班 级: *****
指 导 教 师: *** 专业技术职务: *****
设计时间: **** 年 *月 ** 日 ~ **** 年 * 月 **
目录
1、系统的意义以及主要功能............................................................................................... 2
1.1系统的意义...................................................................................................................... 2
1.2图像的功能...................................................................................................................... 2
2、整个系统的功能结构图以及调用关系.......................................................................... 2
3、各个功能实现流程图........................................................................................................ 2
3.1彩色图像变成灰度图像..................................................................................................... 2
3.2几何变换之--旋转............................................................................................................ 3
3.3几何变换之--镜像............................................................................................................ 3
4、调试运行,程序的界面以及输入数据,以及输出结果............................................ 4
4.1原图................................................................................................................................. 4
4.2彩色图像变为灰度图像..................................................................................................... 4
4.3灰度图像水平镜像............................................................................................................ 4
4.4灰度图像垂直镜像............................................................................................................ 5
4.5彩色图像水平镜像............................................................................................................ 5
4.6彩色图像垂直镜像............................................................................................................ 5
4.7灰度图像旋转(48)............................................................................................................ 6
4.8彩色图像旋转(90)............................................................................................................ 6
5、使用说明............................................................................................................................. 6
6、C语言源程序代码............................................................................................................. 7
7、心得体会........................................................................................................................... 12
8、实习日志........................................................................................................................... 13
9、参考文献........................................................................................................................... 13
~ 1 ~
1、系统的意义以及主要功能
1.1系统的意义
目前图像处理的应用越来越广泛,已经渗透到工业、航空航天、军事等各领域,在国民经济中发挥越来越大的作用
1.2图像的功能
读入一幅彩色的数字图像,完成一系列的几何运算,并输出每个运算的效果图
1.将彩色图像变为灰度图像
2.将灰度图像旋转任意角度;并对彩色图像进行相应旋转
3.将灰度图像和彩色图像进行水平镜像和垂直镜像
2、整个系统的功能结构图以及调用关系
3、各个功能实现流程图
3.1彩色图像变成灰度图像
3.2几何变换之--旋转 3.3几何变换之--镜像
~ 3 ~
4、调试运行,程序的界面以及输入数据,以及输出结果
4.1原图
4.2彩色图像变为灰度图像
4.3灰度图像水平镜像
4.4灰度图像垂直镜像
4.5彩色图像水平镜像
4.6彩色图像垂直镜像
4.7灰度图像旋转(48)
4.8彩色图像旋转(90)
5、使用说明
编译链接后出现对话框和原始图片,按任意键即可在对话框中输入,根据对话框提示输入数字完成对应功能,出现功能图像按任意键摧毁窗口,即可继续输入完成对应功能。输入0结束变换,按任意键退出对话框。
~ 6 ~
6、C语言源程序代码
#include "mydll.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define PI 3.14159265
void main()
{
double maxa(double a,double b);//最大值
void hd(int wide,int height,unsigned char*pdata,unsigned char*gray); //灰度
void spjx(int wide,int height,unsigned char*pdata,int numcolors); //水平镜像
void czjx(int wide,int height,unsigned char*pdata,int numcolors); //垂直镜像
void hdxz(int wide,int height,struct image*p1,struct image *p2,int k); //旋转
struct image img1,img2,*p2=&img2,*p1=&img1;
unsigned char *pdata,*gray;
int i,k,n=3,m;
int wide,height;
imgfiletomat("G:\\ 1.jpg", &img1); //显示原始图像
createwindow("原图");
imgshow("原图",&img1);
wait(0); //等待按键
destroywindow("原图");
height=img1.height;//像素高度
wide=img1.width; //像素宽度
for(i=0;(n!=0);i++)
{
printf("\n\n\n");
printf("\t\t----------------------------------------------------------------------\n");
printf("\t\t| 图像几何变换 |\n");
printf("\t\t----------------------------------------------------------------------\n");
printf("\t\t| [1]----灰 度 |\n");
printf("\t\t| [2]----水平镜像 |\n");
printf("\t\t| [3]----垂直镜像 |\n");
printf("\t\t| [4]----旋 转 |\n");
printf("\t\t| [0]----退出系统 |\n");
printf("\t\t+*·*·*·*·*·*·*·*·*·*·*·*·*·*·*·*·*·*·*·*·*·*·**·*·*·*·*|\n");
printf("\t\t----------------------------------------------------------------------\n");
printf("请输入:");
scanf("%d",&n);
switch(n)
{
case 0: break; ~ 7 ~
case 1: imgfiletomat("G:\\ 1.jpg", &img1);pdata=img1.ptr;
if(img1.numcolors==3)
{
img1.numcolors=1;img1.ptr=gray=(unsignedchar*)malloc(wide*height);
hd(wide,height,pdata,gray);
createwindow("灰度图");
imgshow("灰度图",&img1);
wait(0); //等待按键
mattoimgfile("G:\\ c1.jpg",&img1);
free(gray);
gray=NULL;
destroywindow("灰度图");
}
else
{
printf("\t\t+***************************************|\n");
printf(" 请换彩色图 \n");
printf("\t\t+**************************************|\n");
}
break;
case 2: printf("\t\t+***************************************|\n");
printf("\t\t [1]----彩色水平镜像 \n");
printf("\t\t [2]----灰度水平镜像 \n");
printf("\t\t+***************************************|\n");
printf("请输入:");
scanf("%d",&m);
if(m==1)
{imgfiletomat("G:\\ 1.jpg", &img1);pdata=img1.ptr;}
else
{imgfiletomat("G:\\ c1.jpg", &img1);pdata=img1.ptr;}
spjx(wide,height,pdata,img1.numcolors);
createwindow("水平镜像图");
imgshow("水平镜像图",&img1);
wait(0); //等待按键
destroywindow("水平镜像图");
break;
case 3: printf("\t\t+***************************************|\n");
printf("\t\t [1]----彩色垂直镜像 \n");
printf("\t\t [2]----灰度垂直镜像 \n");
printf("\t\t+***************************************|\n");
printf("请输入:");
scanf("%d",&m);
if(m==1) ~ 8 ~
{imgfiletomat("G:\\ 1.jpg", &img1);pdata=img1.ptr;}
else
{imgfiletomat("G:\\ c1.jpg", &img1);pdata=img1.ptr;}
czjx(wide,height,pdata,img1.numcolors);
createwindow("垂直镜像图");
imgshow("垂直镜像图",&img1);
wait(0); //等待按键
destroywindow("垂直镜像图");
break;
case 4: printf("\t\t+***************************************|\n");
printf("\t\t [1]----彩色旋转镜像 \n");
printf("\t\t [2]----灰度旋转镜像 \n");
printf("\t\t+***************************************|\n");
printf("请输入:");
scanf("%d",&m);
if(m==1)
{imgfiletomat("G:\\ 1.jpg", &img1);pdata=img1.ptr;}
else
{imgfiletomat("G:\\ c1.jpg", &img1);pdata=img1.ptr;}
printf("输入旋转角度:\t");
scanf("%d",&k);
hdxz(wide,height,p1,p2,k);
createwindow("旋转");
imgshow("旋转",&img2);
wait(0); //等待按键
destroywindow("旋转");
break;
default:
printf("\t\t+***************************************|\n");
printf(" 输入错误 \n");
printf("\t\t+***************************************|\n");
}
}
destroyallwindows();
}
double maxa(double a,double b)
{
return (a>b?a:b);
}
//灰度
void hd(int wide,int height,unsigned char*pdata,unsigned char*gray)
{
int i,j,k=0;
for(i=0;i<height;i++)//进行遍历元素 ~ 9 ~
for(j=0;j<wide;j++)
{//将原图RGB的值根据公式赋给新开辟的空间
*(gray++)=(*(pdata+k)*11+*(pdata+k+1)*59+*(pdata+k+2)*30)/100;
k+=3;
}
}
//水平镜像
void spjx(int wide,int height,unsigned char*pdata,int numcolors)
{
unsigned char*temp,*ogray,*ngray,*p=pdata;
int i,j,k,n=numcolors,m;
temp=(unsigned char*)malloc(wide*height*numcolors); //开辟一个空间用以存放数据
for(i=0;i<height;i++)//对元素进行遍历
{
k=wide*n-1;
for(j=0;j<wide;j++)
{
for(m=numcolors;m>0;m--)//灰度与彩色的转换
{
ogray=pdata++;//遍历原图每一个值
ngray=temp+wide*i+k-j*numcolors-(m-1);//对应新开辟空间的地址
*ngray=*ogray;//把数据存放在新开辟的空间里
}
}
if(numcolors==3)
n+=2;
}
memcpy(p,temp,wide*height*numcolors);//数据拷贝
free(temp);//释放开辟的空间
temp=NULL;//防止野指针
}
//垂直镜像
void czjx(int wide,int height,unsigned char*pdata,int numcolors)
{
unsigned char*temp,*lpdst,*lpsrc;
int i,j;
temp=(unsigned char*)malloc(wide*height*numcolors);//开辟一个空间用以存放数据
for(i=0;i<wide*numcolors;i++)//遍历数据并把数据存放在新开辟的空间里
for(j=0;j<height;j++)
{
lpsrc=pdata+wide*numcolors*j+i;//数据地址
lpdst=temp+wide*numcolors*(height-1-j)+i;//相应新开辟的空间的地址
*lpdst=*lpsrc;//把数据存放在新开辟的空间里
} ~ 10 ~
memcpy(pdata,temp,wide*height*numcolors);//数据拷贝
free(temp);//释放开辟的空间
temp=NULL;//防止野指针
}
//灰度图旋转
void hdxz(int wide,int height,struct image*p1,struct image *p2,int k)
{
unsigned char*temp,*pdata;
double offx1,offy1,offx2,offy2;//原图四个角的坐标
double offx3,offy3,offx4,offy4;
double nffx1,nffy1,nffx2,nffy2;//新图四个角的坐标
double nffx3,nffy3,nffx4,nffy4;
double cosa,sina,a,b;
int x0,y0,x1,y1,nwide,nheight,n=0,m=0;
pdata=p1->ptr;
cosa=cos(PI*k/180.0); //角度变弧度
sina=sin(PI*k/180.0);
offx1 = -0.5 * wide;//以中心为原点计算原图四个角的坐标
offy1 = 0.5 * height;
offx2 = 0.5 * wide;
offy2 = 0.5 * height;
offx3 = -0.5 * wide;
offy3 = -0.5 * height;
offx4 = 0.5 * wide;
offy4 = -0.5 * height;
nffx1 = cosa * offx1 + sina * offy1;//旋转后新图四个角的坐标
nffy1 = -sina * offx1 + cosa * offy1;
nffx2 = cosa * offx2 + sina * offy2;
nffy2 = -sina * offx2 + cosa * offy2;
nffx3 = cosa * offx3 + sina * offy3;
nffy3 = -sina * offx3 + cosa * offy3;
nffx4 = cosa * offx4 + sina * offy4;
nffy4 = -sina * offx4 + cosa * offy4;
nwide=(int)(maxa(fabs(nffx4-nffx1),fabs(nffx3-nffx2))+0.5);//新图的宽和高
nheight=(int)(maxa(fabs(nffy4-nffy1),fabs(nffy3-nffy2))+0.5);
p2->width=nwide;//给img2赋值
p2->height=nheight;//给img2赋值
p2->numcolors=p1->numcolors;//给img2赋值
//开辟一个空间用以存放数据
p2->ptr=temp=(unsigned char *)malloc(nwide*nheight*(p2->numcolors));
a = - 0.5 * nwide * cosa - 0.5 * nheight * sina + 0.5 * wide;//旋转常值
b = 0.5 * nwide * sina - 0.5 * nheight * cosa + 0.5 * height;//旋转常值
if(p2->numcolors==3)//判断灰度图,彩色图
{ ~ 11 ~
for(y1=0;y1<nheight;y1++)//进行彩色图元素遍历
{
for(x1=0;x1<nwide;x1++)
{
x0=(int)(x1*cosa+y1*sina+a);//算出新坐标对应的原图坐标
y0=(int)(-x1*sina+y1*cosa+b);
//判断是否超过原图,超过赋255
if((x0<wide)&&(x0>=0)&&(y0<height)&&(y0>=0))
{ //将原图RGB值赋予新开辟空间对应的位置
*(temp++)=*(pdata+y0*wide*p2->numcolors+m);
*(temp++)=*(pdata+y0*wide*p2->numcolors+m+1);
*(temp++)=*(pdata+y0*wide*p2->numcolors+m+2);
}
else
{
*(temp++)=255;//将没有对应点的值赋255,使其变白色
*(temp++)=255;
*(temp++)=255;
}
}
m+=3;
}
}
else
{ //进行灰度图元素遍历
for(y1=0;y1<nheight;y1++)
for(x1=0;x1<nwide;x1++)
{
x0=(int)(x1*cosa+y1*sina+a);//算出新坐标对应的原图坐标
y0=(int)(-x1*sina+y1*cosa+b);
//判断是否超过原图,超过赋255
if((x0<wide)&&(x0>=0)&&(y0<height)&&(y0>=0))
*(temp++)=*(pdata+y0*wide+x0);//将原图的值赋予新开辟空间对应的位置
else
*(temp++)=255;//将没有对应点的值赋255,使其变白色
}
}
}
7、心得体会
刚开始并不了解图像如何用vc来进行几何变换,后来经过初步认识,了解到各门
~ 12 ~
学科的联系,c语言中用到了很多算法和数学有着紧密的联系,感受到数组与指针的强
大,编程需要注意细节,不然犯错了在去找问题所在很难找出问题错在哪里。基础知识要熟练掌握,多上机,发现问题解决问题,才能在今后编程中少犯错误。
8、实习日志
6月17日
安排:学习图像基本知识,完成彩色图像变灰度图像
进度:完成了图像灰度,但并没有真正灰度(numcolors=3)
6月19日
安排:解决上次问题,完成水平镜像(彩色和灰度图像)
进度:解决了上次问题,完成灰度图像的水平镜像,彩色图像水平镜像出现问题
遇到的问题:彩色图像水平镜像后颜色改变(RGB值赋错)
解决办法:调整指针指向(使RGB值赋对)
6月24日
安排:解决上次问题,完成垂直镜像(彩色和灰度图像)
进度:完成良好
6月26日
安排:完成旋转(彩色和灰度图像)
进度:只完成特殊值得旋转
遇到问题:地址访问错误
解决办法:调试逐句查看,查看哪里地址访问错误
6月27日
安排:完成界面设计,彩色图像旋转
进度:界面设计完成良好,彩色图像仍存在问题
9、参考文献
《VC++数字图像处理》何斌 人民邮电出版社
~ 13 ~