图像的缩放

一:使用系统默认的插值法(双线性插值)

#include <cv.h>
#include <highgui.h>
#include <math.h>
 
int main(int argc, char* argv[])
{
    IplImage *src = 0;			//源图像指针
    IplImage *dst = 0;			//目标图像指针
    float scale = 2.0;		    //缩放倍数为2倍
    CvSize dst_cvsize;			//目标图像尺寸
 
    /* the first command line parameter must be image file name */
    if ( argc == 2 && (src = cvLoadImage(argv[1], -1))!=0 )
    {
        //如果命令行传递了需要打开的图片就无须退出,所以注释掉下面一行!
	//return -1;
    }
    else
    {
        src = cvLoadImage("src.jpg");    //载入工作目录下文件名为“src.jpg”的图片。
    }
 
    dst_cvsize.width = src->width * scale;		//目标图像的宽为源图象宽的scale倍
    dst_cvsize.height = src->height * scale;	//目标图像的高为源图象高的scale倍
 
    dst = cvCreateImage( dst_cvsize, src->depth, src->nChannels);	//构造目标图象
    cvResize(src, dst, CV_INTER_LINEAR);	//放大源图像到目标图像,采用双线性法。
 
    cvNamedWindow( "src",   CV_WINDOW_AUTOSIZE );	//创建用于显示源图像的窗口
    cvNamedWindow( "dst",   CV_WINDOW_AUTOSIZE );	//创建用于显示目标图像的窗口
 
    cvShowImage( "src", src );		//显示源图像
    cvShowImage( "dst", dst );		//显示目标图像
	cvSaveImage("Lenna_2scale.jpg", dst);
    cvWaitKey(0);		//等待用户响应
 
    cvReleaseImage(&src);	//释放源图像占用的内存
    cvReleaseImage(&dst);	//释放目标图像占用的内存
    cvDestroyWindow( "src" );	//销毁窗口“src”
    cvDestroyWindow( "dst" );	//销毁窗口“dst”
    //void cvDestroyAllWindows(void);
 
    return 0;
}

原图与放大结果


二:使用双线性函数实现图像放大插值

//设x0处的函数值为f(x0), x1处的函数值为f(x1),  设x0 < x < x1,对f(x)进行线性插值可得:
//
//	f(x) = f(x0)*(x1-x)/(x1-x0) + f(x1)*(x-x0)/(x1-x0)
//opencv中默认的图像插值也是双线性插值

#include <cv.h>
#include <highgui.h>
#include <iostream>  
#include <cmath>  
  
using namespace cv;  
using namespace std;  

#define PI 3.14159265  
  
void MyScale(Mat& src, Mat& dst, float TransMat[3][3]);  
  
/** 
 * @function main 
 */  
int main( int argc, char** argv )  
{  
  // load image  
  /*char* imageName = "images/Lenna_256.png";  */
  
  Mat image;  
  image = imread(argv[1],1);  
  if(!image.data)  
  {  
      cout << "No image data" << endl;  
      return -1;  
  }  
  
  // show image  
  namedWindow("image", CV_WINDOW_AUTOSIZE);  
  imshow("image", image);  
    
    
  Mat dst;  
  float transMat[3][3] = { {2.0, 0, 0}, {0, 2.0, 0}, {0, 0, 1} };  
  MyScale(image, dst, transMat);  
  
  namedWindow("out_image", CV_WINDOW_AUTOSIZE);  
  imshow("out_image", dst);  
  
  imwrite("Lenna_scale_bilinear.jpg", dst);  
  
  waitKey(0);  
  return 0;  
}  
  
