双线性插值法

news2024/9/20 19:12:35

文章目录

  • 前言
  • 一、双线性插值
  • 二、代码实现
  • 总结


前言

  在上一文《最近邻插值法》中我们讨论了最近邻,并且使用python实现,本章节中我们继续讨论图像缩放算法——双线性插值法,给难度升个级。


一、双线性插值

  你在哪里见过下面这个图?回忆总是那么美妙,可能你已经记不清初中同桌的样子,但是老师黑板上画的一元一次方程肯定还记得。

在这里插入图片描述

  公式(1)怎么等起来呢?当然是斜率,公式两边都是算的上图直线的斜率。
y   −   y 0 x   −   x 0 = y 1   −   y 0 x 1   −   x 0 (1) \Large\frac{y\ -\ y_0}{x\ -\ x_0} = \frac{y_1\ -\ y_0}{x_1\ -\ x_0} \tag{1} x  x0y  y0=x1  x0y1  y0(1)
  公式整理一下得到公式(2)

y   =   x 1   −   x x 1   −   x 0   y 0   +   x   −   x 0 x 1   −   x 0   y 1 (2) \Large y\ = \ \frac{x_1\ -\ x}{x_1\ -\ x_0} \ y_0\ + \ \frac{x\ - \ x_0}{x_1\ - \ x_0}\ y_1\tag{2} y = x1  x0x1  x y0 + x1  x0x  x0 y1(2)
  根据两个已知点(x0,y0),(x1,y1)可以求出这条线的关系,用公式(2)表达。图像缩放,插入一个点应该和他周围点是有联系的。比如你坐的教室前排,那你周围坐的极有可能是学霸,通过你周围学霸的成绩是可以大概知道你的学习情况。在最近邻插值法里面没有考虑像素点之间的联系。
  双线性插值法就是进行了两次插入,第一次插入的是辅助点,第二次插入的才是真实点,比如Q12,Q22得到R2,Q11,Q21得到R1,最后R1,R2得到P。为什么不叫三次插入?因为两个辅助点是x方向插入,P是y方向插入,所以是双线性插入。
在这里插入图片描述

