webgl 图像处理

webgl 不仅仅可以用来进行图形可视化, 它还能进行图像处理

图像处理2---图像传输

之前已经进行了点和 uv 数据的传输

webgl 进行图形处理的第二步: 传输图片到 GPU

下图为传输图片并进行相应渲染的结果

对图像进行模糊处理, 并转换为数组输出

处理过程详解

  1. 加载图片

    1. 由于加载图片是异步方法, 因此很多内容都需要写在加载图片的回调函数内
    2. 在回调函数中进行传输图片操作
  2. 传输图片到 GPU

    1. 之前传输数据的步骤

      1. 创建缓存区
      2. 绑定缓冲区
      3. 向缓存区中写入内容
      4. 绑定 shader 中的变量
      5. 开始传输数据
    2. 现在传输图像的步骤, 类似
      1. 创建材质 Texture ( 对应前面第 1 步 )
      2. y 轴反转, 这是由于浏览器 y 轴向下, 需要矫正
      3. 激活纹理单元 ( 简单理解为与纹理绑定的 内容, 一个纹理绑定一个纹理单元 )
      4. 绑定 texture ( 对应前面第 2 步)
      5. 配置图片信息, 两种, 一种是缩放相关参数, 用来将图片的宽高置为 2 的幂次方, 一种是图片内容 ( 对应前面第 3 步)
      6. 传输图片 ( 对应前面第 4,5 步)
  3. 查询当前像素的上下左右的颜色值并进行平均

    1. 当前节点的 uv 为 vUv, 是一个二维向量, 范围从 0-1
    2. 由于图片设置为 200 * 200, 因此可以将 vUv 转换为具体的像素点位置, floor(vUv * 200.0)/200.0
    3. 计算周边点的位置及像素值
      1. 例如该像素左边点位置为, floor(vUv * 200.0 + vec2(-1.0, 0.0)) / 200.0
      2. 像素值为, texture2D(u_Texture, floor(vUv * 200.0 + vec2(-1.0, 0.0)) / 200.0)
  4. 输出图像到数组中

    // 将图片数据加载到 pixels 数组中
    const pixels = new Uint8Array(200 * 200 *4);
    gl.readPixels(0, 0, 200, 200, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
    console.log(pixels);

    最后去得到一个 arrayBuffer 数组

下一阶段

当前阶段对图片进行像素颗粒的控制, 利用这个思路能实现大部分对图片的操作

下个阶段是输入一个数组, 在 GPU 中对数组进行计算, 最后得到相应的数值, 加速计算, 充分利用 GPU 并行计算的能力

代码实现

import Img from "./img/img1.jpg";

// 两种着色器
const VSHADER_SOURCE = `
attribute vec4 a_Position;
attribute vec2 uv;
varying vec2 vUv;
void main(){
// 进行插值计算
vUv = uv;
gl_Position = a_Position;
}
`; const FSHADER_SOURCE = `
// 片元着色器中一定要声明精度
precision mediump float;
varying vec2 vUv;
uniform sampler2D u_Texture; // 求平均
vec4 calculate(vec4 color, vec2 vUv){
vec4 tempColor = color;
if(vUv.x != 0.0 && vUv.y != 0.0){
vec4 left = texture2D(u_Texture, floor(vUv * 200.0 + vec2(-1.0, 0.0)) / 200.0);
vec4 right = texture2D(u_Texture, floor(vUv * 200.0 + vec2(1.0, 0.0)) / 200.0);
vec4 top = texture2D(u_Texture, floor(vUv * 200.0 + vec2(0.0, 1.0)) / 200.0);
vec4 bottom = texture2D(u_Texture, floor(vUv * 200.0 + vec2(0.0, -1.0)) / 200.0);
// tempColor.rg = 1.0 * (left.rg + right.rg + top.rg + tempColor.rg + bottom.rg) / 5.0;
tempColor = 1.0 * (left + right + top + tempColor + bottom) / 5.0;
} return tempColor;
} void main(){
vec4 color = texture2D(u_Texture, vUv); color = calculate(color, vUv); gl_FragColor = color;
}
`; init(); function init() {
const canvas = document.createElement("canvas");
canvas.width = 200;
canvas.height = 200;
document.body.appendChild(canvas); // 获取 gl 环境
const gl = canvas.getContext("webgl");
if (!gl) {
console.log("Fail to init content");
return;
} // webgl 程序
const programe = gl.createProgram(); // 初始化着色器
initShader(gl, VSHADER_SOURCE, FSHADER_SOURCE, programe); // 发送数据
sendData("a_Position", 2, [-1, 1, -1, -1, 1, -1, 1, 1], gl, programe); sendData("uv", 2, [0, 1, 0, 0, 1, 0, 1, 1], gl, programe); // 加载图片
loadImage(gl, programe); } // 初始化着色器
function initShader(gl, VSHADER_SOURCE, FSHADER_SOURCE, programe) {
// 创建 shader
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
// 绑定资源
gl.shaderSource(vertexShader, VSHADER_SOURCE);
// 编译着色器
gl.compileShader(vertexShader);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER, FSHADER_SOURCE);
gl.shaderSource(fragmentShader, FSHADER_SOURCE);
gl.compileShader(fragmentShader); // 常规流程
gl.attachShader(programe, vertexShader);
gl.attachShader(programe, fragmentShader);
gl.linkProgram(programe);
gl.useProgram(programe);
} // 发送数据到 GPU
function sendData(name, size, arr, gl, programe) {
// 获取地址空间
const variate = gl.getAttribLocation(programe, name);
if (variate < 0) {
console.log(`Failed to get the location of ${name}`);
return;
}
const variates = new Float32Array(arr);
// 1. 创建缓存区
const buffer = gl.createBuffer();
if (!buffer) {
console.log("Failed to create buffer");
}
// 2. 绑定缓存区
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
// 3. 向缓冲区中添加数据
gl.bufferData(gl.ARRAY_BUFFER, variates, gl.STATIC_DRAW);
// 4. 将缓冲区与 glsl 中变量绑定
gl.vertexAttribPointer(variate, size, gl.FLOAT, false, 0, 0);
// 5. 开始传输
gl.enableVertexAttribArray(variate);
} function loadImage(gl, programe){
// 初始化 Image
const image = new Image();
// 通过 loader 加载图像路径
image.src = Img; // 设置回调函数
image.onload = ()=>{
const texture = gl.createTexture();
// y 轴反转
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
// 激活 0 号纹理单元
gl.activeTexture(gl.TEXTURE0);
// 绑定 texture
gl.bindTexture(gl.TEXTURE_2D, texture);
// 图像处理, 一定要有, 用来将图片宽高扩展到 2 的幂
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);// 配置纹理参数
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); // 配置图片
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); // 配置纹理图像
// 传输图片
const u_Texture = gl.getUniformLocation(programe, "u_Texure");
gl.uniform1i(u_Texture, 0); // 刷新颜色
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// 清除
gl.clear(gl.COLOR_BUFFER_BIT);
// 画图形
gl.drawArrays(gl.TRIANGLE_FAN, 0, 4); // 将图片数据加载到 pixels 数组中
const pixels = new Uint8Array(200 * 200 *4);
gl.readPixels(0, 0, 200, 200, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
console.log(pixels);
} }

