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. linux 高并发socket通信模型

    ------select 1 一个误区很多人认为它最大可以监听1024个,实际上却是文件描述符的值不能大于等于1024,所以除掉标准输入.输出.错误输出,一定少于1024个,如果在之前还打开了其他文件 ...

  2. Create Shortcut to Get Jar File Meta Information

    You have to get meta information of cobertura.jar with command "unzip -q -c cobertura.jar META- ...

  3. Mysql5.7.34 数据库源码编译安装

    Mysql 数据库源码编译安装 MySQL是一个关系型数据库管理系统,关系型数据库是将数据保存在不同的表中,而非将所有数据放在一个大仓库内,这样就加快了速度并提高了灵活性.由于其体积小.速度快.总体拥 ...

  4. GIT-版本管理-初阶使用

    目前我用的比较多的git指令 git clone -b [branch-name]: 拉取远程指定分支代码 git status: 查看工作区修改状态 在将修改添加进暂存区的时候需要git add . ...

  5. 题解 Game

    传送门 一有「字典序最大」什么的的就懵了--这题我颓的std 首先可以发现全局最大得分很好统计,我们令它为 \(k\) 然后我们尝试构造方案,但发现无论怎么放都可能会有后效性 发现对于一个位置,可以放 ...

  6. Java Slf4j日志配置输出到文件中

    1.概述 新项目需要增加日志需求,所以网上找了下日志配置,需求是将日志保存到指定文件中.网上找了下文章,发现没有特别完整的文章,下面自己整理下. 1.Java日志概述 对于一个应用程序来说日志记录是必 ...

  7. Windows安装Svn客户端

    一.下载程序 官网地址,选择最新64位下载. 下载完成 二.安装过程 点击下一步 点击下一步 选择安装目录 点击安装 安装完成 三.修改中文 下载中文包 下载完成 点击下一步 安装完成 点击设置 选择 ...

  8. MySQL 数据库、数据表、数据的基本操作

    1.数据库(database)管理 1.1 create 创建数据库 create database firstDB; 1.2 show 查看所有数据库 mysql> show database ...

  9. C#基础知识---is与as

    一.is与as对比 is检查一个对象是否兼容于指定的类型,并返回一个Boolean值:true或者fasle. 注:is操作符永远不会抛出异常 经常按如下方法使用: ClassA { .... } O ...

  10. 梦琪小生 【转】【WPF】WPF MVVM 简单实例

    1 新建WPF 应用程序WPFMVVMExample 程序结构如下图所示. 2 Model实现 在Model文件夹下新建业务类StudentModel(类文件StudentModel.cs),类的详细 ...