void MyScale(Mat& src, Mat& dst, float TransMat[3][3])  
{  
    CV_Assert(src.data);  
    CV_Assert(src.depth() != sizeof(uchar));  
      
    // calculate margin point of dst image  
    float left =  0;  
    float right =  0;  
    float top =  0;  
    float down =  0;  
  
    float x = src.cols * 1.0f;  
    float y = 0.0f;  
    float u1 = x * TransMat[0][0] + y * TransMat[0][1];  
    float v1 = x * TransMat[1][0] + y * TransMat[1][1];  
    x = src.cols * 1.0f;  
    y = src.rows * 1.0f;  
    float u2 = x * TransMat[0][0] + y * TransMat[0][1];  
    float v2 = x * TransMat[1][0] + y * TransMat[1][1];  
    x = 0.0f;  
    y = src.rows * 1.0f;  
    float u3 = x * TransMat[0][0] + y * TransMat[0][1];  
    float v3 = x * TransMat[1][0] + y * TransMat[1][1];  
  
    left =  min( min( min(0.0f,u1), u2 ), u3);  
    right =  max( max( max(0.0f,u1), u2 ), u3);  
    top =  min( min( min(0.0f,v1), v2 ), v3);  
    down =  max( max( max(0.0f,v1), v2 ), v3);  
  
    // create dst image  
    dst.create(int(abs(right-left)), int(abs(down-top)), src.type());  
      
  
    CV_Assert( dst.channels() == src.channels() );  
    int channels = dst.channels();  
  
    int i,j;  
    uchar* p;  
    uchar* q0;  
    uchar* q1;  
    for( i = 0; i < dst.rows; ++i)  
    {  
        p = dst.ptr<uchar>(i);  
        for ( j = 0; j < dst.cols; ++j)  
        {  
            //   
            x = (j+left)/TransMat[0][0]  ; // NOTE: adverse rotation here!!!  
            y = (i+top)/TransMat[1][1] ;  
            int x0 = int(x);  
            int y0 = int(y);  
            int x1 = int(x) + 1;  
            int y1 = int(y) + 1;  
  
            if( (x0 >= 0) && (x0 < src.cols) && (y0 >= 0) && (y0 < src.rows) &&  
                (x1 >= 0) && (x1 < src.cols) && (y1 >= 0) && (y1 < src.rows) )   
            {  
                q0 = src.ptr<uchar>(y0);  
                q1 = src.ptr<uchar>(y1);  
                switch(channels)  
                {  
                    case 1:  
                        {  
                            //p[j] = q[x];  
                            break;  
                        }  
                    case 3:  
                        {  
                            float b0 = q0[3*x0] ;  
                            float g0 = q0[3*x0+1];  
                            float r0 = q0[3*x0+2];  
                            float b1 = q0[3*x1] ;  
                            float g1 = q0[3*x1+1];  
                            float r1 = q0[3*x1+2];  
                            float b2 = q1[3*x0] ;  
                            float g2 = q1[3*x0+1];  
                            float r2 = q1[3*x0+2];  
                            float b3 = q1[3*x1] ;  
                            float g3 = q1[3*x1+1];  
                            float r3 = q1[3*x1+2];  
  
                            float b4 = b0 * (x1-x) / (x1-x0) + b1 * (x-x0) / (x1-x0);  
                            float g4 = g0 * (x1-x) / (x1-x0) + g1 * (x-x0) / (x1-x0);  
                            float r4 = r0 * (x1-x) / (x1-x0) + r1 * (x-x0) / (x1-x0);  
                            float b5 = b2 * (x1-x) / (x1-x0) + b3 * (x-x0) / (x1-x0);  
                            float g5 = g2 * (x1-x) / (x1-x0) + g3 * (x-x0) / (x1-x0);  
                            float r5 = r2 * (x1-x) / (x1-x0) + r3 * (x-x0) / (x1-x0);  
  
                            p[3*j] = b4 * (y1-y) / (y1-y0) + b5 * (y-y0) / (y1-y0);  
                            p[3*j+1] = g4 * (y1-y) / (y1-y0) + g5 * (y-y0) / (y1-y0);  
                            p[3*j+2] = r4 * (y1-y) / (y1-y0) + r5 * (y-y0) / (y1-y0);  
  
  
                            break;  
                        }  
                }  
            }  
        }  
    }  
}  

原图与处理结果



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值