2013-05-12 00:51:22 chen3110008916 阅读数 1212
  • Erdas遥感影像处理入门实战教程(GIS思维)

    《Erdas遥感影像处理入门实战教程》以Erdas2010版本经典界面进行实战教学,设计12章内容,正式教学内容总共45课时,15个小时时长。从软件界面开始,到后的应用,适合入门级、初级、中级的人员学习、工作、教师教学参考。课程根据作者实际工作经验,以及采访学员需求,开展课程设计,实用加实战,会是你学习路上的好帮手。

    4398 人正在学习 去看看 黄晓军

这个学期学习图像处理,颓废了学期的前10周,面临快毕业没前途的压力,觉得要努力做点什么,这两天很努力地自己写图像处理的代码,不再像以前那样能复制则复制,
希望能收获到东西,也希望能对自己负责,不要得过且过,三分钟热度,大学的时光快过完了!
回正题:
代码是在MFC中实现的,里面用到OpenCV的一些函数辅助。

frame02是全局变量:

IplImage*frame02=cvLoadImage("E:\\lena02.jpg");//为了比较快看到效果,位置先选好. int height = frame02->height; //这些IplImage结构体里面的变量用变量去定义只是为了方便自己使用,不是必须的,用后者也是一样的。 int width =frame02->width; int step =frame02->widthStep; int channels = frame02->nChannels; uchar *data = (uchar*)frame02->imageData;



void CDerrickView::On02() //通过菜单项去选择消息反应On02函数

{      

        voidzuoyoujingxiang(IplImage *frame);

        voidshagnxiajingxiang(IplImage *frame);

 

        MessageBox("按下空格键可实现左右镜像对换");

        cvWaitKey(0);

        zuoyoujingxiang(frame02);

 

        MessageBox("按下空格键可实现上下镜像对换");

        cvWaitKey(0);

        shagnxiajingxiang(frame02);

 

        if(cvWaitKey(15)==27)

        {      

               exit(0);

        }

}

/********************************************左右镜像对换************************************************/

void zuoyoujingxiang(IplImage *frame)

{

        //cvFlip(frame,frame02,0);//使用OpenCV提供的函数

        //第三个参数设为0时,为垂直镜像变换;也可设为1,此时为水平镜像变换;也可设为-1,此时为既垂直也水平镜像变换
        IplImage*frame02_1=cvCreateImage(cvGetSize(frame),8,3);

        cvCopy(frame,frame02_1);

        cvNamedWindow("Show02_1");

        cvShowImage("Show02_1",frame02_1);

        intheight    = frame02_1->height; 

        intwidth     = frame02_1->width;    

        intstep      = frame02_1->widthStep;

        intchannels  = frame02_1->nChannels;

        uchar*data      = (uchar*)frame02->imageData;

        uchartemp;//注意中间变量的类型

        for(inti=0;i<height;i++)

               for(intj=0;j<width/2;j++)

                       for(intk=0;k<channels;k++)//如果上面没有变量表示的话,这里将会非常难read。

                       {

                               temp=data[i*step+j*channels+k];

                               data[i*step+j*channels+k]=data[i*step+(width-j)*channels+k];

                               data[i*step+(width-j)*channels+k]=temp;

                       }

        cvShowImage("Show02_1",frame02_1);

               if(cvWaitKey(15)==27)

               {      

                       cvReleaseImage(&frame02_1);

                       cvDestroyWindow("Show02_1");

               }

}


搞掂,程序虽然很短,但是事实上还是花了我不少时间,有时候我真觉得自己悟性太低,这么多东西没注意到,不过没办法,就对这个有多点兴趣,笨就笨啦,
没有我这些笨的,怎么显示聪明人的厉害是吧。

 附一个左右变换的图,上下变换的也一样:


2015-12-02 17:00:40 GarfieldEr007 阅读数 2678
  • Erdas遥感影像处理入门实战教程(GIS思维)

    《Erdas遥感影像处理入门实战教程》以Erdas2010版本经典界面进行实战教学,设计12章内容,正式教学内容总共45课时,15个小时时长。从软件界面开始,到后的应用,适合入门级、初级、中级的人员学习、工作、教师教学参考。课程根据作者实际工作经验,以及采访学员需求,开展课程设计,实用加实战,会是你学习路上的好帮手。

    4398 人正在学习 去看看 黄晓军

