图像处理 插值 旋转_图像双线性插值对图像边缘是怎么处理的 - CSDN
  • 图像处理之线性插值旋转算法 基本数学知识: 1. 三角函数基本知识,sin, cosin 2. 反三角函数基本知识,知道任意一点坐标P(x, y)求取该点的角度a = atag2(y/x) 3. 极坐标与笛卡尔坐标系转换知识 图像旋转...

    图像处理之线性插值旋转算法

    基本数学知识:

    1.      三角函数基本知识,sin, cosin

    2.      反三角函数基本知识,知道任意一点坐标P(x, y)求取该点的角度a = atag2(y/x)

    3.      极坐标与笛卡尔坐标系转换知识

    图像旋转矩阵:由此可以计算图像旋转以后的新的高度与宽度。


    相关算法:

    双线性插值算法,实现图像旋转反锯齿效果,同时是一种高质量的图像图像旋转方法,

    缺点是计算量比较大。但是对现在的计算机硬件来说,速度还可以。

    关于角度旋转:

    1.      90度,180度,270度可以直接旋转坐标取得,像素直接映射取得。

    2.      对于任何角度angle可以如下处理n = mod(angle, 90) = 1, 2, 3, 然后

            将角度旋转90,180,270然后再旋转角度(angle– n * 90)。

    程序实现:

    1.      首先根据输入角度参数angle, 背景填充颜色bgcolor初始化

    2.      计算出旋转以后的图像width与height

    3.      循环每个输出像素,计算机坐标

    4.      反旋转输入角度到输入的目标像素浮点数坐标

    5.      使用双线性插值完成目标像素填充,如果不在范围之内填充背景色。

    6.      得到输出像素数据,返回旋转后图像

    原图:


    旋转45度的效果,背景填充为灰色:


    程序代码(特殊角度旋转自己实现吧,有点懒)

    package com.gloomyfish.filter.study;
    
    import java.awt.Color;
    import java.awt.image.BufferedImage;
    import java.awt.image.ColorModel;
    
    public class RotateFilter extends AbstractBufferedImageOp {
    	private double angle;
    	private Color background;
    	private int outw;
    	private int outh;
    	
    	public RotateFilter() {
    		this.angle = (45.0d/180.0d) * Math.PI;
    		background = Color.BLACK;
    		outw = -1;
    		outh = -1;
    	}
    	
    	public void setDegree(double angle) {
    		this.angle = (angle/180.0d) * Math.PI;
    	}
    	
    	public void setBackgroud(Color background) {
    		this.background = background;
    	}
    	
        public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) {
            if ( dstCM == null )
                dstCM = src.getColorModel();
            return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(outw, outh), dstCM.isAlphaPremultiplied(), null);
        }
    
    	@Override
    	public BufferedImage filter(BufferedImage src, BufferedImage dest) {
    		int width = src.getWidth();
            int height = src.getHeight();
    
            int[] inPixels = new int[width*height];
            outw = (int)(width*Math.cos(angle)+height*Math.sin(angle)); 
            outh = (int)(height*Math.cos(angle)+width*Math.sin(angle));
            System.out.println("after rotate, new width : " + outw);
            System.out.println("after rotate, new height: " + outh);
            
            int[] outPixels = new int[outw*outh];
            getRGB( src, 0, 0, width, height, inPixels );
            int index = 0;
            
            int centerPixel = inPixels[height/2 * width + width/2];
            
            // calculate new center coordinate
            float centerX = outw / 2.0f + 0.5f;
            float centerY = outh /2.0f + 0.5f;
            
            // calculate the original center coordinate
            float ocenterX = width / 2.0f + 0.5f;
            float ocenterY = height /2.0f + 0.5f;
            
            float rx =0, ry = 0; //after rotated coordinate
            float px = 0, py = 0; // original coordinate
            float prow = 0, pcol = 0;
            for(int row=0; row<outh; row++) {
            	for(int col=0; col<outw; col++) {
            		rx = col - centerX;
            		ry = centerY - row;
            		float fDistance = (float)Math.sqrt(rx * rx + ry * ry);
            		float fPolarAngle = 0; //;
            		if(rx != 0) {
            			fPolarAngle = (float)Math.atan2((double)ry, (double)rx);
            		} else {
            			if(rx == 0) {
            				if(ry == 0) {
            					outPixels[index] = centerPixel;
            					continue; 
            				} 
            				else if(ry < 0) {
                				fPolarAngle = 1.5f * (float)Math.PI;
                			} else {
                				fPolarAngle = 0.5f * (float)Math.PI;
                			}
            			}
            		}
            		
            		// "reverse" rotate, so minus instead of plus
                    fPolarAngle -= angle;
                    px = fDistance * (float)Math.cos(fPolarAngle);
                    py = fDistance * (float)Math.sin(fPolarAngle);
    
                    // get original pixel float point
                    prow = ((float)ocenterY) - py;
                    pcol = ((float)ocenterX) + px;
    
                    // now start the biline-interpolation algorithm here!!!
                    int[] rgb = bilineInterpolation(inPixels, width, height, prow, pcol);
                    
                    index = row * outw + col;
                    outPixels[index] = (255 << 24) | (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
                    
            	}
            }
    
            if ( dest == null )
            	dest = createCompatibleDestImage( src, null );
            setRGB( dest, 0, 0, outw, outh, outPixels );
            return dest;
    	}
    
    	private int[] bilineInterpolation(int[] input, int width, int height, float prow, float pcol) {
    		double row = Math.floor(prow);
    		double col = Math.floor(pcol);
    		if(row < 0 || row >= height) {
    			return new int[]{background.getRed(), background.getGreen(), background.getBlue()};
    		}
    		if(col < 0 || col >= width) {
    			return new int[]{background.getRed(), background.getGreen(), background.getBlue()};
    		}
    		
    		int rowNext = (int)row + 1, colNext = (int)col + 1;
    		if((row + 1) >= height) {
    			rowNext = (int)row;
    		}
    		
    		if((col + 1) >= width) {
    			colNext = (int)col;
    		}
    		double t = prow - row;
    		double u = pcol - col;
    		double coffiecent1 = (1.0d-t)*(1.0d-u);
    		double coffiecent2 = (t)*(1.0d-u);
    		double coffiecent3 = t*u;
    		double coffiecent4 = (1.0d-t)*u;
    		
    		int index1 = (int)(row * width + col);
    		int index2 = (int)(row * width + colNext);
    		
    		int index3 = (int)(rowNext * width + col);
    		int index4 = (int)(rowNext * width + colNext);
    		int tr1, tr2, tr3, tr4;
    		int tg1, tg2, tg3, tg4;
    		int tb1, tb2, tb3, tb4;
    		
            tr1 = (input[index1] >> 16) & 0xff;
            tg1 = (input[index1] >> 8) & 0xff;
            tb1 = input[index1] & 0xff;
            
            tr2 = (input[index2] >> 16) & 0xff;
            tg2 = (input[index2] >> 8) & 0xff;
            tb2 = input[index2] & 0xff;
            
            tr3 = (input[index3] >> 16) & 0xff;
            tg3 = (input[index3] >> 8) & 0xff;
            tb3 = input[index3] & 0xff;
            
            tr4 = (input[index4] >> 16) & 0xff;
            tg4 = (input[index4] >> 8) & 0xff;
            tb4 = input[index4] & 0xff;
    
            int tr = (int)(tr1 * coffiecent1 + tr2 * coffiecent4 + tr3 * coffiecent2 + tr4 * coffiecent3);
            int tg = (int)(tg1 * coffiecent1 + tg2 * coffiecent4 + tg3 * coffiecent2 + tg4 * coffiecent3);
            int tb = (int)(tb1 * coffiecent1 + tb2 * coffiecent4 + tb3 * coffiecent2 + tb4 * coffiecent3);
    
    		return new int[]{tr, tg, tb};
    	}
    
    }
    
    转载请务必注明
    展开全文
  • 关于图像处理中的插值旋转

    千次阅读 2018-03-02 17:18:17
    关于图像处理中的插值旋转一.插值参考:http://blog.csdn.net/Real_Myth/article/details/49275999 在模板匹配问题中,涉及到角度插值和坐标插值(亚像素精度)问题。角度插值:得到最佳匹配模板左右相邻的模板的...

    关于图像处理中的插值和旋转

    一.插值
    参考:http://blog.csdn.net/Real_Myth/article/details/49275999

    在模板匹配问题中,涉及到角度插值和坐标插值(亚像素精度)问题。

    角度插值:得到最佳匹配模板左右相邻的模板的信息,二次拟合(x为角度,y为得分)

    坐标插值:得到最佳匹配点的3*3邻域点的匹配情况,三次拟合(xy坐标,y为得分)

    确定拟合模型(什么方程)——》找到需要的信息(多少个点及其对应的值)——》求极值

    注意: 相邻元素的确定。在我遇到的实际问题中,要找到同一尺度下的相邻角度的模板,而所有模板在制作保存时用到了并行,故需要遍历搜索。以三个角度为x,以它们同一点(变量的控制)处的得分为y

    【将点一次带入得到方程组/最小二乘法列出方程组】

    三次拟合示例:a0+a1x+a2y+a3x^2+a4y^2+a5xy=z

    voidfittingCurve3D(double *x,double *y,double *z,intn,double *index)

    {

        //直接把点带入方程,把方程组写成矩阵形式,结果用伪逆表示[inv(A'A)]A'b

        double *a =newdouble[n * 6];//已知点的信息矩阵,含xy

        double *b =newdouble[n];//已知点的信息矩阵,含z

       ///构造a的一维数组,n*6

        for (int i = 0; i <n * 6; ++i)

        {

            if (i % 6 == 0)

            {

                a[i]= 1;

                a[i+ 1] = x[i / 6];//x

                a[i+ 2] = y[i / 6];//y

                a[i+ 3] = x[i / 6] * x[i / 6];//x^2

                a[i+ 4] = y[i / 6] * y[i / 6];//y^2

                a[i+ 5] = x[i / 6] * y[i / 6];//x*y

            }

        }

        CvMat AMat = cvMat(n, 6,CV_64FC1, a);//变成矩阵AMat

        CvMat *ATransposedMat =cvCreateMat(AMat.cols, AMat.rows,CV_64FC1);

        cvTranspose(&AMat,ATransposedMat);//转置ATransposedMat

    ///用于存储矩阵相乘结果,构造的数组n*n

        double *c =newdouble[6 * 6];

        for (int i = 0; i < 6 *6; ++i)

        {

            c[i]= 0;

        }

        CvMat invMat1 = cvMat(6,6,CV_64FC1, c);//变成矩阵invMat1

        cvGEMM(ATransposedMat,&AMat, 1, NULL, 0,&invMat1, 0);// ATransposedMat(转置)*AMat=invMat1

        cvInvert(&invMat1,&invMat1, 0);//求invMat1的逆矩阵,invMat1 

     

        ///构造b的一维数组,n*1

        for (int i = 0; i <n; ++i)

        {

            b[i]= z[i];

        }

        CvMat BMat = cvMat(n, 1,CV_64FC1, b);//变成矩阵BMat

    //用于存储矩阵相乘结果,构造的数组6*1

        double *d =newdouble[6];

        for (int i = 0; i < 6;++i)

        {

            d[i]= 0;

        }

        CvMat invMat2 = cvMat(6,1,CV_64FC1, d);//变成矩阵invMat2

        cvGEMM(ATransposedMat,&BMat, 1, NULL, 0,&invMat2, 0);//AMat的转置矩阵 * BMat矩阵 = invMat2

        CvMat indexMat = cvMat(6,1,CV_64FC1, index);

        cvGEMM(&invMat1,&invMat2, 1, NULL, 0,&indexMat, 0);//invMat1 * invMat2 = indexMat

        cvReleaseMat(&ATransposedMat);

        delete[] a;

        delete[] b;

        delete[] c;

        delete[] d;

    }

    各种曲面的拟合:如拟合球面 :x^2+ay^2+bz^2+cx+dy+ez+f=0

    http://blog.csdn.net/hj199404182515/article/details/59480954

     

    二.旋转

    旋转算法原理:http://blog.csdn.net/liyuan02/article/details/6750828

    正向映射://旋转后dst图像坐标系

    double xtemp0 = c*x - s*y + (-0.5*c*(srcW - 1) + 0.5*s*(srcH - 1) +0.5*dstW);

    double ytemp0 = s*x + c*y + (-0.5*s*(srcW - 1) -0.5*c*(srcH - 1) + 0.5*dstH);

    逆向映射:(映射回原图的放大图temp

    double xtemp = c*i + s*j + (-c*(dstW - 1)*0.5 - s* (dstH - 1)*0.5+0.5*temp->width);

    double ytemp = -s*i + c*j + (s*(dstW - 1)*0.5 - c* (dstH -1)*0.5+ 0.5*temp->height);

    //将原图复制到临时图像temp中心  (保证原图可以任意角度旋转的最小尺寸 )

    int tempLength =int( sqrt((double)width *width + (double)height *height) + 10);

    int tempX = (tempLength + 1) / 2 - width /2;

    int tempY = (tempLength + 1) / 2 - height /2;

    IplImage* temp =cvCreateImage(cvSize(tempLength, tempLength), src->depth,src->nChannels);

    memset(temp->imageData, 255,  sizeof(char)*temp->imageSize);

    cvSetImageROI(temp, cvRect(tempX, tempY,width, height));

    cvCopy(src, temp, NULL);

    cvResetImageROI(temp);

    cvReleaseImage(&temp);

     

    正向映射:输入图像上整数点坐标映射到输出图像之后,变成了非整数点坐标。因此,需要将其像素值按一定权重分配到其周围四个像素点上。遍历输出图像,对每个点,将每次映射分配而来的像素值叠加。

    图像旋转中的插值:一般采用反向双线性插值

    http://www.cnblogs.com/mlv5/archive/2012/02/02/2336321.html

    示例:

    intImgBilinearInter(floatfx,floatfy,IplImage * img) {

        //参考函数cv::PicRotaryBilInear——双线性插值

        int value;

        int x = floor(fx);

        int y = floor(fy);

        cv::Point P0 = Pixels_Bound(img, x, y);

        cv::Point P2 = Pixels_Bound(img, x + 1, y);

        cv::Point P1 = Pixels_Bound(img, x, y + 1);

        cv::Point P3 = Pixels_Bound(img, x + 1, y + 1);//边界饱和

        float u =fx - x;

        float v =fy - y;

        float pm3 = u*v;

        float pm2 = u*(1 - v);

        float pm1 = v*(1 - u);

        float pm0 = (1 - u)*(1 -v);

        // 指向图像的指针

        uchar* lp = (uchar *)img->imageData;

        int step =img->widthStep /sizeof(uchar);

        //value = (pm0*lp[P0.y*step + P0.x] + pm1*lp[P1.y *step +P1.x] + pm2*lp[P2.y *step + P2.x ] + pm3*lp[P3.y *step + P3.x ]);

        float value_float =(pm0*lp[P0.y*step + P0.x] + pm1*lp[P1.y *step + P1.x] + pm2*lp[P2.y *step +P2.x] + pm3*lp[P3.y *step + P3.x]);

        value= round(value_float);

        return value;

    }

    cv::Point Pixels_Bound(IplImage *pic, intx0,inty0) {

        if (x0<0) {x0 = 0; }

        elseif (x0 >=pic->width) { x0 = pic->width - 1; }

        if (y0<0) {y0 = 0; }

        elseif (y0 >=pic->height) { y0 = pic->height - 1; }

        cv::Point P(x0,y0);

        return P;

    }

    双线性插值部分,边界元素的处理需注意。

     

    展开全文
  • 图像旋转 双线性插值 c++

    千次阅读 2015-12-08 15:03:13
    前面详细介绍了最近邻插值实现图像旋转,但是我们都知道,最近邻插值对于图像旋转效果不是特别的好。所以在本文中,我们详细讨论一下双线性插值算法。  首先,详细介绍一下什么事双线性插值,以及双线性插值为...

                前面详细介绍了最近邻插值实现图像的旋转,但是我们都知道,最近邻插值对于图像的旋转效果不是特别的好。所以在本文中,我们详细讨论一下双线性插值算法。

                首先,详细介绍一下什么事双线性插值,以及双线性插值为什么会比最近邻插值效果好一些。

                为什么图像的旋转一定要插值,因为在旋转过程中,由于三角函数的影响,导致旋转后的点,并不是每一个点都可以在原图像中找到对应点(如:计算出(3.5,4.4)将对应哪个点呢?),所以这些点的灰度值如何确定,就需要我们利用插值算法来进行处理,最近邻插值,想法比较简单,直接四舍五入,显然这种方法不是最理想的。那么双线性插值是什么呢?首先看图:


                   如上图,假如,我们计算后得到的像素点为p,但是这个点并没有在图像中有点与之对应,因为它的值可能是小数的,那么,我们如何确定它的灰度值呢?

     双线性插值的想法也比较简单,双线性,顾名思义,利用了2次线性插值。那是哪两次呢?这时,我们便利用上了其周围的像素点O12   O22   O11   O 21 .通过O12  O22 计算出R2点的灰度值,然后通过O11   O21计算出R1点的灰度值,然后再根据R1  R2计算出P点的灰度值。这样相比最近邻方法,更加充分的利用了周围的像素点,可以取得较好的效果。

                 那么我们编程如何计算呢?

                 首先,对p点坐标进行取整,得到O21点坐标,然后像素值+1 便得到O22的坐标,然后利用比例计算,便可以得到R2的灰度值,同理可以得到R1灰度值,再根据比例计算,便可以得到p点的灰度值。

    具体代码如下:

    /*
    双线性插值图像旋转函数 , 旋转之后 图像不改变大小  信息有些丢失
    输入参数:
          img: 原图像  width:原图像的宽度  height:原图像的高度
     result:旋转后的图像
     sita:旋转角度(弧度制)
     xr,yr : 旋转中心
     BackGray:背景灰度值
    */
    int TwinRotate(BYTE *img,int width,int height,BYTE *result,double sita,double xr,double yr,BYTE BackGray)
    {
        double SinTheta = sin(sita);double CosTheta = cos(sita);
        if(result)
              delete []result;
        result = new BYTE[width*height];
      //  if(ResultTemp==NULL)
       //     return -1;
        memset( result, BackGray, width*height*sizeof(BYTE) );
        int    x, y, px, py; 
        double tx,ty,p1,p2,p3,p4,p1_2,p3_4;
        double ConstX= -xr*CosTheta + yr*SinTheta + xr ;
        double ConstY= -yr*CosTheta - xr*SinTheta + yr ;
        
        BYTE *pRes=result, *p;
        for(y=0;y<height;y++)
        {
            tx = - y*SinTheta - CosTheta + ConstX ; 
            ty =   y*CosTheta - SinTheta + ConstY ; 
            for(x=0;x<width;x++)
            { 
                tx += CosTheta; //x*CosTheta - y*SinTheta + ConstX; (x-xr)*CosTheta - (y-yr)*SinTheta + xr 
                ty += SinTheta; //y*CosTheta + x*SinTheta + ConstY; (y-yr)*CosTheta + (x-xr)*SinTheta + yr 
                px = (int)tx;
                py = (int)ty;
                if( px<0 || px>width-2 || py<0 || py>height-2 )
                {
                    pRes++;
                    continue;
                }
                      p1 = img[py*width+px];    //此处求出周围点的值
                      p2 = img[py*width+px+1];
                      p3 = img[(py+1)*width+px];
                      p4 = img[(py+1)*width+px+1];
                 p1_2 = p1 + (tx-px)*(p2-p1);
                 p3_4 = p3 + (tx-px)*(p4-p3);
               *pRes = p1_2 + (ty - py)*(p3_4 - p1_2); 
                pRes++;
             }
        }
        return true;
    }

    展开全文
  • 插值实现图像旋转

    2020-07-15 23:30:20
    实现图像旋转,适用于RGB图像和灰度图像
  •  在图像处理中,平移变换、旋转变换以及放缩变换是一些基础且常用的操作。这些几何变换并不改变图象的象素值,只是在图象平面上进行象素的重新排列。在一幅输入图象[u,v][u,v][u,v]中,灰度值仅在整数位置上有...

     在图像处理中,平移变换、旋转变换以及放缩变换是一些基础且常用的操作。这些几何变换并不改变图象的象素值,只是在图象平面上进行象素的重新排列。在一幅输入图象[uv][u,v]中,灰度值仅在整数位置上有定义。然而,输出图象[x,y]的灰度值一般由处在非整数坐标上的uv(u,v)值来决定。这就需要插值算法来进行处理,常见的插值算法有最近邻插值、双线性插值和三次样条插值。

    1、最近邻插值算法原理

    最近邻插值,是指将目标图像中的点,对应到源图像中后,找到最相邻的整数点,作为插值后的输出。

    img

     如上图所示,目标图像中的某点投影到原图像中的位置为点P,此时易知,f(P)=f(Q11)f(P) = f(Q11).

    一个例子:

      如下图所示,将一幅3X3的图像放大到4X4,用f(x,y)f(x, y)表示目标图像,h(x,y)h(x, y)表示原图像,我们有如下公式:

    f(dstX,dstY)=h(dstXsrcWidthdstWidth,dstYsrcHeightdstHeight) \begin{array}{c} f(dst_{X}, dst_{Y}) = h(\frac{dst_{X}src_{Width}} {dst_{Width}}, \frac{dst_{Y}src_{Height}} {dst_{Height}}) \end{array}

    f(0,0)=h(0,0)f(0,1)=h(0,0.75)=h(0,1)f(0,2)=h(0,1.50)=h(0,2)f(0,3)=h(0,2.25)=h(0,2)... \begin{array}{c} f(0,0)=h(0,0) \\ f(0,1)=h(0,0.75)=h(0,1) \\ f(0,2)=h(0,1.50)=h(0,2) \\ f(0,3)=h(0,2.25)=h(0,2) \\ ...\\ \end{array}

    img

    缺点:
    用该方法作放大处理时,在图象中可能出现明显的块状效应

    2、双线性插值

     在讲双线性插值之前先看以一下线性插值,线性插值多项式为:

    f(x)=a1x+a0 f(x)=a_{1} x+a_{0}

    img

    y=y0+(xx0)y1y0x1x0=y0+(xx0)y1(xx0)y0x1x0 y=y_{0}+\left(x-x_{0}\right) \frac{y_{1}-y_{0}}{x_{1}-x_{0}}=y_{0}+\frac{\left(x-x_{0}\right) y_{1}-\left(x-x_{0}\right) y_{0}}{x_{1}-x_{0}}

      双线性插值就是线性插值在二维时的推广,在两个方向上做三次线性插值,具体操作如下图所示:

    img

      令f(xy)f(x,y)为两个变量的函数,其在单位正方形顶点的值已知。假设我们希望通过插值得到正方形内任意点的函数值。则可由双线性方程:
    f(x,y)=ax+by+cxy+d f(x, y)=a x+b y+c x y+d

      来定义的一个双曲抛物面与四个已知点拟合。

      首先对上端的两个顶点进行线性插值得:

    f(x,0)=f(0,0)+x[f(1,0)f(0,0)] f(x, 0)=f(0,0)+x[f(1,0)-f(0,0)]

      类似地,再对底端的两个顶点进行线性插值有:
    f(x,1)=f(0,1)+x[f(1,1)f(0,1)] f(x, 1)=f(0,1)+x[f(1,1)-f(0,1)]

      最后,做垂直方向的线性插值,以确定:

    f(x,y)=f(x,0)+y[f(x,1)f(x,0)] f(x, y)=f(x, 0)+y[f(x, 1)-f(x, 0)]

      整理得:

    f(x,y)=[f(1,0)f(0,0)]x+[f(0,1)f(0,0)]y+[f(1,1)+f(0,0)f(0,1)f(1,0)]xy+f(0,0) \begin{array}{l} f(x, y)=[f(1,0)-f(0,0)] x+[f(0,1)-f(0,0)] y \\ +[f(1,1)+f(0,0)-f(0,1)-f(1,0)] x y+f(0,0) \end{array}

    3、基于opencv的实现

    cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])

    参数:

    参数 描述
    src 【必需】原图像
    dsize 【必需】输出图像所需大小
    fx 【可选】沿水平轴的比例因子
    fy 【可选】沿垂直轴的比例因子
    interpolation 【可选】插值方式

    插值方式:

    cv.INTER_NEAREST 最近邻插值
    cv.INTER_LINEAR 双线性插值
    cv.INTER_CUBIC 基于4x4像素邻域的3次插值法
    cv.INTER_AREA 基于局部像素的重采样

    通常,缩小使用cv.INTER_AREA,放缩使用cv.INTER_CUBIC(较慢)和cv.INTER_LINEAR(较快效果也不错)。默认情况下,所有的放缩都使用cv.INTER_LINEAR。

    使用python实现了最近邻插值算法

    import cv2
    import numpy as np
    
    
    def nearest_resize(img, src_size):
        h, w, c = img.shape
        src = np.zeros((src_size[0], src_size[1], 3), dtype=np.uint8)
        if h == src_size[0] and w == src_size[1]:
            return img
        for i in range(src_size[0]):
            for j in range(src_size[1]):
                # round()四舍五入的函数
                src_x = round(i * (h / src_size[0]))
                src_y = round(j * (w / src_size[1]))
                src[i, j] = img[src_x, src_y]
        return src
    
    
    if __name__ == '__main__':
        img = cv2.imread('F:/DataWhale/cv/imgs/4.jpeg')
        cv2.imshow("img", img)
        src = nearest_resize(img, (270, 480))
        cv2.imshow("resize_img", src)
        cv2.waitKey()
    
    
    image-20200810131553441 image-20200810131445377

    用自带的resize()实践

    import cv2
     
    if __name__ == "__main__":
        img = cv2.imread('D:/image/yuner.jpg', cv2.IMREAD_UNCHANGED)
        
        print('Original Dimensions : ',img.shape)
        
        scale_percent = 30       # percent of original size
        width = int(img.shape[1] * scale_percent / 100)
        height = int(img.shape[0] * scale_percent / 100)
        dim = (width, height)
        # resize image
        resized = cv2.resize(img, dim, interpolation = cv2.INTER_LINEAR)
    
        fx = 1.5
        fy = 1.5
    
        resized1 = cv2.resize(resized, dsize=None, fx=fx, fy=fy, interpolation = cv2.INTER_NEAREST)
        
        resized2 = cv2.resize(resized, dsize=None, fx=fx, fy=fy, interpolation = cv2.INTER_LINEAR)
        print('Resized Dimensions : ',resized.shape)
        
        cv2.imshow("Resized image", resized)
        cv2.imshow("INTER_NEAREST image", resized1)
        cv2.imshow("INTER_LINEAR image", resized2)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    
    展开全文
  • 使用双线性插值图像旋转

    千次阅读 2018-03-10 10:13:35
    依然是“表格识别”课题,目前...下面我们研究一下如何使用双线性插值图像旋转:双线性插值基本原理通过图来说明,已知的是四个点Q11,Q12,Q21,Q22的函数值,要求P点函数值,可以通过线性插值如拉格朗日插值得到R...
  • 图像几何变换的过程中,常用的插值方法有最邻近插值(近邻取样法)、双线性内插值和三次卷积法。 最邻近插值: 这是一种最为简单的插值方法,在图像中最小的单位就是单个像素,但是在旋转个缩放的过程中如果...
  • 数字图像处理--图像插值

    千次阅读 2016-07-15 17:43:05
    定义:设函数y=f(x)在区间[a,b]上有定义,且已知在点a≤x0P(xi)=yi...有时,在图像的几何变换中,比如缩放和旋转,输出图像上的像素点坐标有可能对应于原图像上几个像素点之间的位置,这个时候就需要通过灰度插值处理
  • 图像运动专题-图像旋转-基于近邻插值的图像旋转 1. 图像处理前后结果展示 图像处理前 图1 图像处理后 图2 2.图像旋转原理 图像以坐标原点为中心进行旋转比较好做,那么以任意的指定点来旋转,可以平移...
  • 图像旋转-不同插值法比较——MATLAB

    千次阅读 2017-06-19 19:13:48
    %不同插值法比较 clear all; img = imread(‘g0.jpg’); rotateimg1=imrotate(img,30,’nearest’);%最邻近插值 rotateimg2=imrotate(img,-30,’bilinear’);%双线性插值 rotateimg3=imrotate(img,50,’bicubic...
  • 数字图像处理中的一些插值算法

    千次阅读 2014-04-14 16:44:58
    在图像缩放,旋转等一些图像处理中,dui
  • 数字图像处理插值方法

    千次阅读 2016-05-28 19:21:56
    在对图像进行空间变换的过程中,典型的情况是在对图像进行放大,旋转处理的时候,图像会出现失真的现象。这是由于在变换之后的图像中,存在着一些变换之前的图像中没有的像素位置。处理这一问题的方法被称为图像灰度...
  • 图像处理用的线性插值算法实现图像缩放旋转祥解
  • 数字图像处理图像旋转, 3图像旋转算法 ①读入图像文件并把图像转为灰度图像,显示图像,X轴标注为图(a); ②计算图像旋转θ角后的四个顶点坐标(以便确定旋转后的图像大小); ③根据四个顶点坐标,计算移动偏移...
  • 采用Python、numpy库实现图像插值算法,主要用于分析三种常见的插值算法的具体流程。   这里主要实现了最邻近插值算法(由于图像中具有邻域相关性,用这种方法会产生明显的锯齿)、双线性插值、双立方插值(这里...
  • 目录图像处理一、OpenCV框架与图像插值算法 图像处理 图像处理(image processing), 一、OpenCV框架与图像插值算法
  • 在做数字图像处理时,经常会碰到小数象素坐标的取值问题,这时就需要依据邻近象素的值来对该坐标进行插值。比如:做地图投影转换,对目标图像的一个象素进行坐标变换到源图像上对应的点时,变换出来的对应的坐标是一...
  • 图像插值是在基于模型框架下,从低分辨率图像生成高分辨率图像的过程,用以恢复图像中所丢失的信息。图象插值方法有:最近邻插值,双线性插值,双平方插值,双立方插值以及其他高阶方法。 在很多情况下,人们需要对...
1 2 3 4 5 ... 20
收藏数 9,441
精华内容 3,776
关键字:

图像处理 插值 旋转