求双线性差值算法的图像旋转代码---------大家帮帮忙啊,有谁以前写过或者是在哪找到过这样的代码,帮帮我这个初学者吧
图像旋转的代码我会写,但是要求用双线性差值写旋转,我就不会了,请大侠们帮忙啊。。。。。。
[解决办法]
我查了一下双线性差值的公式是:
对于一个目的像素,设置坐标通过反向变换得到的浮点坐标为(i+u,j+v),其中i、j均为非负整数,u、v为[0,1)区间的浮点数,则这个像素得值 f(i+u,j+v) 可由原图像中坐标为 (i,j)、(i+1,j)、(i,j+1)、(i+1,j+1)所对应的周围四个像素的值决定,即:
f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)
其中f(i,j)表示源图像(i,j)处的的像素值,以此类推
[解决办法]
我这书上有类似的代码 你可以参考研究
HGLOBAL CDibImage::RotateDIB2(LPSTR lpDIB, int iRotateAngle)
{
LONGlWidth;// 源图像的宽度
LONGlHeight;// 源图像的高度
LONGlNewWidth;// 旋转后图像的宽度
LONGlNewHeight;// 旋转后图像的高度
LONGlNewLineBytes;// 旋转后图像的宽度(lNewWidth ',必须是4的倍数)
LPSTRlpDIBBits;// 指向源图像的指针
HDIBhDIB;// 旋转后新DIB句柄
LPSTRlpDst;// 指向旋转图像对应象素的指针
LPSTRlpNewDIB;// 指向旋转图像的指针
LPSTRlpNewDIBBits;
LPBITMAPINFOHEADER lpbmi;// 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPCOREHEADER lpbmc;// 指向BITMAPCOREINFO结构的指针
LONGi;// 循环变量(象素在新DIB中的坐标)
LONGj;
FLOATi0;// 象素在源DIB中的坐标
FLOATj0;
floatfRotateAngle;// 旋转角度(弧度)
floatfSina, fCosa;// 旋转角度的正弦和余弦
// 源图四个角的坐标(以图像中心为坐标系原点)
floatfSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;
// 旋转后四个角的坐标(以图像中心为坐标系原点)
floatfDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4;
floatf1,f2;
lpDIBBits = FindDIBBits(lpDIB);// 找到源DIB图像象素起始位置
lWidth = DIBWidth(lpDIB);// 获取图像的宽度
lHeight = DIBHeight(lpDIB);// 获取图像的高度
// 将旋转角度从度转换到弧度
fRotateAngle = (float) RADIAN(iRotateAngle);
fSina = (float) sin((double)fRotateAngle);// 计算旋转角度的正弦
fCosa = (float) cos((double)fRotateAngle);// 计算旋转角度的余弦
// 计算原图的四个角的坐标(以图像中心为坐标系原点)
fSrcX1 = (float) (- (lWidth - 1) / 2);
fSrcY1 = (float) ( (lHeight - 1) / 2);
fSrcX2 = (float) ( (lWidth - 1) / 2);
fSrcY2 = (float) ( (lHeight - 1) / 2);
fSrcX3 = (float) (- (lWidth - 1) / 2);
fSrcY3 = (float) (- (lHeight - 1) / 2);
fSrcX4 = (float) ( (lWidth - 1) / 2);
fSrcY4 = (float) (- (lHeight - 1) / 2);
// 计算新图四个角的坐标(以图像中心为坐标系原点)
fDstX1 = fCosa * fSrcX1 + fSina * fSrcY1;
fDstY1 = -fSina * fSrcX1 + fCosa * fSrcY1;
fDstX2 = fCosa * fSrcX2 + fSina * fSrcY2;
fDstY2 = -fSina * fSrcX2 + fCosa * fSrcY2;
fDstX3 = fCosa * fSrcX3 + fSina * fSrcY3;
fDstY3 = -fSina * fSrcX3 + fCosa * fSrcY3;
fDstX4 = fCosa * fSrcX4 + fSina * fSrcY4;
fDstY4 = -fSina * fSrcX4 + fCosa * fSrcY4;
// 计算旋转后的图像实际宽度
lNewWidth = (LONG)(max(fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2)) + 0.5);
lNewLineBytes = WIDTHBYTES(lNewWidth * 8);
// 计算旋转后的图像高度
lNewHeight = (LONG)(max(fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2)) + 0.5);
f1 = (float) (-0.5 * (lNewWidth - 1) * fCosa - 0.5 * (lNewHeight - 1) * fSina
+ 0.5 * (lWidth - 1));
f2 = (float) ( 0.5 * (lNewWidth - 1) * fSina - 0.5 * (lNewHeight - 1) * fCosa
+ 0.5 * (lHeight - 1));
// 分配内存,以保存新DIB
hDIB = (HDIB) ::GlobalAlloc(GHND, lNewLineBytes * lNewHeight +
*(LPDWORD)lpDIB + PaletteSize(lpDIB));
if (hDIB == NULL)
{
return NULL;
}
lpNewDIB = (char * )::GlobalLock((HGLOBAL) hDIB);
// 复制DIB信息头和调色板
memcpy(lpNewDIB, lpDIB, *(LPDWORD)lpDIB + PaletteSize(lpDIB));
// 找到新DIB象素起始位置
lpNewDIBBits = FindDIBBits(lpNewDIB);
lpbmi = (LPBITMAPINFOHEADER)lpNewDIB;
lpbmc = (LPBITMAPCOREHEADER)lpNewDIB;
// 更新DIB中图像的高度和宽度
if (IS_WIN30_DIB(lpNewDIB))
{
// 对于Windows 3.0 DIB
lpbmi-> biWidth = lNewWidth;
lpbmi-> biHeight = lNewHeight;
}
else
{
// 对于其它格式的DIB
lpbmc-> bcWidth = (unsigned short) lNewWidth;
lpbmc-> bcHeight = (unsigned short) lNewHeight;
}
for(i = 0; i < lNewHeight; i++)// 针对图像每行进行操作
{
for(j = 0; j < lNewWidth; j++)// 针对图像每列进行操作
{
// 指向新DIB第i行,第j个象素的指针
// 注意此处宽度和高度是新DIB的宽度和高度
lpDst = (char *)lpNewDIBBits + lNewLineBytes * (lNewHeight - 1 - i) + j;
// 计算该象素在源DIB中的坐标
i0 = -((float) j) * fSina + ((float) i) * fCosa + f2;
j0 = ((float) j) * fCosa + ((float) i) * fSina + f1;
// 利用双线性插值算法来估算象素值
*lpDst = Interpolation (lpDIBBits, lWidth, lHeight, j0, i0);
}
}
return hDIB;
}
[解决办法]
书名是: 数字图象处理典型算法及实现
第四章
它的做法是先平移到图的中心,然后做旋转,
可以得到坐标,然后进行双线性插值
[解决办法]
用变换过的uv乘以旋转矩阵的逆矩阵就得到原来的uv,再用这个uv做双线性插值。
你自己在二楼已经说的很清楚了。
伪代码如下:
for ( int i = 0; i < width; i++ )
{
for ( int j = 0; j < height; j++ )
{
float u = GetSrcU(i,j);
float v = GetSrcV(i,j);
newImage[j*height + i] = BilinearInterpolation(u,v);
}
}