第六章 几何运算

目录

  1. 引言
  2. 灰度级插值
  3. 空间变换

3.1 仿射变换

3.2 透视变换

  1. 几何校正
  2. 图象卷绕(Image Warping)
  3. 图象变形(Image Morphing)

作业


1.引言

几何运算与点运算不同,它可改变图象中物体(象素)之间的空间关系。这种运算可以看成将各象素在图象内移动的过程。其定义为:

g(x,y)=f(x',y')=f[a(x,y),b(x,y)] 其中,f(x,y)表示输入图象,g(x,y)表示输出图象,a(x,y)和b(x,y)表示空间变换,若它们是连续的,则将保持图象中的连通关系。

几何运算中灰度级插值是必不可少的组成部分,因为图象一般用整数位置处的象素来定义,而几何变换中,g(x,y)的灰度值一般由处在非整数坐标上的f(x,y)的值来确定,即g中的一个象素一般对应于f中的几个象素之间的位置。反过来看也是一样,即f中的一个象素往往被映射到g中的几个象素之间的位置。

实现几何运算有两种方法,其一为前向映射法,即:将输入象素的灰度一个个地转移到输出图象中,如果一个输入象素被映射到四个输出象素之间的位置,则其灰度值就按插值法在四个输出象素之间进行分配;其二为后向映射法(象素填充法),这时将输出象素逐个地映射回输入图象中,若输出象素被映射到四个输入象素之间的位置,则其灰度由它们的插值来确定。在实际中,通常采用后向映射法。

几何变换常用于摄象机的几何校正过程,这对于利用图象进行几何测量的工作是十分重要的。

仿射变换(Affine Transformation)和图象卷绕(Image Warping)是两类常见的几何运算。前者属于射影几何变换,多用于图象配准(ImageRegistration)作为比较或匹配的预处理过程;后者用控制点及插值过程来定义,将一幅图象逐渐变化到另一幅图象的图象变形(Morphing)过程是其典型的应用,多见于影视特技及广告的制作。

2.灰度级插值

最简单的插值方法是最近邻插值,即选择离它所映射到的位置最近的输入象素的灰度值为插值结果。复杂一点的方法是双线性插值,如下图所示:

假设输出图象的宽度为W,高度为H,输入图象的宽度为w高度为h,要将输入图象的尺度拉伸或压缩变换至输出图象的尺度。按照线形插值的方法,将输入图象的宽度方向分为W等份,高度方向分为H等份,那么输出图象中任意一点(x,y)的灰度值就应该由输入图象中四点(a,b)、(a+1,b)、(a,b+1)和(a+1,b+1)的灰度值来确定(如图1.)。其中a和b的值分别为:

 
 

 

(x,y)点的灰度值f(x, y)应为:

 
 

 

其中

 
 

 

此外,还有多种其它插值方法,如三次样条等。图象处理软件一般都提供若干种插值方法供用户自己选择。

3.空间变换

空间变换包括可用数学函数表达的简单变换(如:平移、拉伸等仿射变换)和依赖实际图象而不易用函数形式描述的复杂变换(如对存在几何畸变的摄象机所拍摄的图象进行校正,需要实际拍摄栅格图象,根据栅格的实际扭曲数据建立空间变换;再如通过指定图象中一些控制点的位移及插值方法来描述的空间变换)。

3.1 仿射变换(affine transformation)

 
 

其中 A 是变形矩阵,b是平移矢量。在2维空间,A可以按如下的四个步骤分解:尺度、伸缩、扭曲、旋转

(1)尺度

 
 

(2)伸缩

 
 

(3)扭曲

 
 

(4)旋转

 
 

即:

图2 人脸图象和掩膜图象

3.2 透视变换(Perspective Transformation)

透视变换是中心投影的射影变换,在用非齐次射影坐标表达时是平面的分式线性变换,具有如下的形式:

 
 

(参见:丘维生,解析几何,北京大学出版社,1996。)

透视变换常用于图象的校正,例如在移动机器人视觉导航研究中,由于摄象机与地面之间有一倾斜角,而不是直接垂直朝下(正投影),有时希望将图象校正成正投影的形式,就需要利用透视变换。

 重投影变换的应用实例(透视变形的校正)