{ f ( x , y 1 )   =   f ( R 1 )   ≈   x 2   −   x x 2   −   x 1   f ( Q 11 ) + x   −   x 1 x 2   −   x 1   f ( Q 21 ) w h e r e R 1   =   ( x , y 1 ) f ( x , y 2 )   =   f ( R 2 )   ≈   x 2   −   x x 2   −   x 1   f ( Q 12 ) + x   −   x 1 x 2   −   x 1   f ( Q 22 ) w h e r e R 2   =   ( x , y 2 ) (3) \begin{cases} \large f(x, y_1)\ =\ f(R_1)\ \approx \ \frac{x_2\ -\ x}{x_2\ -\ x_1}\ f(Q_{11}) + \frac{x\ -\ x_1}{x_2\ -\ x_1}\ f(Q_{21}) \quad\quad\quad where\quad R_1\ = \ (x, y_1)\\ \large f(x, y_2)\ = \ f(R_2)\ \approx \ \frac{x_2\ -\ x}{x_2\ -\ x_1}\ f(Q_{12}) + \frac{x\ -\ x_1}{x_2\ -\ x_1}\ f(Q_{22}) \quad\quad\quad where\quad R_2\ = \ (x, y_2)\tag{3} \end{cases} {f(x,y1) = f(R1)  x2  x1x2  x f(Q11)+x2  x1x  x1 f(Q21)whereR1 = (x,y1)f(x,y2) = f(R2)  x2  x1x2  x f(Q12)+x2  x1x  x1 f(Q22)whereR2 = (x,y2)(3)
f ( x , y )   =   f ( P )   ≈   y 2   −   y y 2   −   y 1   f ( R 1 ) + y   −   y 1 y 2   −   y 1   f ( R 2 ) (4) \large f(x, y)\ =\ f(P)\ \approx \ \frac{y_2\ -\ y}{y_2\ -\ y_1}\ f(R_1) + \frac{y\ -\ y_1}{y_2\ -\ y_1}\ f(R_2)\tag{4} f(x,y) = f(P)  y2  y1y2  y f(R1)+y2  y1y  y1 f(R2)(4)
f ( x , y )   ≈   ( x 2   −   x )   ( y 2   −   y ) ( x 2   −   x 1 )   ( y 2   −   y 1 )   f ( Q 11 )   +   ( x   −   x 1 )   ( y 2   −   y ) ( x 2   −   x 1 )   ( y 2   −   y 1 )   f ( Q 21 ) +   ( x 2   −   x )   ( y   −   y 1 ) ( x 2   −   x 1 )   ( y 2   −   y 1 )   f ( Q 12 )   +   ( x   −   x 1 )   ( y   −   y 1 ) ( x 2   −   x 1 )   ( y 2   −   y 1 )   f ( Q 22 ) (5) \large f(x, y)\ \approx \ \frac{(x_2\ -\ x)\ (y_2\ -\ y)}{(x_2\ -\ x_1)\ (y_2\ -\ y_1)}\ f(Q_{11}) \ +\ \frac{(x\ -\ x_1)\ (y_2\ -\ y)}{(x_2\ -\ x_1)\ (y_2\ -\ y_1)}\ f(Q_{21})\\ +\ \frac{(x_2\ -\ x)\ (y\ -\ y_1)}{(x_2\ -\ x_1)\ (y_2\ -\ y_1)}\ f(Q_{12})\ +\ \frac{(x\ -\ x_1)\ (y\ -\ y_1)}{(x_2\ -\ x_1)\ (y_2\ -\ y_1)}\ f(Q_{22})\tag{5} f(x,y)  (x2  x1) (y2  y1)(x2  x) (y2  y) f(Q11) + (x2  x1) (y2  y1)(x  x1) (y2  y) f(Q21)+ (x2  x1) (y2  y1)(x2  x) (y  y1) f(Q12) + (x2  x1) (y2  y1)(x  x1) (y  y1) f(Q22)(5)
  公式(5)换个形式
f ( x , y )   =   1 ( x 2   −   x 1 )   ( y 2   −   y 1 )   ( f ( Q 11 ) ( x 2   −   x ) ( y 2   −   y )   +   f ( Q 21 ) ( x   −   x 1 ) ( y 2   −   y ) ) +   f ( Q 12 ) ( x 2   −   x ) ( y   −   y 1 )   +   f ( Q 22 ) ( x   −   x 1 ) ( y   −   y 1 ) ) (6) \large f(x, y)\ =\ \frac{1}{(x_2\ -\ x_1)\ (y_2\ -\ y_1)}\ (f(Q_{11})(x_2\ -\ x)(y_2\ -\ y)\ +\ f(Q_{21})(x\ -\ x_1)(y_2\ -\ y))\\+\ f(Q_{12})(x_2\ -\ x)(y\ -\ y_1)\ +\ f(Q_{22})(x\ -\ x_1)(y\ -\ y_1))\tag{6} f(x,y) = (x2  x1) (y2  y1)1 (f(Q11)(x2  x)(y2  y) + f(Q21)(x  x1)(y2  y))+ f(Q12)(x2  x)(y  y1) + f(Q22)(x  x1)(y  y1))(6)
  为什么要换成这样的形式,因为Q11,Q12,Q21,Q22四个点是相邻的,x2 - x1,y2 - y1都为1,所以上面的公式可以进一步简化为公式(7)
