http://blog.csdn.net/kezunhai
在实际中,图像有可能太大或太小,不利于传输等原因,常常需要对图像进行缩放。加上图像X轴方向的缩放比例为fx,Y轴方向的缩放比例为fy,那么对于原图的(x0,y0)点,对应于缩放后的图像(x1,y1),它们之间有如下关系:
x0 = x1/fx;
y0 = y1/fy;
对于缩小的情况,如果fx=fy=0.5,也即图像被缩放到原图的1/4(宽和高各缩小一半),此时缩小后图像的(0,))位置对应原图的(0,0),(0,1)位置对应原图的(0,2),(1,0)位置对应原图的(2,0),也即每隔一行取一个像素点,每隔一列进行操作;同理,当fx=fy=2时,图像放大到原来的4倍,此时(0,0)对应原图的(0,0),(1,0)对应原图的(0.5,0),而该像素不存在,所以需要进行插值(本文算法采用最近邻插值方法)。
实现代码:
// fx:x方向缩放比例
// fy:y方向缩放比例
void PhotoShop::Zoom(Mat& img, Mat& dst, float fx, float fy)
{
int height = (int)(img.rows*fy+0.5);
int width = (int)(img.cols*fx+0.5);
if ( dst.empty())
dst.create( height,width, img.type());
dst = cv::Scalar::all(0);
int i, j, i0, j0, k;
Size size = dst.size();
int chns = dst.channels();
for ( i= 0; i<size.height; ++i)
{
i0 = (int)(i/fy+0.5); // 在原图的位置行
const unsigned char* srcData = (const unsigned char*)img.data + img.step*i0;
unsigned char* dstData = (unsigned char*)dst.data + dst.step*i;
for ( j=0; j<size.width; ++j)
{
j0 = (int)(j/fx+0.5); // 在原图的列
if ( i0>=0 && i0<img.rows && j0>=0 && j0<img.cols)
{
for ( k=0; k<chns; ++k)
{
dstData[j*chns+k] = srcData[j0*chns+k];
//setPixel(dst, i, j, k, getPixel(img, i0, j0, k));
}
}
else
{
for ( k=0; k<chns; ++k)
{
dstData[j*chns+k] = 255;
//setPixel(dst, i, j, k, 255);
}
}
}
}
}
来张缩小的实验图:
再来张放大的实验图:
从上面的实验图可以看到,缩放后的图像变得比较粗糙,图像质量有所下降。在进行图像缩放时需要进行必要的插值操作,除了最近邻插值法外,还有效果更佳的双线性插值和高阶插值等。
作者:kezunhai 出处:http://blog.csdn.net/kezunhai 欢迎转载或分享,但请务必声明文章出处。