(根据孙健同学的硕士论文摘录改编,祥见:孙健,面向室外移动机器人THMR-III导航的路标识别算法的研究,硕士学位论文,清华大学计算机系,1997.5)

如果将摄取到的图象映射到平行于地面的平面上,其效果相当于摄影机把姿态改变为垂直于地面向下看,就会在这个新的平面上得到物体真实形状。由于这种映射相当于将原图象重新投影到另一个成象面上,故称之为重投影变换,并将映射后得到的图象称为重投影图象。

图3. 重投影示意图

在两个坐标平面之间的投影变换的数学形式如下:

设(x, y)是坐标平面XOY中的一点,(x’,y’)是(x,y)在坐标平面X’OY’中对应的象点,则有

其中a,b,c,d,e,f,u,v都是常量。

确定两个平面之间的投影变换只需要在两个平面上找到四对“物点和象点”,有这四对点的对应关系就可以确定a,b,c,d,e,f,u,v。具体而言,用一个规范化坐标系(平面)作为重投影平面,首先建立从规范化坐标(NormalCoordinate)到原始图象坐标(Oringinal Coordinate)的变换,其形式为

在地面上取定一个矩形(不一定是正方形),要求它的边平行或垂直于车体轴线,这样的矩形在原始图象中显示为一个等腰梯形,如图4.所示。

图4. 规范化坐标系和原始图象坐标系

设A点的坐标为(x1,y1),C点坐标为(x2,y2),则B、D的坐标分别是(φ-x1,y1)和(φ-x2,y2)。经过投影,ABCD四个点依此与规范化坐标系中的(0,0),(1,0),(0,1),(1,1)四个点相对应。把此对应关系代入上式,得

 

 

可以求得如下的各待定常数:

以上变换的逆变换OrgToNormal的形式是

把四对点的对应关系代入上式,得到待定系数的计算方法为:

 其中

公式中只需确定(x1,y1)和(x2,y2),确定这几个参数的方法如图5.所示:

图5. 几何关系参数示意图

(注:“重投影变换”源于:朱志刚,林学闫,“重投影变换在智能移动机器人视觉系统的应用”,模式识别与人工智能,1990,Vol.5,No.2)

4.几何校正

 几何校正通过由已知的控制点(栅格)建立起来的几何变换(.\download_IPCVPR\GeometricsTransformation\GeometricTransformations.htm)进行。

 

左图:走廊的原图象;中图:透视变换将图象中的地砖校正成正方形;右图:透视变换将门的四角(原图最右侧的门,有把手的门)校正成矩形。(图片来源:Andrew Zisserman,Robotics Research Group, University ofOxford, http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/EPSRC_SSAZ/node10.html)

5.图象卷绕(Image Warping)

 图象卷绕是通过指定一系列控制点的位移来定义空间变换的图象变形处理。非控制点的位移根据控制点进行插值来确定。有时利用多项式函数来拟合控制点之间的对应关系,这时称为多项式卷绕(Polynomial Warping)。一般情况下,由控制点将图象分成许多多变形区域,对每个变形区域使用双线性插值函数来填充非控制点。

  =>

6.图象变形(Image Morphing)

 变形是使图象中的一个物体逐渐变形为另外一个物体的过程。从一起始图象出发,利用渐隐(dissolve)技术,使起始图象逐渐“淡出(fadeout)”,而目标图象则逐渐“淡入(fade in)”,同时以对应物体为转换控制对象,通过选择控制点及控制线来建立插值过程,让物体上的点从它们的起始位置逐渐移向对应的终止位置。

 

演示播放(..\Demos\chapter06\morph\ahzmorph.avi)

作业

  1. 使用UleadMorph应用,选择控制点或控制线及网格,观察图象变形,说明原因。
  2. 编制实现透视及仿射变换的程序,通过交互输入参数观察效果。
  3. 有两幅人像摄影照片(例如,一幅是明星的剧照,另一幅是你自己的照片),试设计一个程序,通过少量的交互选择若干重要的控制点,通过图象卷绕将其中一幅照片中的人脸部分用另一个人的脸部替换

返回主目录 返回本章目录

清华大学计算机系 艾海舟

最近修改时间:2001年7月18日

