加入收藏 | 设为首页 | 会员中心 | 我要投稿 上海站长网 (https://www.021zz.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

webgl 图像处理2---图像处理

发布时间:2022-11-04 14:01:30 所属栏目:PHP教程 来源:网络
导读: webgl 图像处理 webgl 不仅仅可以用来进行图形可视化, 它还能进行图像处理
图像处理2---图像传输 之前已经进行了点和 uv 数据的传输
webgl 进行图形处理的第二步: 传输图片到 GPU
下图为传

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

图像处理2---图像传输 之前已经进行了点和 uv 数据的传输

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

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

图像拼接处理_php图像乱码_PHP图像处理

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

PHP图像处理_图像拼接处理_php图像乱码

处理过程详解 加载图片

由于加载图片是异步方法, 因此很多内容都需要写在加载图片的回调函数内

在回调函数中进行传输图片操作

传输图片到 GPU

之前传输数据的步骤

创建缓存区绑定缓冲区向缓存区中写入内容绑定 shader 中的变量开始传输数据 现在传输图像的步骤, 类似

创建材质 Texture ( 对应前面第 1 步 )y 轴反转, 这是由于浏览器 y 轴向下, 需要矫正激活纹理单元 ( 简单理解为与纹理绑定的 内容,一个纹理绑定一个纹理单元 )绑定 texture ( 对应前面第 2 步)配置图片信息PHP图像处理, 两种, 一种是缩放相关参数, 用来将图片的宽高置为 2 的幂次方, 一种是图片内容 ( 对应前面第 3 步) 传输图片 ( 对应前面第 4,5 步) 查询当前像素的上下左右的颜色值并进行平均当前节点的 uv 为 vUv, 是一个二维向量, 范围从 0-1

由于图片设置为 200 * 200, 因此可以将 vUv 转换为具体的像素点位置, floor(vUv * 200.0)/200.0计算周边点的位置及像素值

例如该像素左边点位置为, floor(vUv * 200.0 + vec2(-1.0, 0.0)) / 200.0像素值为, texture2D(u_Texture, floor(vUv * 200.0 + vec2(-1.0, 0.0)) / 200.0) 输出图像到数组中

// 将图片数据加载到 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);
  }
}

(编辑:上海站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!