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. Python日志记录

    官方文档:https://docs.python.org/2/library/logging.html logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为, ...

  2. Windows内核-7-(IRP)I/O请求包

    Windows内核-7-(IRP)I/O请求包 IRP(I/O Request Packet)就是一个进行I/O操作的请求包. IRP是一个结构体,谁分配谁就得释放,通常由执行体里的管理器,获取内核驱 ...

  3. docker加速器,设置cdn

    添加加速器 vim /etc/docker/daemon.json 添加如下内容 { "registry-mirrors": ["https://registry.doc ...

  4. 基于typescript编写vue的ts文件语法模板

    1 <template> 2 <div> 3 <input v-model="msg"> 4 <p>prop: {{ propMes ...

  5. spring4整合hibernate5以及出现的问题解决办法

    每一次的学习,都是一小步一小步的进行的,学习语言,重要的是能把hello world写出来 以及在学习过程中出现的问题能够及时的记录并总结 spring目前最新的版本是4.3,而hibernate是5 ...

  6. SpringBoot集成<个推推送> Maven 下载jar包异常处理本地打包下载

    问题描述 公司需要对用户进行消息推送,选择了个推,由于是Java进行开发,个推操作文档, 这是官网上安装的方式,可是不成功,无论怎么样都无法把Jar包下载下来! MAVEN方式(本人测试Jar无法下载 ...

  7. 莫逸风CSDN文章目录

    『Ⅱ』-----随笔 莫逸风CSDN文章目录 The Programmer's Oath程序员的誓言-- 今天突发奇想写了一个小工具,CSDN文章目录生成器 vue去掉一些烦人的校验规则 输入npm ...

  8. Playwright-python 教程

    安装 pip install playwright -i https://mirrors.aliyun.com/pypi/simple/ 使用阿里源,下载速度快一点. python -m playwr ...

  9. 【CSS复合选择器、元素显示模式、背景】前端小抄(3) - Pink老师自学笔记

    [CSS复合选择器.元素显示模式.背景]前端小抄(3) 本学习笔记是个人对 Pink 老师课程的总结归纳,转载请注明出处! 一.CSS的复合选择器 1.1 什么是复合选择器 在 CSS 中,可以根据选 ...

  10. Hutool中那些常用的工具类和方法

    Hutool中那些常用的工具类和方法 Hutool是一个Java工具包,它帮助我们简化每一行代码,避免重复造轮子.如果你有需要用到某些工具方法的时候,不妨在Hutool里面找找,可能就有.本文将对Hu ...