出处:http://media.cs.tsinghua.edu.cn/~ahz/digitalimageprocess/CourseImageProcess.html

2013-05-12 15:09:18 chen3110008916 阅读数 499
  • Erdas遥感影像处理入门实战教程(GIS思维)

    《Erdas遥感影像处理入门实战教程》以Erdas2010版本经典界面进行实战教学,设计12章内容,正式教学内容总共45课时,15个小时时长。从软件界面开始,到后的应用,适合入门级、初级、中级的人员学习、工作、教师教学参考。课程根据作者实际工作经验,以及采访学员需求,开展课程设计,实用加实战,会是你学习路上的好帮手。

    4398 人正在学习 去看看 黄晓军

继续学习图像点操作,关键是熟悉二维图像在内存中的一维数组方式储存的方式。代码如下:

全局变量和菜单栏反应函数:

(上次舍友对我说,“其实不用全局变量,新定义一个类,把要用的数据放public更好啦,全局变量毕竟不太好。”好像有点道理,不过我我是学光信息专业的,学C++算是半路出家,所以很多东西其实不太清楚的。于是先记下来,以后有机会再找找看看啦。

IplImage *frame02=cvLoadImage("E:\\lena02.jpg");
	int height    = frame02->height;  //这些IplImage结构体里面的变量用变量去定义只是为了方便自己使用,不是必须的,用后者也是一样的。
	int width     = frame02->width;	
	int step      = frame02->widthStep;	
	int channels  = frame02->nChannels;
	uchar *data      = (uchar *)frame02->imageData;
void CDerrickView::On02() 
{	
	void zhognjian(IplImage *frame);
	void shantiao(IplImage *frame);

	MessageBox("按下空格键可实现图像从中间开始显示");
	cvWaitKey(0);
	zhognjian(frame02);

	MessageBox("按下空格键可实现栅条显示图像");
	cvWaitKey(0);
	shantiao(frame02);

	if(cvWaitKey(15)==27) 
	{	
	   exit(0);
	}
}
具体实现的子函数:

/*******************************************图像从中间开始显示************************************************/
void zhognjian(IplImage *frame)
{
	IplImage *frame02_3=cvCreateImage(cvGetSize(frame),8,3);
	int height02_3   = frame02_3->height;  
	int width02_3    = frame02_3->width;	
	int step02_3     = frame02_3->widthStep;	
	int channels02_3 = frame02_3->nChannels;
	uchar *data02_3  = (uchar *)frame02_3->imageData;
	int n=1;
	cvNamedWindow("Show02_3");
	for(int i=height/2;i>=0;i--)//注意:如果是height=5,那么,i=height/2=2.
		{	for(int j=0;j<width;j++)
				for(int k=0;k<channels;k++)			
					if(height%2==0)
					{
						if(i==0)//行数为偶数,以5、6行建立模型,小心分析究竟i=0时,i+n是第几行。特别要注意:行数是从0开始的。
						{
							data02_3[i*step+j*channels+k]=data[i*step+j*channels+k];
						}
						else
						{
							data02_3[i*step+j*channels+k]=data[i*step+j*channels+k];
							data02_3[(i+n)*step+j*channels+k]=data[(i+n)*step+j*channels+k];
						}
					}
					else //行数为奇数
					{
						if(i==0)
						{
							data02_3[i*step+j*channels+k]=data[i*step+j*channels+k];
						}
						else
						{
							data02_3[i*step+j*channels+k]=data[i*step+j*channels+k];
							data02_3[(i+n)*step+j*channels+k]=data[(i+n)*step+j*channels+k];
						}
					}
			n+=2;
			cvShowImage("Show02_3",frame02_3);
			cvWaitKey(20);
			if(i==0)
			{break;}
		}	


	if(cvWaitKey(15)==27) 
		{	
			cvReleaseImage(&frame02_3);
			cvDestroyWindow("Show02_3");
		}
}
/*******************************************图像水平栅条显示************************************************/
void shantiao(IplImage *frame)
{
	IplImage *frame02_4=cvCreateImage(cvGetSize(frame),8,3);
	int height02_4   = frame02_4->height;  
	int width02_4    = frame02_4->width;	
	int step02_4    = frame02_4->widthStep;	
	int channels02_4 = frame02_4->nChannels;
	uchar *data02_4  = (uchar *)frame02_4->imageData;
	cvNamedWindow("Show02_4");
	for(int j=0;j<width02_4;j++)
	{
		for(int i=0;i<height02_4;)		
			{
				data02_4[i*step02_4+j*channels02_4+0]=data[i*step+(width-j)*channels+0];
				data02_4[i*step02_4+j*channels02_4+1]=data[i*step+(width-j)*channels+1];
				data02_4[i*step02_4+j*channels02_4+2]=data[i*step+(width-j)*channels+2];
				i+=2;
			}
		for(i=1;i<height02_4;)		
			{
				data02_4[i*step02_4+(width02_4-j)*channels02_4+0]=data[i*step+j*channels+0];
				data02_4[i*step02_4+(width02_4-j)*channels02_4+1]=data[i*step+j*channels+1];
				data02_4[i*step02_4+(width02_4-j)*channels02_4+2]=data[i*step+j*channels+2];
				i+=2;
			}
		cvWaitKey(20);
		cvShowImage("Show02_4",frame02_4);
	}
	if(cvWaitKey(15)==27) 
		{	
			cvReleaseImage(&frame02_4);
			cvDestroyWindow("Show02_4");
		}
}

Okay,搞掂,其实弄清楚了上面的代码后,上下栅条显示,上下显示图像,都是很容易可以写出来的。

呼!改代码的时间比写代码的时间要长的多!给自己的建议,当你陷入局部问题比较久的时候,跳出来,看看大局,整理下思路流程,很可能有收获的。

附效果图:


2013-12-23 22:20:14 Geng19930909 阅读数 832
  • Erdas遥感影像处理入门实战教程(GIS思维)

    《Erdas遥感影像处理入门实战教程》以Erdas2010版本经典界面进行实战教学,设计12章内容,正式教学内容总共45课时,15个小时时长。从软件界面开始,到后的应用,适合入门级、初级、中级的人员学习、工作、教师教学参考。课程根据作者实际工作经验,以及采访学员需求,开展课程设计,实用加实战,会是你学习路上的好帮手。

    4398 人正在学习 去看看 黄晓军

     对图像进行操作,不外乎有点运算,代数运算和空间运算等。

     点运算对单幅图像做处理,不改变像素的空间位置。

     代数运算对多幅图像做处理,不改变像素的空间位置。

     空间运算对单幅图像做处理,但是改变像素的空间位置。

     这里我们要讲的是空间运算,常见的空间运算包括平移,缩放,旋转等等。

     常见的几何运算的算法有2个:空间变换算法和灰度级插值算法。

    灰度级插值:

     1)向前映射法:

       通过输入图像像素位置 计算输出图像对应像素位置,

      将该位置像素的灰度值按某种方式分配到输出图像相邻四个像素。

     

    2)向后映射法:

    通过输出图像像素位置 计算输入图像对应像素位置,

    根据输入图像相邻四个像素的灰度值计算该位置像素的灰度值。

    在实际应用中,由于向前映射法需要多次运算才能得到输出图像,所以使用得不如向后映射法常见。

    在这儿我主要讲向后映射法相关的内容:

    1)最近邻插值法

    对于一个像素点做空间运算时,其输出的灰度或像素值等于其最近的像素点的灰度或像素值。

     对于编程来说,对于输出图像点(Xo,Yo)得到做几何运算之后的点(Xi,Yi),那么在原图像中对应的像素点就为(round(Xi),round(Yi))。

     以下是用Python写的最近邻缩放,lvl表示缩放等级也就是缩放的百分比。

    