webgl 图像处理2---图像传输的更多相关文章

  1. webgl 图像处理 加速计算

    webgl 图像处理 webgl 不仅仅可以用来进行图形可视化, 它还能进行图像处理 图像处理1---数据传输 webgl 进行图形处理的第一步: 传输数据到 GPU 下图为传输点数据到 GPU 并进 ...

  2. WebGL 与 WebGPU比对[6] - 纹理

    目录 1. WebGL 中的纹理 1.1. 创建二维纹理与设置采样参数 1.2. 纹理数据写入与拷贝 1.3. 着色器中的纹理 1.4. 纹理对象 vs 渲染缓冲对象 1.5. 立方体六面纹理 1.6 ...

  3. HTML5 学习总结(四)——canvas绘图、WebGL、SVG

    一.Canvas canvas是HTML5中新增一个HTML5标签与操作canvas的javascript API,它可以实现在网页中完成动态的2D与3D图像技术.<canvas> 标记和 ...

  4. 共有31款PHP 图形/图像处理开源软件(转)

    详情点击:http://www.oschina.net/project/lang/22/php?tag=141&os=0&sort=view PHP 图像处理库 Grafika Gra ...

  5. canvas绘图、WebGL、SVG

    目录 一.Canvas 1.1.创建canvas元素 1.2.画线 1.3.绘制矩形 1.4.绘制圆弧 1.5.绘制图像 1.6.绘制文字 1.7.随机颜色与简单动画 二.WebGL 2.1.HTML ...

  6. HTML5 学习笔记(四)——canvas绘图、WebGL、SVG

    一.Canvas canvas是HTML5中新增一个HTML5标签与操作canvas的javascript API,它可以实现在网页中完成动态的2D与3D图像技术.<canvas> 标记和 ...

  7. DICOM医学图像处理:DIMSE消息发送与接收“大同小异”之DCMTK fo-dicom mDCM

    背景: 从DICOM网络传输一文开始,相继介绍了C-ECHO.C-FIND.C-STORE.C-MOVE等DIMSE-C服务的简单实现,博文中的代码给出的实例都是基于fo-dicom库来实现的,原因只 ...

  8. Canvas绘图方法和图像处理方法(转)

    转自:http://javascript.ruanyifeng.com/htmlapi/canvas.html 概述 Canvas API(画布)用于在网页实时生成图像,并且可以操作图像内容,基本上它 ...

  9. 开源免费跨平台opengl opencv webgl gtk blender, opengl贴图程序

    三维图形的这是opengl的强项,大型3D游戏都会把它作为首选.图像处理,是opencv的锁定的目标,大多都是C的api,也有少部分是C++的,工业图像表现,图像识别,都会考虑opencv的.webg ...

