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 欢迎转载或分享,但请务必声明文章出处。