#最近邻缩放
def singleZoom(lvl):
    h,w = originalImage.size
    opix = originalImage.load()
    nh = int(round(h * lvl , 0))
    nw = int(round(w * lvl , 0))
    singleImage = Image.new('RGB' , (nh,nw))
    npix = singleImage.load()
    for i in range (nh):
        for j in range (nw):
            npix[i,j] = (255,255,255)
    for i in range (nh):
        for j in range (nw):
            x = int(round(i / lvl , 0))
            y = int(round(j / lvl , 0))
            if (x >= h):
                x = h - 1
            if (y >= w):
                y = w - 1
            npix[i,j] = opix[x,y]

     2)双线性插值法:

     由运算后的点(Xi,Yi)相邻的四个点围城一个正方形,这四个点分别有其对应的灰度值或像素值等,从而确定这个点(Xi,Yi)的灰度值或像素值。

     将问题转换一下叙述就是:

     单位正方形顶点值已知,求正方形内任一点的f(x,y)

     求解方法如下:

    所以就得到了结果,可以根据这个公式来求解像素点的灰度值或像素值。

    以下是用Python写的双线性插值缩放,lvl表示缩放等级也就是缩放的百分比。

   

#双线性缩放
def doubleZoom(lvl):
    h,w = originalImage.size
    opix = originalImage.load()
    nh = int(round(h * lvl , 0))
    nw = int(round(w * lvl , 0))
    singleImage = Image.new('RGB' , (nh,nw))
    npix = singleImage.load()
    for i in range (nh):
        for j in range (nw):
            npix[i,j] = (255,255,255)
    for i in range (nh):
        for j in range (nw):
            xx = i / lvl;
            yy = j / lvl;
            x = int(i / lvl)
            y = int(j / lvl)
            xx = xx - x
            yy = yy - y
            if (0 <= x and x < h - 1 and 0 <= y and y < w - 1):
                f00r = opix[x,y][0]
                f00g = opix[x,y][1]
                f00b = opix[x,y][2]
                f01r = opix[x,y + 1][0]
                f01g = opix[x,y + 1][1]
                f01b = opix[x,y + 1][2]
                f10r = opix[x + 1,y][0]
                f10g = opix[x + 1,y][1]
                f10b = opix[x + 1,y][2]
                f11r = opix[x + 1,y + 1][0]
                f11g = opix[x + 1,y + 1][1]
                f11b = opix[x + 1,y + 1][2]
                r = xx * (f10r - f00r) + yy * (f01r - f00r) + (f11r + f00r - f10r - f01r) * xx * yy + f00r
                g = xx * (f10g - f00g) + yy * (f01g - f00g) + (f11g + f00g - f10g - f01g) * xx * yy + f00g
                b = xx * (f10b - f00b) + yy * (f01b - f00b) + (f11b + f00b - f10b - f01b) * xx * yy + f00b
                r = int(round(r , 0))
                g = int(round(g , 0))
                b = int(round(b , 0))
                npix[i,j] = (r,g,b)