f ( x , y )   =   f ( Q 11 ) ( x 2   −   x ) ( y 2   −   y )   +   f ( Q 21 ) ( x   −   x 1 ) ( y 2   −   y ) ) +   f ( Q 12 ) ( x 2   −   x ) ( y   −   y 1 )   +   f ( Q 22 ) ( x   −   x 1 ) ( y   −   y 1 ) (7) \large f(x, y)\ =\ f(Q_{11})(x_2\ -\ x)(y_2\ -\ y)\ +\ f(Q_{21})(x\ -\ x_1)(y_2\ -\ y))\\+\ f(Q_{12})(x_2\ -\ x)(y\ -\ y_1)\ +\ f(Q_{22})(x\ -\ x_1)(y\ -\ y_1)\tag{7} f(x,y) = f(Q11)(x2  x)(y2  y) + f(Q21)(x  x1)(y2  y))+ f(Q12)(x2  x)(y  y1) + f(Q22)(x  x1)(y  y1)(7)
  原图和目标图像的计算如公式(8)所示,计算的结果肯定是浮点类型,但是图像的像素点索引必须是整数,所以这里求出的坐标可以认为是虚拟坐标,也就是不存在的。我们可以用这个虚拟坐标的附近四个真实坐标推算出靠近这个虚拟坐标的坐标(注意这里是坐标,不是像素值)。为什么要用这么奇怪的公式(8),公式(8)其实是原图和目标图像的映射公式。在《最近邻插值法》里面提到了原始图像和目标图像的几何中心点需要重合,这样虚拟坐标周围的四个坐标都能参与计算。
{ s r c _ x = ( d e s _ x + 0.5 )   ∗ s r c _ w   /   d e s _ w   −   0.5 s r c _ y = ( d e s _ y + 0.5 )   ∗ s r c _ h   /   d e s _ h   −   0.5 (8) \begin{cases} \large src\_x = (des\_x + 0.5)\ * src\_w\ /\ des\_w\ -\ 0.5\\ \large src\_y = (des\_y + 0.5)\ * src\_h\ /\ des\_h\ -\ 0.5 \end{cases}\tag{8} {src_x=(des_x+0.5) src_w / des_w  0.5src_y=(des_y+0.5) src_h / des_h  0.5(8)
  虚拟坐标可以拆分成(i+u),(j+v)的形式,u,v是虚拟坐标的小数部分,i,j是虚拟坐标的整数部分。我们想知道(i+u,j+v)的像素值就可以使用以下公式(9),因为坐标之间的关系求出来了,像素值就使用坐标点的关系求出。
f ( i + u , j + v )   =   f ( i , j ) ( 1   −   u ) ( 1   −   v )   +   f ( i , j + 1 ) ( 1   −   u ) v +   f ( i + 1 , j ) u ( 1   −   v )   +   f ( i + 1 , j + 1 ) u v (9) \large f(i+u, j+v)\ =\ f(i,j)(1\ -\ u)(1\ -\ v)\ +\ f(i,j+1)(1\ -\ u)v\\+\ f(i+1,j)u(1\ -\ v)\ +\ f(i+1,j+1)uv\tag{9} f(i+u,j+v) = f(i,j)(1  u)(1  v) + f(i,j+1)(1  u)v+ f(i+1,j)u(1  v) + f(i+1,j+1)uv(9)
  在python代码里面只需要公式(8,9),其他的都是推演过程,同学们不要慌啊。

二、代码实现

import numpy as np
import matplotlib.pyplot as plt
image = cv2.imread("three_body.jpg")
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
"""
根据当前坐标(x, y)最近的四个坐标像素值,求出当前(x, y)的像素值
x: 当前坐标x值(float)
y: 当前坐标y值(float)
src_img: 原图像(ndarray)
return: (x, y)的像素值(int)
"""
def four_pixels(x, y, src_img):
    x = abs(x)#前面的点会出现负数,先abs一下
    y = abs(y)
    i, j = int(x), int(y)#x,y的整数部分
    u = x - i#求出x的小数部分
    v = y - j#求出y的小数部分
    pixel = int((1-u) * (1-v) * src_img[i,j]  + u * (1 - v) * src_img[i + 1, j] + (1-u) * v * src_img[i, j + 1] + u * v * src_img[i + 1, j + 1])#根据公式(9)
    return pixel
"""
双线性插值法
src_img: 原图
des_shape: 目标图像shape
return: 缩放后图像
"""
def bilinear_interpolation(src_img, des_shape):
    src_size = src_img.shape[:-1]
    des_size = des_shape[:-1]
    src_w, src_h = src_size
    des_w, des_h = des_size
    des_img = np.zeros(des_shape)
    for i in range(des_w):
        for j in range(des_h):
            src_x = (i + 0.5) * (src_w / des_w) - 0.5#根据公式(8)
            src_y = (j + 0.5) * (src_h / des_h) - 0.5#根据公式(8)
            des_img[i, j, 0] = four_pixels(src_x, src_y, src_img[:, :, 0])
            des_img[i, j, 1] = four_pixels(src_x, src_y, src_img[:, :, 1])
            des_img[i, j, 2] = four_pixels(src_x, src_y, src_img[:, :, 2])
    des_img = des_img.astype(np.uint8)
    return des_img
bimage = bilinear_interpolation(image, (159, 401, 3))
plt.imshow(bimage)

  还是借用三体图像,运行结果如下

在这里插入图片描述


总结

  呼~
  数学简直了,又爱又恨,但是代码就好多了。要记住,编程离不开数学,数学很重要,很重要,重要,要,切克闹。感谢你的观看,再会。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/196700.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java基础—JDK基础面试题一

文章目录1.和equals区别是什么&#xff1f;2.Java中的 <<、>>、>>> 是什么3.if-else-if-else与switch的区别4.while和do-while的区别5.switch 是否能作用在 byte 上&#xff0c;是否能作用在 long 上&#xff0c;是否能作用在String上6.&和&&…

Mysql大数据表处理方案

场景&#xff1a; 当我们业务数据库表中的数据越来越多&#xff0c;如果你也和我遇到了以下类似场景&#xff0c;那让我们一起来解决这个问题 数据的插入,查询时长较长后续业务需求的扩展 在表中新增字段 影响较大表中的数据并不是所有的都为有效数据 需求只查询时间区间内的…

DynaSLAM-10 DynaSLAM中双目运行流程(Ⅳ):DynaSLAM的三大线程解析

目录 1.双目初始化部分 2.三种追踪模式 1.双目初始化部分 进入追踪线程首先判断双目追踪器状态mstate&#xff0c;在刚进入SLAM系统时&#xff0c; Tracking::Tracking函数默认将其设置为NO_IMAGES_YET&#xff0c;系统经过reset时也会将mstate设置为NO_IMAGES_YET......如果是…

【工业视觉-CCD相机和CMOS相机成像的本质区别】

工业视觉-CCD相机和CMOS相机成像的本质区别1.CCD的功耗高&#xff0c;CMOS的功耗低2.CCD速度较CMOS慢3.CCD的画质优于CMOS4.CCD的高感画质低于CMOS在学习工业视觉的起初&#xff0c;一般都是先去了解光源、镜头、相机等概念&#xff0c;在接触工业相机时看到两个概念&#xff0…

Java集合框架

Java集合框架 每博一文案 《杀死一只知更鸟》中有这样一段话&#xff1a;“你永远不可能真正地了解一个人&#xff0c;除非你穿上他的鞋子走来走去&#xff0c;站在他的角度思考问题。 可真当你走过他的路时&#xff0c;你连路过都觉得难过。” 世上没有真正的感同身受&#x…

数据结构 第六章 二叉树与树(树和森林)

1 双亲表示法(方便查找双亲) 使用层次遍历的方法将一个树中的所有结点存储到一维数组中 2 孩子表示法(方便查找孩子) 顺序链式存储结构&#xff1a; 1 使用数组来存储所有结点 2 为每一个结点来设置一个单链表 3 单链表链接的是其所有孩子结点的下标3 双亲孩子结合表示法 …

扬兴 | 选型技巧!晶振在商业显示屏的应用

据有关机构预计&#xff0c;未来五年&#xff0c;商显市场将以每年13-16%的增速发展&#xff0c;预计到2024年将达到1545亿元的规模。伴随着商显屏行业的飞速发展&#xff0c;必然带动电子元器件行业的增长&#xff0c;这也对元器件产品要求不断提高&#xff0c;其中晶振作为数…

【字符串】剑指Offer 05.替换空格(C/C++/Java/Python/Js)

剑指Offer 05.替换空格1 题目2 思路--双指针法3 代码3.1 C版本3.2 C版本3.3 Java版本3.4 Python3版本3.5 JavaScript版本4 总结1 题目 题源链接 请实现一个函数&#xff0c;把字符串 s 中的每个空格替换成"%20"。 示例 1&#xff1a; 输入&#xff1a;s “We are…

重磅!马斯克再抛特斯拉股票,去年中国市场份额首次下滑

特斯拉的走势&#xff0c;正在凸显智能电动汽车市场格局的新变化。 几周前&#xff0c;特斯拉首席执行官埃隆马斯克出售了价值近36亿美元的股票&#xff0c;就在三周前&#xff0c;这家全球智能电动汽车领头羊宣布未能实现年度交付目标&#xff08;少了近2.2万辆&#xff09;。…

windows下同时安装mysql5.5和mysql8.0.32

一、安装mysql8.0.32 我先安装的是mysql5.5&#xff0c;如&#xff1a;MySQL5.5安装教程SQLyog安装_柒七的博客-CSDN博客_mysql5.5的安装步骤 1.下载解压 https://dev.mysql.com/downloads/mysql/ 2.创建配置 下载完后&#xff0c;建议解压到一个没有中文的路径&#xff0…

Vue使用ElementUI动态修改table单元格背景颜色或文本颜色

前言 今天遇到一个场景&#xff0c;表格行属性的字典项要针对不同的状态&#xff0c;展示不同的文本颜色&#xff0c;如下图所示&#xff1a; 账号状态这一栏&#xff0c;如果是正常就展示以绿色字体展示&#xff0c;如果是禁用就以红色颜色展示 针对这个需求&#xff0c;我第…

u盘文件被电脑杀毒软件删掉了,怎么才能恢复

案例分享&#xff1a;【我的u盘中毒文件被电脑杀毒软件删掉了&#xff0c;怎么才能恢复啊&#xff1f;&#xff1f;里面有很重要的资料。求高手指点&#xff01;急&#xff01;&#xff01;&#xff01;】——虽然u盘能够存储数据&#xff0c;且体积小巧便于携带&#xff0c;但…

算法:(十二)排序

文章目录12.1 计数排序面试题75&#xff1a;数组相对排序12.2 快速排序面试题76&#xff1a;数组中第k大的数12.3 归并排序面试题77&#xff1a;链表排序面试题78&#xff1a;合并排序链表12.1 计数排序 面试题75&#xff1a;数组相对排序 题目&#xff1a; 给定两个数组&…

UNIAPP实战项目笔记57 发送手机验证码 接入短信SDK

UNIAPP实战项目笔记57 发送手机验证码 接入短信SDK 注册时候需要发送验证 通过验阿里云或腾讯云等短信sdk供应商 实际案例图片 后端接口文件 index.js var express require(express); var router express.Router(); var connection require(../db/sql.js); var user requi…

龙芯处理器7A2000桥片iTOP-3A5000开发板

龙芯处理器7A2000桥片iTOP-3A5000开发板 主要参数 处理器: 龙芯3A5000 主频: 2.3GHz-2.5GHz 桥片: 7A2000 内存: 8GB、16GB DDR4带ECC纠错&#xff08;配置可选&#xff09; 系统: Loongnix 典型功耗: 35W 核心板: 16层 底板: 4层 核心板参数 尺寸: 125*95mm C…

力扣二叉树篇题

题目说明B树如果为空树则不是A树的子结构 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode(int x) { val x; }* }*/ class Solution {public boolean isSubStructure(TreeNode A,…

VMware ESXi 7.0 Update 3j 更新发布,修复已知问题

VMware ESXi 7.0 Update 3j Standard & All Custom Image for ESXi 7.0 U3j Install CD 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-esxi-7-u3/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;www.sysin.org 产品简介…

迁移mysql数据库到opengauss

一、安装chameleon工具1.下载源码git clone gitgitee.com:opengauss/openGauss-tools-chameleon.git2.创建Python虚拟环境并激活安装依赖&#xff1a;yum install mysql-devel gcc gcc-devel python-develpython3 -m venv venvsource venv/bin/activate3.进入代码的目录&#x…

CAD转PDF其实很简单,掌握这4种方法就可以

Hello&#xff0c;大家好&#xff0c;这里是建模助手&#xff01; CAD作为一种绘图格式&#xff0c;在工业设计领域发挥着不可替代的作用&#xff0c;一般有DXF、DWG两种常见的格式&#xff0c;但是一般需要在电脑中安装特定软件才能打开此类格式的文件。 因此大多数人在给别…

网站表单实时通知 销售线索不错漏

对于企业来说&#xff0c;在进行产品发布或营销推广时&#xff0c;都需要大量的信息收集汇总。此时都会用到表单功能&#xff0c;网站上的表单功能应用非常广泛&#xff0c;可做信息收集效果&#xff0c;可做付费预约效果等&#xff0c;而如果希望能实时推送表单收集到的数据&a…