随机推荐

  1. Java8新特性(一)之Lambda表达式

    .personSunflowerP { background: rgba(51, 153, 0, 0.66); border-bottom: 1px solid rgba(0, 102, 0, 1); ...

  2. 【动画消消乐|CSS】086.炫酷水波浪Loading过渡动画

    前言 Hello!小伙伴! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出-   自我介绍 ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简介:因C语言结识编程,随后转入计 ...

  3. JVM G1GC的算法与实现

    G1GC 是什么? 一些基本概念 实时性 G1GC 有什么特点? G1GC 的堆结构是什么样的? G1GC 的执行过程是什么样的? 并发标记 并发标记是什么 标记位图 执行步骤 步骤 1--初始标记阶 ...

  4. SpringMVC学习07(Ajax)

    7.Ajax研究 7.1 简介 AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML). AJAX 是一种在无需重新加载整个网页的情况 ...

  5. ECDSA—模加减模块

    如果a,b GF(P),则加法运算a+b=r (mod p),其中r满足0<r<p-1,即a+b除以p的余数,该操作成为模p加法.对于模减运算可以视为另类的模加运算,即a+(-b)=k ( ...

  6. GC垃圾收集器

    垃圾收集器是垃圾收集算法的具体实现,是执行垃圾收集算法的,是守护线程. HotSport虚拟机采用分代收集(JVM规范并未对堆区进行划分),将堆分为年轻代和老年代,垃圾收集器也是这样组合使用的,不过已 ...

  7. SpringDataJpa使用原生sql(EntityManager)动态拼接,分页查询

    SpringDataJpa Spring Data JPA是较大的Spring Data系列的一部分,可轻松实现基于JPA的存储库.该模块处理对基于JPA的数据访问层的增强支持.它使构建使用数据访问技 ...

  8. linux 常用命令(五)——(centos7-centos6.8)JDK安装

    1.安装jdk前先检测系统是否带有OpenJDK:若存在则删除 查看: java -version 查询出OpenJDK相关的文件:rpm -qa | grep java 删除OpenJDK相关的文件 ...

  9. Git(GitHub)配合TortoiseGit使用

    1.首先下载安装配置Git 安装请参照 https://www.cnblogs.com/xueweisuoyong/p/11914045.html 配置请参照 https://www.jianshu. ...

  10. JOB状态与并发

    由于job每次被执行时都会创建一个新的实例, jobDetail实例时,要进行数据存储或者,特殊字段操作,需要每次schedul执行job时保留之前的数据, 那么就需要job在有状态下保持之前的数据信 ...