2019-12-10 22:34:34 qq_34562355 阅读数 11
  • Erdas遥感影像处理入门实战教程(GIS思维)

    《Erdas遥感影像处理入门实战教程》以Erdas2010版本经典界面进行实战教学,设计12章内容,正式教学内容总共45课时,15个小时时长。从软件界面开始,到后的应用,适合入门级、初级、中级的人员学习、工作、教师教学参考。课程根据作者实际工作经验,以及采访学员需求,开展课程设计,实用加实战,会是你学习路上的好帮手。

    4398 人正在学习 去看看 黄晓军


图像的几何运算是指引起图像几何形状发生改变的变换。与点运算不同的是,几何运算可以看成是像素在图像内的移动过程,该移动过程可以改变图像中物体对象之间的空间关系。

1.图像的插值

图像插值是指利用已知邻近像素点的灰度值来产生位置像素点的灰度值,以便由原始图像再生成具有更高分辨率的图像。插值是在不生成新的像素的情况下对原图像的像素重新分布,从而改变像素数量的一种方法。在图像放大过程中,像素也相应的增加,增加的过程就是‘插值’发生作用的过程,‘’插值程序自动选择信息较好的像素作为增加、弥补空白像素的空间,而并非只使用近邻的像素,所以在放大图像时,图像看上去会比较平滑、干净。无论使用何种插值方法,首先都需要找到与输出图像像素相对应的输入图像点,然后再通过计算该点附近某一像素集合的权平均值来指定输出像素的灰度值。像素的权是根据像素到点的距离来而定的,不同插值方法的区别就在于考虑的像素集合不同。最常见的插值方法如下:
(1)向前映射法:
通过输入图像像素的位置,计算输出图像对应像素的位置,将该位置像素的灰度值按某种方式分配到输出图像相邻的四个像素。
(2)向后映射法:
通过输出图像像素位置,计算输入图像对应像素的位置,根据输入图像相邻四个像素的灰度值计算该位置像素的灰度值。
(3)最近邻插值:
表示输出像素将被指定为像素点所在位置处的像素值。
(4)双线性插值:
表示输出像素值是像素2×2邻域内的平均值。
(5)双三次插值:
表示输出像素值是像素4×4邻域内的权平均值。
在MATLAB中,interp2函数用于对图像进行插值处理,该函数的调用方法如下:

