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. 输出图像到数组中

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

    最后去得到一个 arrayBuffer 数组

下一阶段

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

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

代码实现

  1. import Img from "./img/img1.jpg";
  2. // 两种着色器
  3. const VSHADER_SOURCE = `
  4. attribute vec4 a_Position;
  5. attribute vec2 uv;
  6. varying vec2 vUv;
  7. void main(){
  8. // 进行插值计算
  9. vUv = uv;
  10. gl_Position = a_Position;
  11. }
  12. `;
  13. const FSHADER_SOURCE = `
  14. // 片元着色器中一定要声明精度
  15. precision mediump float;
  16. varying vec2 vUv;
  17. uniform sampler2D u_Texture;
  18. // 求平均
  19. vec4 calculate(vec4 color, vec2 vUv){
  20. vec4 tempColor = color;
  21. if(vUv.x != 0.0 && vUv.y != 0.0){
  22. vec4 left = texture2D(u_Texture, floor(vUv * 200.0 + vec2(-1.0, 0.0)) / 200.0);
  23. vec4 right = texture2D(u_Texture, floor(vUv * 200.0 + vec2(1.0, 0.0)) / 200.0);
  24. vec4 top = texture2D(u_Texture, floor(vUv * 200.0 + vec2(0.0, 1.0)) / 200.0);
  25. vec4 bottom = texture2D(u_Texture, floor(vUv * 200.0 + vec2(0.0, -1.0)) / 200.0);
  26. // tempColor.rg = 1.0 * (left.rg + right.rg + top.rg + tempColor.rg + bottom.rg) / 5.0;
  27. tempColor = 1.0 * (left + right + top + tempColor + bottom) / 5.0;
  28. }
  29. return tempColor;
  30. }
  31. void main(){
  32. vec4 color = texture2D(u_Texture, vUv);
  33. color = calculate(color, vUv);
  34. gl_FragColor = color;
  35. }
  36. `;
  37. init();
  38. function init() {
  39. const canvas = document.createElement("canvas");
  40. canvas.width = 200;
  41. canvas.height = 200;
  42. document.body.appendChild(canvas);
  43. // 获取 gl 环境
  44. const gl = canvas.getContext("webgl");
  45. if (!gl) {
  46. console.log("Fail to init content");
  47. return;
  48. }
  49. // webgl 程序
  50. const programe = gl.createProgram();
  51. // 初始化着色器
  52. initShader(gl, VSHADER_SOURCE, FSHADER_SOURCE, programe);
  53. // 发送数据
  54. sendData("a_Position", 2, [-1, 1, -1, -1, 1, -1, 1, 1], gl, programe);
  55. sendData("uv", 2, [0, 1, 0, 0, 1, 0, 1, 1], gl, programe);
  56. // 加载图片
  57. loadImage(gl, programe);
  58. }
  59. // 初始化着色器
  60. function initShader(gl, VSHADER_SOURCE, FSHADER_SOURCE, programe) {
  61. // 创建 shader
  62. const vertexShader = gl.createShader(gl.VERTEX_SHADER);
  63. // 绑定资源
  64. gl.shaderSource(vertexShader, VSHADER_SOURCE);
  65. // 编译着色器
  66. gl.compileShader(vertexShader);
  67. const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER, FSHADER_SOURCE);
  68. gl.shaderSource(fragmentShader, FSHADER_SOURCE);
  69. gl.compileShader(fragmentShader);
  70. // 常规流程
  71. gl.attachShader(programe, vertexShader);
  72. gl.attachShader(programe, fragmentShader);
  73. gl.linkProgram(programe);
  74. gl.useProgram(programe);
  75. }
  76. // 发送数据到 GPU
  77. function sendData(name, size, arr, gl, programe) {
  78. // 获取地址空间
  79. const variate = gl.getAttribLocation(programe, name);
  80. if (variate < 0) {
  81. console.log(`Failed to get the location of ${name}`);
  82. return;
  83. }
  84. const variates = new Float32Array(arr);
  85. // 1. 创建缓存区
  86. const buffer = gl.createBuffer();
  87. if (!buffer) {
  88. console.log("Failed to create buffer");
  89. }
  90. // 2. 绑定缓存区
  91. gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  92. // 3. 向缓冲区中添加数据
  93. gl.bufferData(gl.ARRAY_BUFFER, variates, gl.STATIC_DRAW);
  94. // 4. 将缓冲区与 glsl 中变量绑定
  95. gl.vertexAttribPointer(variate, size, gl.FLOAT, false, 0, 0);
  96. // 5. 开始传输
  97. gl.enableVertexAttribArray(variate);
  98. }
  99. function loadImage(gl, programe){
  100. // 初始化 Image
  101. const image = new Image();
  102. // 通过 loader 加载图像路径
  103. image.src = Img;
  104. // 设置回调函数
  105. image.onload = ()=>{
  106. const texture = gl.createTexture();
  107. // y 轴反转
  108. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
  109. // 激活 0 号纹理单元
  110. gl.activeTexture(gl.TEXTURE0);
  111. // 绑定 texture
  112. gl.bindTexture(gl.TEXTURE_2D, texture);
  113. // 图像处理, 一定要有, 用来将图片宽高扩展到 2 的幂
  114. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);// 配置纹理参数
  115. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  116. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
  117. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
  118. // 配置图片
  119. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); // 配置纹理图像
  120. // 传输图片
  121. const u_Texture = gl.getUniformLocation(programe, "u_Texure");
  122. gl.uniform1i(u_Texture, 0);
  123. // 刷新颜色
  124. gl.clearColor(0.0, 0.0, 0.0, 1.0);
  125. // 清除
  126. gl.clear(gl.COLOR_BUFFER_BIT);
  127. // 画图形
  128. gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);
  129. // 将图片数据加载到 pixels 数组中
  130. const pixels = new Uint8Array(200 * 200 *4);
  131. gl.readPixels(0, 0, 200, 200, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
  132. console.log(pixels);
  133. }
  134. }

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. Alibaba-技术专区-Dubbo3总体技术体系介绍及技术指南(序章)

    Dubbo的背景介绍 Apache Dubbo 是一款微服务开发框架(是一款高性能.轻量级的开源 Java 服务框架),它提供了 RPC通信 与 微服务治理 两大关键能力.这意味着,使用 Dubbo ...

  2. 深入理解jvm-2Edition-Java内存区域

    1.运行时数据区域 Java虚拟机会将内存区域划分为几个区域,每个区域储存不同类型的数据或承担不同的功能. PC,堆-Java堆,栈-虚拟机栈.本地方法栈,方法区.直接内存. 当类被实例化或stati ...

  3. 前端 | Nuxt.js axios baseURL,proxy 代理

    平时用 Vue 写前端时,对于 axios 请求的常规操作一般是 统一定义好一个 axios 对象,使用 axios.defaults.baseURL 设置 baseURL 也不是不能直接把服务器地址 ...

  4. Java 多线程与并发【知识点笔记】

    Java 多线程与并发[知识点笔记] Java多线程与并发 先说一下线程与进程的由来: 在初期的计算机,计算机只能串行执行任务,并且需要长时间的等待用户的输入才行 到了后来,出现了批处理,可以预先将用 ...

  5. php本地文件包含 Writeup

    目录 本地文件包含 LFI本地文件包含案例一 LFI本地文件包含案例二 本地文件包含简介 文件包含函数加载的参数没有经过过滤或者严格的定义,可以被用户控制,包含其他恶意文件,导致了执行了非预期的代码. ...

  6. Java社区——个人项目开发笔记(一)

    1.maven安装与测试 安装过程略,常用的maven命令行工具: mvn --version 查看maven版本 mvn compile 编译maven工程 mvn clean 删除编译文件 mvn ...

  7. 从自旋锁、睡眠锁、读写锁到 Linux RCU 机制讲解

    ​    同步自我的 csdn 博客 6.S081 从自旋锁.睡眠锁.读写锁到 Linux RCU 机制讲解_我说我谁呢 --CSDN博客 总结一下 O/S 课程里面和锁相关的内容. 本文是 6.S0 ...

  8. ReentrantLock中的Condition(等待和唤醒)

    Condition 类的 awiat 方法和 Object 类的 wait 方法等效 Condition 类的 signal 方法和 Object 类的 notify 方法等效 Condition 类 ...

  9. Centos7上yum安装mongodb(安装epel中的版本可能会比较老)

    yum install epel-release 搜索mongodb-server 安装mongodb yum install mongodb-server.x86_64 配置mongodb vim ...

  10. C# 通过反射实现对象映射:将2个属性相近的对象相互转换

    前言 我们在编程过程中,经常需要将一个对象转成另一个对象(一般称为对象映射). 比如我们有2个类: //第1个类 CLS1 class CLS1 { public int i {get; set;} ...