实现js的双线性插值和双三次插值法
免费学习推荐:js视频教程
- 介绍
- 双线性插值
- 原理
- 双三次插值法
- 原理
- js实现
介绍
在网页中利用canvas进行绘图时,遇到一个问题,原始的数据分辨率很小,而图片要放大到整个网页,所以需要把数据进行插值放大。学习了双线性插值和三次内插法插值,两种方式实现效果不同,都用js代码实现了一下,下面给大家分享一下
双线性插值
原理
双线性插值即在x和y两个方向上,对数据各进行一次线性插值。
原始数据的矩阵,即一个二维数组,大小为a*b,目标矩阵大小为m*n,m、n比a、b可以大(放大),也可以小(缩小),当然比例也可以不一样, 取决于你插值后的数据需要多大。
基本思想为,遍历目标矩阵的坐标,如x*y这个点,找到这个点在原始矩阵中对应的位置,称为映射点,然后找到这个映射点P在原始矩阵中周围的四个点,然后根据映射点P到这个四个点的x和y方向上的坐标的距离,进行两次线性插值,得到映射点的值即可。
如上图所示,p点为目标矩阵中x*y点在原始矩阵中映射的位置,它周围最近的有Q12,Q11,Q21,Q22四个点,现在x方向进行线性插值,得到R1和R2两个点的值,再在y方向进行一次线性插值,得到P点的值。
注意:用双线性插值放大数据后,如果放大倍数过大,生成图片后发现有着明显的马赛克现象
实现代码参考后面js代码
双三次插值法
原理
双三次插值又称立方卷积插值。三次卷积插值是一种更加复杂的插值方式。该算法利用待采样点周围16个点的灰度值作三次插值,不仅考虑到4 个直接相邻点的灰度影响,而且考虑到各邻点间灰度值变化率的影响。具体的原理可参考下面博客:
参考这里的博客
基本原理就是,先找到目标矩阵中点在源数据矩阵中的映射点P,然后找到P点周围16个点,然后根据P点坐标距离16个点的x和y方向的距离,利用BiCubic函数算出每个点的权重,最后每个点乘以权重后,加起来即可得到P的值。
BiCubic函数:
其中,a取-0.5时,BiCubic函数具有如下形状:
取a=-0.5时,放大的数据挺好,生成的图片非常平滑,也保留了很多细节。
具体为什么要用这个函数,我也没有深入研究,不过利用该方法放大数据后,生成图片效果很好,没有马赛克现象
js实现
/** * 数据处理工具类(也可以自己直接定义方法,不用class) */class DataUtil { constructor() {}}/** * 数据插值 * @param w 目标矩阵宽度 * @param h 目标矩阵高度 * @param data 源数据矩阵(二维数组) * @param type 插值方式,1:双线性插值,2:双三次插值法 */DataUtil.scaleData = function(w, h, data, type = 2) { let t1 = new Date().getTime(); let dw = data[0].length; let dh = data.length; let resData = new Array(h); for (let j = 0; j < h; j++) { let line = new Array(w); for (let i = 0; i < w; i++) { let v; if (type === 2) { // 双三次插值法 v = DataUtil.cubicInterpolation(w, h, i, j, data); } else if (type === 1) { // 双线性插值 v = DataUtil.interpolation(w, h, i, j, data); } else { throw new Error('scale data, type not supported(type must be 1 or 2)'); } line[i] = Math.round(v); } resData[j] = line; } let t2 = new Date().getTime(); console.log("数据插值耗时:", (t2 - t1)); return resData;}/** * 双线性插值 * @param sw 目标矩阵的宽度 * @param sh 目标矩阵的高度 * @param x_ 目标矩阵中的x坐标 * @param y_ 目标矩阵中的y坐标 * @param data 源数据矩阵(二维数组) */DataUtil.interpolation = function(sw, sh, x_, y_, data) { let t1 = new Date().getTime(); let w = data[0].length; let h = data.length; let x = (x_ + 0.5) * w / sw - 0.5; let y = (y_ + 0.5) * h / sh - 0.5; let x1 = Math.floor(x); let x2 = Math.floor(x + 0.5); let y1 = Math.floor(y); let y2 = Math.floor(y + 0.5); x1 = x1 < 0 ? 0 : x1; y1 = y1 < 0 ? 0 : y1; x1 = x1 < w - 1 ? x1 : w - 1; y1 = y1 < h - 1 ? y1 : h - 1; x2 = x2 < w - 1 ? x2 : w - 1; y2 = y2 < h - 1 ? y2 : h - 1; // 取出原矩阵中对应四个点的值 let f11 = data[y1][x1]; let f21 = data[y1][x2]; let f12 = data[y2][x1]; let f22 = data[y2][x2]; // 计算该点的值 let xm = x - x1; let ym = y - y1; let r1 = (1 - xm) * f11 + xm * f21; let r2 = (1 - xm) * f12 + xm * f22; let value = (1-ym) * r1 + ym * r2; return value;}/** * 双三次插值法 * @param sw 目标矩阵的宽度 * @param sh 目标矩阵的高度 * @param x_ 目标矩阵中的x坐标 * @param y_ 目标矩阵中的y坐标 * @param data 源数据矩阵(二维数组) */DataUtil.cubicInterpolation = function (sw, sh, x_, y_, data) { let w = data[0].length; let h = data.length; // 计算缩放后坐标对应源数据上的坐标 let x = x_ * w / sw; let y = y_ * h / sh; // 计算x和y方向的最近的4*4的坐标和权重 let wcx = DataUtil.getCubicWeight(x); let wcy = DataUtil.getCubicWeight(y); // 权重 let wx = wcx.weight; let wy = wcy.weight; // 坐标 let xs = wcx.coordinate; let ys = wcy.coordinate; let val = 0; // 遍历周围4*4的点,根据权重相加 for (let j = 0; j < 4; j++) { let py = ys[j]; py = py < 0 ? 0 : py; py = py > h - 1 ? h - 1 : py; for (let i = 0; i < 4; i++) { let px = xs[i]; px = px < 0 ? 0 : px; px = px > w - 1 ? w - 1 : px; // 该点的值 let dv = data[py][px]; // 该点的权重 let w_x = wx[i]; let w_y = wy[j]; // 根据加权加起来 val += (dv * w_x * w_y); } } return val;}/** * 双三次插值法中,基于BiCubic基函数,计算源坐标v,最近的4*4的坐标和坐标对应的权重 * @param v 目标矩阵中坐标对应在源矩阵中坐标值 */DataUtil.getCubicWeight = function (v){ let a = -0.5; // 取整 let nv = Math.floor(v); // 坐标差值集合 let xList = new Array(4); // 坐标集合 let xs = new Array(4); // 最近的4个坐标差值 xList[0] = nv - v - 1; xList[1] = nv - v xList[2] = nv - v + 1; xList[3] = nv - v + 2; // xs[0] = nv - 1; xs[1] = nv; xs[2] = nv + 1; xs[3] = nv + 2; // 计算权重 let ws = new Array(4); for (let i = 0; i < 4; i++) { let val = Math.abs(xList[i]); let w = 0; // 基于BiCubic基函数的双三次插值 if (val <= 1) { w = (a + 2) * val * val * val - (a + 3) * val * val + 1; } else if (val < 2) { w = a * val * val * val - 5 * a * val * val + 8 * a * val - 4 * a; } ws[i] = w; } return { weight: ws, coordinate: xs };}
相关免费学习推荐:javascript(视频)
Atas ialah kandungan terperinci 实现js的双线性插值和双三次插值法. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Cara menggunakan WebSocket dan JavaScript untuk melaksanakan sistem pengecaman pertuturan dalam talian Pengenalan: Dengan perkembangan teknologi yang berterusan, teknologi pengecaman pertuturan telah menjadi bahagian penting dalam bidang kecerdasan buatan. Sistem pengecaman pertuturan dalam talian berdasarkan WebSocket dan JavaScript mempunyai ciri kependaman rendah, masa nyata dan platform merentas, dan telah menjadi penyelesaian yang digunakan secara meluas. Artikel ini akan memperkenalkan cara menggunakan WebSocket dan JavaScript untuk melaksanakan sistem pengecaman pertuturan dalam talian.

WebSocket dan JavaScript: Teknologi utama untuk merealisasikan sistem pemantauan masa nyata Pengenalan: Dengan perkembangan pesat teknologi Internet, sistem pemantauan masa nyata telah digunakan secara meluas dalam pelbagai bidang. Salah satu teknologi utama untuk mencapai pemantauan masa nyata ialah gabungan WebSocket dan JavaScript. Artikel ini akan memperkenalkan aplikasi WebSocket dan JavaScript dalam sistem pemantauan masa nyata, memberikan contoh kod dan menerangkan prinsip pelaksanaannya secara terperinci. 1. Teknologi WebSocket

Pengenalan kepada cara menggunakan JavaScript dan WebSocket untuk melaksanakan sistem pesanan dalam talian masa nyata: Dengan populariti Internet dan kemajuan teknologi, semakin banyak restoran telah mula menyediakan perkhidmatan pesanan dalam talian. Untuk melaksanakan sistem pesanan dalam talian masa nyata, kami boleh menggunakan teknologi JavaScript dan WebSocket. WebSocket ialah protokol komunikasi dupleks penuh berdasarkan protokol TCP, yang boleh merealisasikan komunikasi dua hala masa nyata antara pelanggan dan pelayan. Dalam sistem pesanan dalam talian masa nyata, apabila pengguna memilih hidangan dan membuat pesanan

Cara menggunakan WebSocket dan JavaScript untuk melaksanakan sistem tempahan dalam talian Dalam era digital hari ini, semakin banyak perniagaan dan perkhidmatan perlu menyediakan fungsi tempahan dalam talian. Adalah penting untuk melaksanakan sistem tempahan dalam talian yang cekap dan masa nyata. Artikel ini akan memperkenalkan cara menggunakan WebSocket dan JavaScript untuk melaksanakan sistem tempahan dalam talian dan memberikan contoh kod khusus. 1. Apakah itu WebSocket? WebSocket ialah kaedah dupleks penuh pada sambungan TCP tunggal.

JavaScript dan WebSocket: Membina sistem ramalan cuaca masa nyata yang cekap Pengenalan: Hari ini, ketepatan ramalan cuaca sangat penting kepada kehidupan harian dan membuat keputusan. Apabila teknologi berkembang, kami boleh menyediakan ramalan cuaca yang lebih tepat dan boleh dipercayai dengan mendapatkan data cuaca dalam masa nyata. Dalam artikel ini, kita akan mempelajari cara menggunakan teknologi JavaScript dan WebSocket untuk membina sistem ramalan cuaca masa nyata yang cekap. Artikel ini akan menunjukkan proses pelaksanaan melalui contoh kod tertentu. Kami

Tutorial JavaScript: Bagaimana untuk mendapatkan kod status HTTP, contoh kod khusus diperlukan: Dalam pembangunan web, interaksi data dengan pelayan sering terlibat. Apabila berkomunikasi dengan pelayan, kami selalunya perlu mendapatkan kod status HTTP yang dikembalikan untuk menentukan sama ada operasi itu berjaya dan melaksanakan pemprosesan yang sepadan berdasarkan kod status yang berbeza. Artikel ini akan mengajar anda cara menggunakan JavaScript untuk mendapatkan kod status HTTP dan menyediakan beberapa contoh kod praktikal. Menggunakan XMLHttpRequest

Penggunaan: Dalam JavaScript, kaedah insertBefore() digunakan untuk memasukkan nod baharu dalam pepohon DOM. Kaedah ini memerlukan dua parameter: nod baharu untuk dimasukkan dan nod rujukan (iaitu nod di mana nod baharu akan dimasukkan).

JavaScript ialah bahasa pengaturcaraan yang digunakan secara meluas dalam pembangunan web, manakala WebSocket ialah protokol rangkaian yang digunakan untuk komunikasi masa nyata. Menggabungkan fungsi berkuasa kedua-duanya, kami boleh mencipta sistem pemprosesan imej masa nyata yang cekap. Artikel ini akan memperkenalkan cara untuk melaksanakan sistem ini menggunakan JavaScript dan WebSocket, dan memberikan contoh kod khusus. Pertama, kita perlu menjelaskan keperluan dan matlamat sistem pemprosesan imej masa nyata. Katakan kita mempunyai peranti kamera yang boleh mengumpul data imej masa nyata