A=interp2(X,Y,Z,IX,IY):Z为要插值的原始图像,IX和IY为图像的新行和新列
clear all
close all
clc
I2=imread('eight.tif');
subplot(231)
imshow(I2)
title('原始图像')
Z1=interp2(double(I2),2,'nearest');%最近邻插值法
Z1=uint8(Z1);
subplot(232)
imshow(Z1)
title('最近邻插值')
Z2=interp2(double(I2),2,'linear');%线性插值法
Z2=uint8(Z2);
subplot(232)
imshow(Z2)
title('线性插值法')
Z3=interp2(double(I2),2,'spline');%三次样条插值法
Z3=uint8(Z3);
subplot(234)
imshow(Z3);
title('三次样条插值');
Z4=interp2(double(I2),2,'cubic');%立方插值法
Z4=uint8(Z4);
subplot(235);
imshow(Z4);
title('立方插值')

在这里插入图片描述

2.旋转与平移变换

旋转变换的表达式为
在这里插入图片描述
用齐次矩阵表示为
在这里插入图片描述
在MATLAB中,使用imrotate函数来旋转一幅图像,调用格式如下:

B=imrotate(A,ANGLE,METHOD,BBOX)

其中,A是需要旋转的图像;ANGLE是旋转的角度,正值为逆时针;METHOD是插值方法;BBOX表示旋转后的显示方式。
图像的平移变换所用到的是直角坐标系的平移变换公式
在这里插入图片描述
其中x,y表示矩阵的行列方向。
对图像实现旋转变换

clear all
clc
close all
[A,map]=imread('autumn.tif');
J=imrotate(A,40,'bilinear');
subplot(121)
imshow(A,map);
title('原始图像')
subplot(122)
imshow(J,map)
title('旋转后的图像')

在这里插入图片描述
使用不同的插值方法对图像进行旋转

clear all
close all
clc
[I,map]=imread('trees.tif');
J=imrotate(I,35,'bilinear');
J1=imrotate(I,35,'bilinear','crop');%采用双线性插值法,对图像进行水平旋转
J2=imrotate(I,35,'nearest','crop');%采用最近邻插值法,对图像进行水平旋转
J3=imrotate(I,35,'bicubic','crop');%采用双立方插值法,对图像进行水平旋转
subplot(231)
imshow(I,map)
title('原始图像')
subplot(232)
imshow(J,map)
title('双线性插值')
subplot(233)
imshow(J1,map)
title('双线性插值')
subplot(234)
imshow(J2,map)
title('最近邻插值')
subplot(235)
imshow(J3,map)
title('双立方插值')

在这里插入图片描述
对图像进行平移

clear all
close all
clc
A=imread('office_4.jpg');
subplot(121)
imshow(A)
title('原始图像')
A=double(A);
A_move=zeros(size(A));
H=size(A);
A_x=50;
A_y=50;
A_movesult(A_x+1:H(1),A_y+1:H(2),1:H(3))=A(1:H(1)-A_x,1:H(2)-A_y,1:H(3));
subplot(122)
imshow(uint8(A_movesult))
title('平移后的图像')

在这里插入图片描述

3.缩放与裁剪变换

图像的缩放是指在保持原有图像形状的基础上,对图像进行放大或缩小。若在x方向缩放c倍,在y方向缩小d倍,则用齐次矩阵表示为
在这里插入图片描述
在MATLAB中,imresize函数用于改变一幅图像的大小,该函数的调用格式如下

B=imresize(A,M,METHOD)

