代数运算
????????1加法运算
????????2减法运算(差分)
????????3乘法运算
????????4除法运算
????????5实验结果
????????图像的代数运算是指对两幅图像进行点对点的四则运算而得到一幅新的输出图像。图像的代数运算在图像处理中有着广泛的应用,它除了可以实现自身所需要的算术操作,还能为许多复杂的图像处理提供准备。
1加法运算
C(x,y) = A(x,y) + B(x,y)
????????主要应用去除“叠加性”噪声以及生成图像叠加效果。图像叠加效果的生成过程中会得到二次曝光的效果,通用推广公式为:h(x,y) = a·f(x,y) + b·g(x,y),且a+b=1。
2减法运算(差分)
C(x,y) = A(x,y) - B(x,y)
????????可用于突出图像中的研究对象,通过去除背景效果,能够去除部分系统影响,从而突出观测物体本身。还可以在同一场景中检测不同时间下两幅图像之间的变化。在减法运算中,两幅图像相减,可能会导致图像整体亮度下降,且出现小于0的像素值情况,这部分需要根据图像特点自行处理,比如增强亮度(乘个常量系数)。
3乘法运算
C(x,y) = A(x,y) * B(x,y)
????????可用来遮盖图像中的某些部分(图像掩膜)。乘法必然会出现像素值越界,在此需要整体进行处理(比如除以灰度级)。
4除法运算
C(x,y) = A(x,y) / B(x,y)
????????常用于产生比率图像,这对于多光谱图像的分析十分有用。
5实验结果
//对图像进行代数运算处理ColorLen=256 int?temp?= 0; switch(flag) { case?0: //add ????????temp?= LeftImg[m][i*width+j]/2 + RightImg[m][i*twidth+j]/2; ????????break; case?1: ?//subtract ????????temp?= (LeftImg[m][i*width+j] - RightImg[m][i*twidth+j])*2; ????????break; case?2: ?//multiply ????????temp?= LeftImg[m][i*width+j] * RightImg[m][i*twidth+j]/(ColorLen-1); ????????break; case?3: ?//divide ????????temp?= LeftImg[m][i*width+j]/(ColorLen?- RightImg[m][i*twidth+j]); ????????//temp = LeftImg[m][i*width+j]/(RightImg[m][i*twidth+j]+FLT_EPSILON);//不反色 ????????break; default: ????????cout<<"flag doesn't exist."<<endl; ????????break; } | flag | 输入图像 | 输出图像 | 0 | | | | 1 | | | 2 | | 3 | | 3 不反色 | | 1 | | | |
????????首先,我们发现处理和获得的图片都是彩色的,这里面需要了解彩色图像的处理其实就是多层灰度图像的处理。因此对上面的彩色图片的处理在读入影像后,都分波段的对应灰度图处理即可。
????????在实验代码中,可以发现减法运算为了避免整体亮度过暗,进行了乘2增强整体亮度的做法;乘法运算中避免值域越界除以了灰度级(ColorLen-1);除法运算针对原图像,把图2进行了反色处理,从而能够得到中间的蝴蝶部分,这里如果不反色处理,结果图里蝴蝶部分会是黑色的,而蝴蝶外围将得到超大值越界。当然最后仍需要判断将越界值处理为0或ColorLen-1,从而呈现白色。
????????在实验代码中,我们可以看出LeftImg与RightImg读取像素使用的宽分别为width和twidth。这主要是这里的原始图像宽高存在不一致情况。一般的处理前均需要处理原始影像的,不然就需要在处理过程中对此做出处理。
????????对于最后一个减法运算实验,进行背景的去除,如果单纯的相减将会是全黑的图像,往往需要对差值进行差异化处理。
????????理想状态下应该是得到上图,上图的获得除了减法运算还需要其他的策略进行处理,如差异区域反色处理等。其次还对输入图像有一定的要求:需要两幅输入图像是匹配的且亮度一致,即场景区域完全一致的,做差就可以消除背景。实验中得到的结果比较差,是因为原图像两者长宽不一致,没有匹配上,因此在处理这些数据源之前有必要进行影像的匹配和配准。
void AlgebraicTrans(const char* filename1,const char* filename2,char* savepath,int flag)
{
if (filename1 == NULL || filename2 == NULL || savepath == NULL)
{
cout<<"Error:输入的文件路径有空值存在,请检查!"<<endl;
return ;
}
int width = 0,height = 0,band = 0;
int twidth = 0,theight = 0,tband = 0;
ImgTyp** LeftImg = GDALreadImage(width,height,band,filename1);
ImgTyp** RightImg = GDALreadImage(twidth,theight,tband,filename2);
if (width != twidth || height != theight || band != tband)
{
cout<<"Warning:输入图像的宽高或着波段数不一致!"<<endl;
band = band < tband ? band : tband;
}
ImgTyp** resultImg = new ImgTyp*[band];
for (int n = 0;n < band;n++)
{
resultImg[n] = new ImgTyp[width*height];
//memset(resultImg[n],0,sizeof(ImgTyp)*width*height);
memcpy(resultImg[n],LeftImg[n],sizeof(ImgTyp)*width*height);//以LeftImg为准
}
for (int m = 0; m < band;m++)
{
for (int i = 0; i < height;i++)
{
for (int j = 0;j < width;j++)
{
int temp = 0;
switch(flag)
{
case 0: //add
temp = LeftImg[m][i*width+j]/2 + RightImg[m][i*twidth+j]/2;
break;
case 1: //subtract
temp = (LeftImg[m][i*width+j] - RightImg[m][i*twidth+j])*2;
//if (temp > 50 || temp < -50)//差异处理
//{
// temp += ColorLen-1;
//}
break;
case 2: //multiply
temp = LeftImg[m][i*width+j] * RightImg[m][i*twidth+j]/(ColorLen-1);
break;
case 3: //divide
temp?= LeftImg[m][i*width+j]/(RightImg[m][i*twidth+j]+FLT_EPSILON);
//temp = LeftImg[m][i*width+j]/(ColorLen - RightImg[m][i*twidth+j]);
break;
default:
cout<<"flag doesn't exist."<<endl;
break;
}
if (temp < 0)
{
temp = 0;
}
if (temp > ColorLen-1)
{
temp = ColorLen-1;
}
resultImg[m][i*width+j] = temp;
if (j > twidth)
{
break;
}
}
if (i > theight)
{
break;
}
}
}
SaveImage(resultImg,savepath,width,height,band);
for (int i = 0;i < band;i++)
{
delete []LeftImg[i];
LeftImg[i] = NULL;
}
delete []LeftImg;
LeftImg = NULL;
for (int i = 0;i < tband;i++)
{
delete []RightImg[i];
RightImg[i] = NULL;
}
delete []RightImg;
RightImg = NULL;
for (int i = 0;i < band;i++)
{
delete []resultImg[i];
resultImg[i] = NULL;
}
delete []resultImg;
resultImg = NULL;
}
?????????基础的原理和操作实现和整理了一下,如果文中有什么错误,希望大家在评论中指出来,谢谢!
|