资源描述
图像平移算法流程:
(1) 取得原图的数据区指针。
(2) 通过对话框输入偏移量tx,ty。
(3) 开辟一个同样大小的缓冲区。
(4) 对原图依次循环每个像素,每读入一个像素点(x0,y0),根据它的坐标,找到目标图像的位置(x1=x0-tx,y1=y0-ty),将像素(x0,y0)处的颜色值赋给新图中的(x1,y1)。
for( i = 0; i < wide; i++)
{ for(int j = 0; j < height; j++)
{ // 计算该象素在源DIB中的坐标
lpSrc = (LPBYTE)p_data + lLineBytes * (height - 1 - j) + i;
int i0,j0;
// 计算该象素在新DIB中的坐标
i0 = i+m_Xmove;
j0 = j + m_Ymove;
if( (i0 >= 0) && (i0 < wide) && (j0 >= 0) && (j0 < height)) // 判断是否在新图范围内
{ lpDst = (LPBYTE)temp + lLineBytes *(height - 1 - j0) + i0;
*lpDst = *lpSrc; // 复制象素
}
else
{
* ((unsigned char*)lpDst) = 255; // 对于源图中没有的象素,直接赋值为255
}
}
}
水平垂直镜像
(1) 取得原图的数据区指针。
(2) 开辟一个同样大小的缓冲区。
(3) 每个像素依次循环。
在水平镜像中,将原图中的像素点的水平坐标变成镜像后的坐标(用图像的宽度减去坐标值)在显示到图像上。
垂直镜像中,则对垂直坐标做相应的处理。
for(j = 0; j < height; j++)
for(i = 0; i < wide;i++)
{
lpSrc = (LPBYTE)p_data +wide *j + i;
lpDst = (LPBYTE)temp + wide* j+ wide - i;
*lpDst = *lpSrc;
}
for(i = 0; i < wide;i++)
for(j = 0; j < height; j++)
{
lpSrc = (LPBYTE)p_data + wide * j+i;
lpDst = (LPBYTE)temp + wide * (height - j - 1)+i;
*lpDst = *lpSrc;
}
缩放
算法流程:
(1) 取得原图的数据区指针。
(2) 通过对话框获得放大整数比例:kx,ky。
更改图象的宽度和高度。
(3) 每个像素依次循环。计算该象素在原图象中的坐标,将原图的象素值赋给目标象素相应位置kx*ky个值。
缩小:
for(j = 0; j < newheight-1; j++)
{// 针对图像每列进行操作
for(i = 0; i < newwide-1; i++)
{// 指向新DIB第i行,第j个象素的指针, 注意此处宽度和高度是新DIB的宽度和高度
lpDst = (LPBYTE)hDIB + newwide * j + i;
// 计算该象素在源DIB中的坐标
j0 = (LONG) (j / yzoom + 0.5);
i0 = (LONG) (i / xzoom + 0.5);
if( (i0 >= 0) && (i0 < wide) && (j0 >= 0) && (j0 < height)) // 判断是否在源图范围内
{// 指向源DIB第i0行,第j0个象素的指针
lpSrc = (LPBYTE)p_data + wide * j0 + i0;
*lpDst = *lpSrc; // 复制象素
}
else
*lpDst = 255; // 对于源图中没有的象素,直接赋值为255
}
}
放大:
// 针对图像每行进行操作
for(j = 0; j < height-1; j++)
{ // 针对图像每列进行操作
for(i = 0; i < wide-1; i++)
{ // 指向源DIB第i0行,第j0个象素的指针
lpSrc = (LPBYTE)p_data + wide * j + i;
// 复制象素
for(int n=0;n<k1;n++)
for(int m=0;m<k2;m++)
{
lpDst = (LPBYTE)temp + newwide *(j*k1+ n) + i*k2+m;
*lpDst = *lpSrc;
}
}
}
转置
(1) 取得原图的数据区指针。
(2) 通过对话框输入偏移量tx,ty。
(3) 开辟一个同样大小的缓冲区。
(4) 对原图依次循环每个像素,
每读入一个像素点(x0,y0),根据它的坐标,
找到目标图像的位置(x1=y0,y1=x0),
将像素(x0,y0)处的颜色值赋给新图中的(x1,y1)。
for(j = 0; j < height; j++)
// 针对每行图像每列进行操作
for(i = 0; i < wide;i++)
{
// 指向源DIB第j行,第i个象素的指针
lpSrc = (LPBYTE)p_data+ lLineBytes * j + i;
// 指向转置DIB第i行,第j个象素的指针
// 注意此处wide和height是源DIB的宽度和高度,应该互换
lpDst = (LPBYTE)temp + lNewLineBytes* i+ j;
// 复制象素
*lpDst = *lpSrc;
}
旋转
(1) 以图像的中心为原点,旋转一定的角度。根据下图,将坐标系Ⅰ变成坐标系Ⅱ;
屏幕中的坐标一般是以左上角为原点,向右为x轴正方向、向下为y轴正方向,设其为坐标系Ⅰ。旋转是绕中心坐标轴原点(a,b)进行的,向右为x轴正方向,向上为y轴正方向,设其为坐标系Ⅱ, 如果是绕一个指定点(a,b)旋转,则先要将坐标系平移到该点,再进行旋转,然后平移回新的坐标原点。
(2)根据旋转公式,将该点顺时针旋转α角;
(3)将坐标系Ⅱ变成坐标系Ⅰ。
num1=(double)( -0.5*Wnew*cosa-0.5*Hnew*sina+0.5*Wold);
num2=(double)(0.5*Wnew*sina-0.5*Hnew*cosa+0.5*Hold);
for(y1=0;y1<Hnew;y1++)
{
for(x1=0;x1<Wnew;x1++)
{ //x0,y0为对应的原图上的坐标
x0= (DWORD)(x1*cosa+y1*sina+num1);
y0= (DWORD)(-1.0f*x1*sina+y1*cosa+num2);
if( (x0>=0) && (x0<Wold) && (y0>=0) && (y0<Hold)) //在原图范围内
{
lpPtr=lpSrc+y0*Wold+x0;
lpTempPtr=lpTemp+y1*Wnew+x1;
*lpTempPtr=*lpPtr; //进行象素的复制
}
}
}
非0元素取一:
(1)取得原图的数据区指针。
(2)每个像素依次循环,若该像素灰度值为0,则不变;若该像素灰度值不为0,则置为255。
void HuiDuBianHuanDib::Fei0()//对图像进行非零取一运算
{
LPBYTE p_data; //原图数据区指针
int wide,height; //原图长、宽
p_data=this->GetData (); //取得原图的数据区指针
wide=this->GetWidth ();
height=this->GetHeight ();
for(int j=0;j<height;j++)
for(int i=0;i<wide;i++) //所有像素依次循环
{
if(*p_data!=0) //若像素值不为0
*p_data=255; //将其置为255
p_data++;
}
}
固定阈值:
1)取得原图的数据区指针。
2)通过对话框输入阈值T。
3)所有像素依次循环,若像素灰度值小于T,则将该像素置为0;否则置为255。
3.编程代码
void HuiDuBianHuanDib::GuDing(int YuZhi)//固定阀值运算
{
LPBYTE p_data; //原图数据区指针
int wide,height; //原图长、宽
p_data=this->GetData (); //取得原图的数据区指针
wide=this->GetWidth ();
height=this->GetHeight ();
for(int j=0;j<height;j++)
for(int i=0;i<wide;i++)
{
if(*p_data>YuZhi) //灰度值大于给定阈值,置为255
*p_data=255;
else
*p_data=0; //不大于置为0
p_data++;
}
}
二值图像的黑白点噪声滤波
(1)取得图像大小、数据区,并把数据区复制到缓冲区中;
(2)循环取得各点像素值;
(3)取得该点周围8像素值的平均值;
(4)平均值与该点像素值相比,若大于127.5则把该点颜色反转;
(5)把缓冲区中改动的数据复制到原数据区中。
//用3*3屏蔽窗口的8近邻均值进行滤波
for(int j=1;j<height-1;j++)
{
for(int i=1;i<wide-1;i++)
{
averg=0;
averg=(int)((p_data[(j-1)*wide+(i-1)]+p_data[(j-1)*wide+i]
+p_data[(j-1)*wide+(i+1)]+p_data[j*wide+(i-1)]
+p_data[j*wide+i+1]+p_data[(j+1)*wide+(i-1)]
+p_data[(j+1)*wide+i]+p_data[(j+1)*wide+i+1])/8); //求周围8近邻均值
if(abs(averg-p_temp[j*wide+i])>127.5)
p_temp[j*wide+i]=averg;
}
}
消除孤立黑像素点
(1)取得图像大小、数据区,并把数据区复制到缓冲区中;
(2)循环取得各点像素值;
(3)判断为4连接或8连接;
(4)为4连接时,若该点上下左右4个像素全为白,则该点置白;为8连接时,若该点周围8个像素全为白,则该点置白;
(5) 把缓冲区中改动的数据复制到原数据区中。
// 4连接的情况下,消去上下左右都为255(白点)的孤立黑点
if (connec==4)
{
for (int j=1;j<height-1;j++)
{
for (int i=1;i<wide-1;i++)
{
if (*(p_temp + wide * j + i)==255)
continue;
if((*(p_temp + wide * (j-1) + i)+*(p_temp+
wide* (j+1) + i)+*(p_temp + wide * j + i-1)
+*(p_temp + wide * j + i+1))==255*4)
*(p_data + wide * j + i)=255; }
}
}
// 8连接的情况下,消去周围都为255(白点)的孤立黑点
if (connec==8)
{
for (int j = 1; j < height-1; j ++)
{
for (int i = 1; i < wide-1; i ++)
{
if (*(p_temp + wide * j + i)==255)
continue;
if((*(p_temp + wide * (j-1) + i)+*(p_temp + wide * (j+1) + i)+*(p_temp + wide * j + i-1)+ *(p_temp + wide * j + i-1)+*(p_temp + wide * (j-1) + i-1)+*(p_temp + wide * (j+1) + i+1)+ *(p_temp + wide * (j-1) + i+1)+*(p_temp + wide * (j+1) + i-1))==255*8)
*(p_data + wide * j + i)=255;
}
}
}
3×3均值滤波
(1)取得图像大小、数据区,并把数据区复制到缓冲区中;
(2)循环取得各点像素值;
(3)取得该点周围8像素值的平均值;
(4)把缓冲区中改动的数据复制到原数据区中。
//用3*3屏蔽窗口的8近邻均值进行滤波
for(int j=1;j<height-1;j++)
{
for(int i=1;i<wide-1;i++)
{
averg=0;
//求周围8近邻均值
averg=(int)(p_data[(j-1)*wide+(i-1)]+p_data[(j-1)*wide+i]
+p_data[(j-1)*wide+(i+1)]+p_data[j*wide+(i-1)]
+p_data[j*wide+i+1]+p_data[(j+1)*wide+(i-1)]
+p_data[(j+1)*wide+i]+p_data[(j+1)*wide+i+1])/8;
p_temp[j*wide+i]=averg;
}
}
超限邻域平均法
(1)取得图像大小、数据区,并把数据区复制到缓冲区中;
(2)循环取得各点像素值;
(3)取得该点周围8像素值的平均值;
(4)判断该点的像素值是否大于平均值,若大于平均值则将平均值赋于该点,否则还保留原像素的灰度值。
(5)把缓冲区中改动的数据复制到原数据区中。
//用3*3屏蔽窗口的8近邻均值进行滤波
for(int j=1;j<height-1;j++)
{
for(int i=1;i<wide-1;i++)
{ averg=0;
//求周围8近邻均值
averg=(int)(p_data[(j-1)*wide+(i-1)]+p_data[(j-1)*wide+i]
+p_data[(j-1)*wide+(i+1)]+p_data[j*wide+(i-1)] +p_data[j*wide+i+1]+p_data[(j+1)*wide+(i-1)] +p_data[(j+1)*wide+i]+p_data[(j+1)*wide+i+1])/8;
if(abs(p_temp[j*wide+i]-averg)>T)
p_temp[j*wide+i]=averg;
}
}
N×N均值滤波器
(1)取得图像大小、数据区,并把数据区复制到缓冲区中;
(2)取得N值;
(3)循环取得各点像素值;
(4)算出以该点像素为中心的N×N屏蔽窗口内平均值;
(5)把该点像素值置为平均值;
(6)把缓冲区中改动的数据复制到原数据区中。
//用N*N屏蔽窗口平均化
for(int j=n2;j<height-n2;j++)
{
for(int i=n2;i<wide-n2;i++)
{ //求N*N屏蔽窗口内的总和sum
sum=0;
for(yy=j-n2;yy<=j+n2;yy++)
for(xx=i-n2;xx<=i+n2;xx++)
sum+=p_data[yy*wide+xx];
//把n*n屏蔽窗口内的平均值四舍五入后作为显示图像像素值
p_temp[j*wide+i]=(int)((float)sum/(n*n)+0.5);
}
}
N*N中值滤波器
(1)取得图像大小、数据区,并把数据区复制到缓冲区中;
(2)取得N值;
(3)循环取得各点像素值;
(4)对以该点像素为中心的N×N屏蔽窗口包括的各点像素值进行排序,得到中间值。
(5)把该点像素值置为中间值;
(6)把缓冲区中改动的数据复制到原数据区中。
for(int j=n2;j<height-n2;j++)
for(int i=n2;i<wide-n2;i++)
{
//把n*n屏蔽窗口部分的所有像素值放入mado[m]
m=0;
for(yy=j-n2;yy<=j+n2;yy++)
for(xx=i-n2;xx<=i+n2;xx++)
{
mado[m]=p_data[yy*wide+xx];
m++;
}
//求中值medi
medi=mado[chuo];
//把中值代入显示图像中
p_temp[j*wide+i]=medi;
}
memcpy(p_data,p_temp,size);
delete p_temp;
十字型中值滤波器
(1)取得图像大小、数据区,并把数据区复制到缓冲区中;
(2)取得N值;
(3)循环取得各点像素值;
(4)计算以该像素为中心的型屏蔽窗口(十字型的纵向和横向的长度为N)内灰度值中值;
(5)把该点像素值置为中间值;
(6)把缓冲区中改动的数据复制到原数据区中。
N×N最大值滤波器
(1)取得图像大小、数据区,并把数据区复制到缓冲区中;
(2)取得N值;
(3)循环取得各点像素值;
(4)取得以该点为中心的N×N屏蔽窗口包括的各点像素值中的最大值;
(5)把该点像素值置为最大;
(6)把缓冲区中改动的数据复制到原数据区中。
if(m_pBitmapInfoHeader->biBitCount<9) //灰度图像
{
//n*n最大值频率滤波
for(int j=n2;j<height-n2;j++)
for(int i=n2;i<wide-n2;i++)
{
//把n*n屏蔽窗口部分复制到mado[m]
m=0;
for(yy=j-n2;yy<=j+n2;yy++)
for(xx=i-n2;xx<=i+n2;xx++)
{
mado[m]=p_data[yy*wide+xx];
m++;
}
//找出mado[m]中的最大值madomax,用作最大频率值
madomax=mado[0];
for(m=1;m<nn;m++)
if(madomax<mado[m])
madomax=mado[m];
p_temp[j*wide+i]=madomax;
}
memcpy(m_pData,p_temp,size);
delete p_temp;
}
纵向微分运算
实现步骤
(1)取得原图的数据区指针。
(2)开辟一块内存缓冲区,并初始化为255。 (3)每个像素依次循环,新图像缓冲区中的当前像素的灰度值等于原图中当前像素的灰度值与其左方的像素的灰度值之差的绝对值。
(4)将缓冲区中的图像复制回原图数据区。
横向
(1)取得原图的数据区指针。
(2)开辟一块内存缓冲区,并初始化为255。
(3)每个像素依次循环,新图像缓冲区中的当前像素的灰度值等于原图中当前像素的灰度值与其上方的像素的灰度值之差的绝对值。
(4)将缓冲区中的图像复制回原图数据区。
双向一次
(1)取得原图的数据区指针。
(2)开辟一块内存缓冲区,并初始化为255。
(3)每个像素依次循环,原图中当前像素的灰度值与其左方的像素的灰度值之差的绝对值的平方,再加上当前像素的灰度值与其上方的像素的灰度值之差的绝对值的平方,所得的平方根即为新图像当前像素的灰度值。
(4)缓冲区中的图像复制回原图数据区。
for(int j=n2;j<height-n2;j++)
for(int i=n2;i<wide-n2;i++)
{
//把n*n屏蔽窗口部分的所有像素值放入mado[m]
m=0;
for(yy=j-n2;yy<=j+n2;yy++)
for(xx=i-n2;xx<=i+n2;xx++)
{
mado[m]=p_data2[yy*wide+xx];
m++;
}
//把mado[m]中的值按下降顺序用冒泡法排序
do{
chg=0;
for(m=0;m<nn-1;m++)
{
if(mado[m]<mado[m+1])
{
madom=mado[m];
mado[m]=mado[m+1];
mado[m+1]=madom;
chg=1;
}
}
}while(chg==1);
//求中值medi
medi=mado[chuo];
//把中值代入显示图像中
p_temp[j*wide+i]=medi;
}
memcpy(p_data,p_temp,size);
delete p_temp;
//轮廓提取
p_data= p_data2;
LPBYTE temp=new BYTE[wide*height]; //新图像缓冲区
//初始化新分配的内存为0
memset( temp,0,sizeof( temp));
for(j=1;j<height-1 ;j++)
for(i=1;i<wide-1 ;i++)
{
if(p_data[j*wide+i]==0)
{
temp[j*wide+i]=0;
n1= p_data[(j+1)*wide+i-1];
n2= p_data[(j+1)*wide+i];
n3= p_data[(j+1)*wide+i+1];
n4= p_data[j*wide+i-1];
n5= p_data[j*wide+i+1];
n6= p_data[(j-1)*wide+i-1];
n7= p_data[(j-1)*wide+i];
n8= p_data[(j-1)*wide+i+1];
//如果相邻的八个点都是黑点
if(n1==n2 && n3==n4 && n5==n6 && n7==n8 && n2==n3 && nn4==n5 &&n6==n7)
temp[j*wide+i]=255;
}
}
memcpy(p_data, temp,wide*height); //复制处理后的图像
delete temp;
}
2.将给定图象的目标物体进行锐化处理及边缘检测。
要求:在一幅带有复杂背景的位图上提取目标物体(数字),对该目标物体进行锐化处理及边缘检测。
任务:
(1)在左视图中打开一幅位图。
(2)制作一个【图像锐化处理及边缘检测】菜单,将消息映射到右视图中,在右视图
中显示位图,完成如下功能:
a. 若是24位彩色图象,将其彩色图像进行灰度变换。
Gray(i,j)=0.11R(i,j)+0.59G(i,j)+0.3B(i,j)
b. 计算该图象的平均灰度值 。
c. 以平均灰度值为基本阈值T1,对此图象的阈值在T1基础上进行调整,对图象进行二值化,使目标与背景分离,提取出目标物体。
d. 应用边缘检测算子,完成目标物体的锐化处理及边缘检测。
展开阅读全文