Opencv下双线性插值法进行图像放缩

关于图像放缩的算法有很多,本文主要介绍双线性插值法进行图像放缩,本文参考了: http://www.cnblogs.com/funny-world/p/3162003.html

我们设源图像src的大小为m*N,目标图像的大小为a*b。无论是放大还是缩小,我们所遵循的原则就是对于目标图像的像素点 f(i,j),我们在源图像当中找到其对应点 f(x,y)。

其算法为:i/x=m/a  j/y=n/b 因此我们可以得到:x=i*(m/a)     y=j*(n/b)

但是为了使放缩的效果更好,可以使两个图片的几何中心重合,所以我们可以:x=(i+0.5)*(m/a)-0.5   y=(j+0.5)*(n/b)-0.5

通过这样算法,我们便可以在源图像当中找到目标图像的对应点了,但是这样计算 x,y 很可能是float型,因此我们需要继续对 x,y进行处理

我们可以找到 于P(所求的点)最为临近的四个点 Q11 ,Q12 ,Q21,Q22 ,通过下面的算法进行处理:


 f(R1)=(X2-X)/(X2-X1)*f(Q11)+(X-X1)/(X2-X1)*f(Q21)


 f(R2)=(X2-X)/(X2-X1)*f(Q12)+(X-X1)/(X2-X1)*f(Q22)


 f(i,j)=(Y2-Y)/(Y2-Y1)f(R1)+(Y-Y1)/(Y2-Y1)*f(R2)

 通过这样的处理,我们便可以计算出目标图像法 f(i,j)的像素值了,从而可以求出目标图像.

下面是Opencv的代码:

#include<opencv2\opencv.hpp>
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>

using namespace std;
using namespace cv;

int main(){
    Mat src;
    src=imread("G:/save1.jpg",1);    //输入图片;
    if(src.empty()){
        return -1;
    }
    Mat dist=Mat((2*src.rows),(2*src.cols),CV_32FC3);        //目标图片,将原图放大两倍;

    //遍历目标图片的点,将目标图片的归溯到原图的点当中,若结果为浮点型,则按照算法计算;
    //归溯算法,原图大小为a*b,目标图大小m*n,i/x=a/m,j/y=b/n;

    float x,y;
    int Q11[2],Q21[2],Q12[2],Q22[2];          //Q11 Q12 Q21 Q22分别对应着与P点最为临近的四个点,P点为目标图点还原到原图的点的对应位置;
    float R1[3],R2[3];
    for(int i=0;i<dist.rows-1;i++){           //这里减2是因为对于(src.rows-1,src.cols-1)的位置对应的是(dist.rows-2,dits.cols-2),再大一点就会超过内存。
        for(int j=0;j<dist.cols-1;j++){
            x=(i+0.5)*0.5-0.5;               //通过加减0.5,将像素点移到中心点的位置,使放缩效果更好。
            y=(j+0.5)*0.5-0.5;

            Q11[0]=(int)x;
            Q12[0]=(int)x;
            Q21[0]=(int)x+1;
            Q22[0]=(int)x+1;

            Q11[1]=(int) y;
            Q21[1]=(int) y;
            Q12[1]=(int) y+1;
            Q22[1]=(int) y+1;

            // 插值法算法如下:
            // X1=(int)x; X2=(int)x+1; Y1=(int)y; Y2=(int)y+1;
            // f(R1)=(X2-X)/(X2-X1)*f(Q11)+(X-X1)/(X2-X1)*f(Q21);
            // f(R2)=(X2-X)/(X2-X1)*f(Q12)+(X-X1)/(X2-X1)*f(Q22);
            // f(i,j)=(Y2-Y)/(Y2-Y1)f(R1)+(Y-Y1)/(Y2-Y1)*f(R2);
            for(int m=0;m<3;m++){
                R1[m]=((Q21[0]-x)*src.at<Vec3b>(Q11[0],Q11[1])[m])+((x-Q11[0])*src.at<Vec3b>(Q21[0],Q21[1])[m]);
                R2[m]=((Q21[0]-x)*src.at<Vec3b>(Q12[0],Q12[1])[m])+((x-Q11[0])*src.at<Vec3b>(Q22[0],Q22[1])[m]);
                dist.at<Vec3f>(i,j)[m]=(Q12[1]-y)*R1[m]+(y-Q11[1])*R2[m];
            }
        }
    }
    imwrite("G:/save.jpg",dist);          //输出图片;
}
View Code

 

转载于:https://www.cnblogs.com/code-wangjun/p/5956233.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二次线性插值是一种在图像处理中常用的插值方,可以用于对图像进行缩放、旋转等操作。在 Python 中,可以使用 OpenCV 库来实现二次线性插值。 下面是一个实现二次线性插值的示例代码: ```python import cv2 def bilinear_interpolation(img, x, y): # 取整数部分和小数部分 x1, y1 = int(x), int(y) x2, y2 = x1+1, y1+1 r1 = (x2-x)*(y2-y) r2 = (x-x1)*(y2-y) r3 = (x2-x)*(y-y1) r4 = (x-x1)*(y-y1) # 根据公式进行插值计算 result = img[y1,x1]*r1 + img[y1,x2]*r2 + img[y2,x1]*r3 + img[y2,x2]*r4 return result def resize_bilinear(img, dst_size): height, width = img.shape[:2] dst_height, dst_width = dst_size dst_img = np.zeros((dst_height, dst_width, 3), dtype=np.uint8) scale_x, scale_y = float(width) / dst_width, float(height) / dst_height for dst_y in range(dst_height): for dst_x in range(dst_width): # 计算原图上对应的坐标 src_x = (dst_x + 0.5) * scale_x - 0.5 src_y = (dst_y + 0.5) * scale_y - 0.5 if src_x < 0 or src_x >= width or src_y < 0 or src_y >= height: continue # 进行插值计算 dst_img[dst_y, dst_x] = bilinear_interpolation(img, src_x, src_y) return dst_img ``` 其中,`bilinear_interpolation` 函数实现了二次线性插值的算,`resize_bilinear` 函数则是用于对图像进行缩放的函数。 使用示例: ```python import cv2 # 读取图像 img = cv2.imread('test.jpg') # 缩放图像 dst_size = (int(img.shape[1] * 0.5), int(img.shape[0] * 0.5)) dst_img = resize_bilinear(img, dst_size) # 显示图像 cv2.imshow('Original', img) cv2.imshow('Resized', dst_img) cv2.waitKey(0) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值