其中,A是原图像;M为缩放系数;B为缩放后的图像;METHOD为插值方法,可取值‘nearest’,‘bilinear’和‘bicubic’。
图像上的裁剪是指将图像不需要的部分切除,只保留感兴趣的部分。在MATLAB中,imcrop函数用于从一幅图像中抽取一个矩形的部分,该函数的调用格式如下:
I2=imcrop(I):表示交互式地对灰度图像进行剪切,显示图像,允许用鼠标指定裁剪矩形。
X2=imcrop(X,map):表示交互式地对索引图像进行剪切,显示图像,允许用鼠标指定裁剪矩形。
RGB2=imcrop(RGB):表示交互式地对真彩图像进行剪切,显示图像,允许用鼠标指定裁剪矩形。
I2=imcrop(I,rect):表示非交互式地对指定灰度图像进行剪裁,按照指定的矩阵框rect剪切图像,rect四元素向量[xmin,ymin,width,height],分别表示举行的左下角和长度及宽度,这些值在空间坐标中指定。
X2=imcrop(X,map,rect):表示非交互式地对索引图像进行剪裁。
RGB2=imcrop(RGB,rect):表示非交互式地对真彩图像进行剪裁。

clear all
close all
clc
I=imread('football.jpg');
figure;
subplot(131)
imshow(I)
title('原始图像')
I=double(I);
I_en=imresize(I,4,'nearest');%最近邻法标志函数nearest扩大4subplot(132)
imshow(uint8(I_en))
title('扩大4倍后的图像')
I_re=imresize(I,0.5,'nearest');
subplot(133)
imshow(uint8(I_re))
title('缩小2倍后的图像')

在这里插入图片描述
下面利用不同的方法对图像进行缩放

clear all 
clc
close all
i=imread('pout.tif');
j=imresize(i,0.5);
j1=imresize(i,2.5);
j2=imresize(i,0.05,'nearest');%利用不同的方法对图像进行缩放
j3=imresize(i,0.05,'bilinear');
j4=imresize(i,0.05,'bicubic');
subplot(231)
imshow(i)
subplot(232)
imshow(j)
subplot(233)
imshow(j2)
subplot(234)
imshow(j1)
subplot(235)
imshow(j3)
subplot(236)
imshow(j4)

在这里插入图片描述
手动裁剪图像

clear all 
clc
close all
[I,map]=imread('trees.tif');
figure
subplot(121)
imshow(I)
[I2,map]=imcrop(I,map);
subplot(122)
imshow(I2)

在这里插入图片描述
指定剪切区域大小和位置,对图像进行剪切

clear all 
clc
close all
[I,map]=imread('trees.tif');
figure
subplot(121)
imshow(I)
%指定剪切区域的大小和位置,剪切图像,并返回坐标(x,y)和剪切区域rect
[x,y,I2,rect]=imcrop(I,map,[75 68 130 112]);
subplot(122)
imshow(I2)
x,y,rect

在这里插入图片描述

4.镜像变换

镜像变换的特点是左右颠倒或者上下颠倒,图像的镜像分为水平镜像和垂直镜像两种。
水平镜像计算公式为
在这里插入图片描述
由于表示图像的矩阵坐标必须非负,因此需要在进行镜像计算之后,再进行坐标平移。
在这里插入图片描述
垂直镜像计算公式为
在这里插入图片描述
由于表示图像的矩阵坐标必须非负,因此需要在进行镜像计算之后,再进行坐标平移。
在这里插入图片描述
在MATLAB中,flipud函数用于实现对图像的上下翻转;fliplr函数用于实现对图像的左右翻转。
对图像的镜像变换。

clear all 
clc
close all
I=imread('office_4.jpg');
figure
subplot(221)
imshow(I)
title('原始图像')
I=double(I);
h=size(I);
I_fliplr(1:h(1),1:h(2),1:h(3))=I(1:h(1),h(2):-1:1,1:h(3));%水平镜像旋转
I1=uint8(I_fliplr);
subplot(222)
imshow(I1)
title('水平镜像变换')
I_flipud(1:h(1),1:h(2),1:h(3))=I(h(1):-1:1,1:h(2),1:h(3));%垂直镜像变换
I2=uint8(I_flipud);
subplot(223)
imshow(I2)
title('垂直镜像变换')
I_fliplr_flipud(1:h(1),1:h(2),1:h(3))=I(h(1):-1:1,h(2):-1:1,1:h(3));%对角镜像变换(先水平变换再垂直变换)
I3=uint8(I_fliplr_flipud);
subplot(224)
imshow(I3)
title('对角镜像变换')

在这里插入图片描述

图像几何运算

阅读数 1016

图像基本运算

阅读数 1566

没有更多推荐了,返回首页