【视觉基础篇】17 # 如何使用后期处理通道增强图像效果?

简介: 【视觉基础篇】17 # 如何使用后期处理通道增强图像效果?

说明

【跟月影学可视化】学习笔记。



为什么需要后期处理通道?

由于 GPU 是并行渲染的,所以在着色器的执行中,每个像素的着色都是同时进行的,彼此独立的,不能共享信息,就不能获得某一个像素坐标周围坐标点的颜色信息,也不能获得要渲染图像的全局信息。



什么是后期处理通道?

所谓后期处理通道,是指将渲染出来的图像作为纹理输入给新着色器处理,是一种二次加工的手段。可以从纹理中获取任意 uv 坐标下的像素信息,也就相当于可以获取任意位置的像素信息。



后期处理通道的一般过程

  1. 将数据送入缓冲区
  2. 然后执行 WebGLProgram
  3. 将输出的结果再作为纹理,送入另一个 WebGLProgram 进行处理
  4. 最后输出结果


6ce12747eeda402499d62c147b63ee43.png




如何用后期处理通道实现 Blur 滤镜?

下面实现一个绘制随机三角形图案的着色器,然后使用后期处理通道对它进行高斯模糊。

这是没有进行高斯模糊的效果:


e86a822cd7a747ddb9c310cc517ed214.png

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>如何用后期处理通道实现 Blur 滤镜</title>
        <style>
            canvas {
                border: 1px dashed salmon;
            }
        </style>
    </head>
    <body>
        <canvas width="512" height="512"></canvas>
        <script src="./common/lib/gl-renderer.js"></script>
        <script>
            const vertex = `
                attribute vec2 a_vertexPosition;
                attribute vec2 uv;
                varying vec2 vUv;
                void main() {
                    gl_PointSize = 1.0;
                    vUv = uv;
                    gl_Position = vec4(a_vertexPosition, 1, 1);
                }
            `;
            const fragment = `
                #ifdef GL_ES
                precision highp float;
                #endif
                float line_distance(in vec2 st, in vec2 a, in vec2 b) {
                    vec3 ab = vec3(b - a, 0);
                    vec3 p = vec3(st - a, 0);
                    float l = length(ab);
                    return cross(p, normalize(ab)).z;
                }
                float seg_distance(in vec2 st, in vec2 a, in vec2 b) {
                    vec3 ab = vec3(b - a, 0);
                    vec3 p = vec3(st - a, 0);
                    float l = length(ab);
                    float d = abs(cross(p, normalize(ab)).z);
                    float proj = dot(p, ab) / l;
                    if(proj >= 0.0 && proj <= l) return d;
                    return min(distance(st, a), distance(st, b));
                }
                float triangle_distance(in vec2 st, in vec2 a, in vec2 b, in vec2 c) {
                    float d1 = line_distance(st, a, b);
                    float d2 = line_distance(st, b, c);
                    float d3 = line_distance(st, c, a);
                    if(d1 >= 0.0 && d2 >= 0.0 && d3 >= 0.0 || d1 <= 0.0 && d2 <= 0.0 && d3 <= 0.0) {
                        return -min(abs(d1), min(abs(d2), abs(d3))); // 内部距离为负
                    }
                    return min(seg_distance(st, a, b), min(seg_distance(st, b, c), seg_distance(st, c, a))); // 外部为正
                }
                float random (vec2 st) {
                    return fract(sin(dot(st.xy, vec2(12.9898,78.233)))*43758.5453123);
                }
                vec3 hsb2rgb(vec3 c){
                    vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0), 6.0)-3.0)-1.0, 0.0, 1.0);
                    rgb = rgb * rgb * (3.0 - 2.0 * rgb);
                    return c.z * mix(vec3(1.0), rgb, c.y);
                }
                varying vec2 vUv;
                void main() {
                    vec2 st = vUv;
                    st *= 10.0;
                    vec2 i_st = floor(st);
                    vec2 f_st = 2.0 * fract(st) - vec2(1);
                    float r = random(i_st);
                    float sign = 2.0 * step(0.5, r) - 1.0;
                    float d = triangle_distance(f_st, vec2(-1), vec2(1), sign * vec2(1, -1));
                    gl_FragColor.rgb = (smoothstep(-0.85, -0.8, d) - smoothstep(0.0, 0.05, d)) * hsb2rgb(vec3(r + 1.2, 0.5, r));
                    gl_FragColor.a = 1.0;
                }
            `;
      // 通过blurFragment,能将第一次渲染后生成的纹理 tMap 内容给显示出来。
            const blurFragment = `
                #ifdef GL_ES
                precision highp float;
                #endif
                varying vec2 vUv;
                uniform sampler2D tMap;
                uniform int axis;
                void main() {
                    vec4 color = texture2D(tMap, vUv);
                    // 高斯矩阵的权重值
                    float weight[5];
                    weight[0] = 0.227027;
                    weight[1] = 0.1945946;
                    weight[2] = 0.1216216;
                    weight[3] = 0.054054;
                    weight[4] = 0.016216;
                    // 每一个相邻像素的坐标间隔,这里的512可以用实际的Canvas像素宽代替
                    float tex_offset = 1.0 / 512.0;
                    vec3 result = color.rgb;
                    result *= weight[0];
                    for(int i = 1; i < 5; ++i) {
                        float f = float(i);
                        if(axis == 0) {
                            // x轴的高斯模糊
                            result += texture2D(tMap, vUv + vec2(tex_offset * f, 0.0)).rgb * weight[i];
                            result += texture2D(tMap, vUv - vec2(tex_offset * f, 0.0)).rgb * weight[i];
                        } else {
                            // y轴的高斯模糊
                            result += texture2D(tMap, vUv + vec2(0.0, tex_offset * f)).rgb * weight[i];
                            result += texture2D(tMap, vUv - vec2(0.0, tex_offset * f)).rgb * weight[i];
                        }
                    }
                    gl_FragColor.rgb = result.rgb;
                    gl_FragColor.a = color.a;
                }
            `;
            const canvas = document.querySelector("canvas");
            const renderer = new GlRenderer(canvas);
            const program = renderer.compileSync(fragment, vertex);
            renderer.useProgram(program);
            renderer.setMeshData([
                {
                    positions: [
                        [-1, -1],
                        [-1, 1],
                        [1, 1],
                        [1, -1],
                    ],
                    attributes: {
                        uv: [
                            [0, 0],
                            [0, 1],
                            [1, 1],
                            [1, 0],
                        ],
                    },
                    cells: [
                        [0, 1, 2],
                        [2, 0, 3],
                    ],
                },
            ]);
            // 高斯模糊有两个方向,下面分别对 x 轴和 y 轴执行 2 次渲染为例
            const blurProgram = renderer.compileSync(blurFragment, vertex);
            // 创建两个FBO(帧缓冲对象)交替使用
            const fbo1 = renderer.createFBO();
            const fbo2 = renderer.createFBO();
            // 第一次,渲染原始图形
            renderer.bindFBO(fbo1); // 绑定帧缓冲对象
            renderer.render();
            // 第二次,对x轴高斯模糊
            renderer.useProgram(blurProgram);
            renderer.setMeshData(program.meshData);
            renderer.bindFBO(fbo2);
            renderer.uniforms.tMap = fbo1.texture;
            renderer.uniforms.axis = 0;
            renderer.render();
            // 第三次,对y轴高斯模糊
            renderer.useProgram(blurProgram);
            renderer.bindFBO(fbo1);
            renderer.uniforms.tMap = fbo2.texture;
            renderer.uniforms.axis = 1;
            renderer.render();
            // 第四次,对x轴高斯模糊
            renderer.useProgram(blurProgram);
            renderer.bindFBO(fbo2);
            renderer.uniforms.tMap = fbo1.texture;
            renderer.uniforms.axis = 0;
            renderer.render();
            // 第五次,对y轴高斯模糊
            renderer.useProgram(blurProgram);
            renderer.bindFBO(null);
            renderer.uniforms.tMap = fbo2.texture;
            renderer.uniforms.axis = 1;
            renderer.render();
        </script>
    </body>
</html>

高斯模糊之后,效果如下:

672d873c806c4cfeaa4d3d4622ecfb59.png


如何用后期处理通道实现辉光效果?

实现它的关键,就是在高斯模糊原理的基础上,将局部高斯模糊的图像与原始图像叠加,就实现了最终的局部辉光效果。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>如何用后期处理通道实现辉光效果?</title>
        <style>
            canvas {
                border: 1px dashed salmon;
            }
        </style>
    </head>
    <body>
        <canvas width="512" height="512"></canvas>
        <script src="./common/lib/gl-renderer.js"></script>
        <script>
            const vertex = `
                attribute vec2 a_vertexPosition;
                attribute vec2 uv;
                varying vec2 vUv;
                void main() {
                    gl_PointSize = 1.0;
                    vUv = uv;
                    gl_Position = vec4(a_vertexPosition, 1, 1);
                }
            `;
            const fragment = `
                #ifdef GL_ES
                precision highp float;
                #endif
                float line_distance(in vec2 st, in vec2 a, in vec2 b) {
                    vec3 ab = vec3(b - a, 0);
                    vec3 p = vec3(st - a, 0);
                    float l = length(ab);
                    return cross(p, normalize(ab)).z;
                }
                float seg_distance(in vec2 st, in vec2 a, in vec2 b) {
                    vec3 ab = vec3(b - a, 0);
                    vec3 p = vec3(st - a, 0);
                    float l = length(ab);
                    float d = abs(cross(p, normalize(ab)).z);
                    float proj = dot(p, ab) / l;
                    if(proj >= 0.0 && proj <= l) return d;
                    return min(distance(st, a), distance(st, b));
                }
                float triangle_distance(in vec2 st, in vec2 a, in vec2 b, in vec2 c) {
                    float d1 = line_distance(st, a, b);
                    float d2 = line_distance(st, b, c);
                    float d3 = line_distance(st, c, a);
                    if(d1 >= 0.0 && d2 >= 0.0 && d3 >= 0.0 || d1 <= 0.0 && d2 <= 0.0 && d3 <= 0.0) {
                        return -min(abs(d1), min(abs(d2), abs(d3))); // 内部距离为负
                    }
                    return min(seg_distance(st, a, b), min(seg_distance(st, b, c), seg_distance(st, c, a))); // 外部为正
                }
                float random (vec2 st) {
                    return fract(sin(dot(st.xy, vec2(12.9898,78.233)))*43758.5453123);
                }
                vec3 hsb2rgb(vec3 c){
                    vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0), 6.0)-3.0)-1.0, 0.0, 1.0);
                    rgb = rgb * rgb * (3.0 - 2.0 * rgb);
                    return c.z * mix(vec3(1.0), rgb, c.y);
                }
                varying vec2 vUv;
                void main() {
                    vec2 st = vUv;
                    st *= 10.0;
                    vec2 i_st = floor(st);
                    vec2 f_st = 2.0 * fract(st) - vec2(1);
                    float r = random(i_st);
                    float sign = 2.0 * step(0.5, r) - 1.0;
                    float d = triangle_distance(f_st, vec2(-1), vec2(1), sign * vec2(1, -1));
                    gl_FragColor.rgb = (smoothstep(-0.85, -0.8, d) - smoothstep(0.0, 0.05, d)) * hsb2rgb(vec3(r + 1.2, 0.5, r));
                    gl_FragColor.a = 1.0;
                }
            `;
            /**
             * 通过blurFragment,能将第一次渲染后生成的纹理 tMap 内容给显示出来。
             * 给 blurFragment 加了一个关于亮度的滤镜,将颜色亮度大于 filter 值的三角形过滤出来添加高斯模糊。
             * */ 
            const blurFragment = `
                #ifdef GL_ES
                precision highp float;
                #endif
                varying vec2 vUv;
                uniform sampler2D tMap;
                uniform int axis;
                uniform float filter;
                void main() {
                    vec4 color = texture2D(tMap, vUv);
                    float brightness = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
                    brightness = step(filter, brightness);
                    // 高斯矩阵的权重值
                    float weight[5];
                    weight[0] = 0.227027;
                    weight[1] = 0.1945946;
                    weight[2] = 0.1216216;
                    weight[3] = 0.054054;
                    weight[4] = 0.016216;
                    // 每一个相邻像素的坐标间隔,这里的512可以用实际的Canvas像素宽代替
                    float tex_offset = 1.0 / 512.0;
                    vec3 result = color.rgb;
                    result *= weight[0];
                    for(int i = 1; i < 5; ++i) {
                        float f = float(i);
                        if(axis == 0) {
                            // x轴的高斯模糊
                            result += texture2D(tMap, vUv + vec2(tex_offset * f, 0.0)).rgb * weight[i];
                            result += texture2D(tMap, vUv - vec2(tex_offset * f, 0.0)).rgb * weight[i];
                        } else {
                            // y轴的高斯模糊
                            result += texture2D(tMap, vUv + vec2(0.0, tex_offset * f)).rgb * weight[i];
                            result += texture2D(tMap, vUv - vec2(0.0, tex_offset * f)).rgb * weight[i];
                        }
                    }
                    gl_FragColor.rgb = brightness * result.rgb;
                    gl_FragColor.a = color.a;
                }
            `;
            // 再增加一个 bloomFragment 着色器,用来做最后的效果混合。 
            const bloomFragment = `
                #ifdef GL_ES
                precision highp float;
                #endif
                uniform sampler2D tMap;
                uniform sampler2D tSource;
                varying vec2 vUv;
                void main() {
                    vec3 color = texture2D(tSource, vUv).rgb;
                    vec3 bloomColor = texture2D(tMap, vUv).rgb;
                    color += bloomColor;
                    // Tone Mapping(色调映射):将对比度过大的图像色调映射到合理的范围内
                    float exposure = 2.0;
                    float gamma = 1.3;
                    vec3 result = vec3(1.0) - exp(-color * exposure);
                    // also gamma correct while we're at it
                    if(length(bloomColor) > 0.0) {
                        result = pow(result, vec3(1.0 / gamma));
                    }
                    gl_FragColor.rgb = result;
                    gl_FragColor.a = 1.0;
                }
            `;
            const canvas = document.querySelector("canvas");
            const renderer = new GlRenderer(canvas);
            const program = renderer.compileSync(fragment, vertex);
            renderer.useProgram(program);
            renderer.setMeshData([
                {
                    positions: [
                        [-1, -1],
                        [-1, 1],
                        [1, 1],
                        [1, -1],
                    ],
                    attributes: {
                        uv: [
                            [0, 0],
                            [0, 1],
                            [1, 1],
                            [1, 0],
                        ],
                    },
                    cells: [
                        [0, 1, 2],
                        [2, 0, 3],
                    ],
                },
            ]);
            // 高斯模糊有两个方向,下面分别对 x 轴和 y 轴执行 2 次渲染为例
            const blurProgram = renderer.compileSync(blurFragment, vertex);
            const bloomProgram = renderer.compileSync(bloomFragment, vertex);
            // 创建三个FBO(帧缓冲对象),fbo1和fbo2交替使用
            const fbo0 = renderer.createFBO();
            const fbo1 = renderer.createFBO();
            const fbo2 = renderer.createFBO();
            // 第一次,渲染原始图形
            renderer.bindFBO(fbo0);
            renderer.render();
            // 第二次,对x轴高斯模糊
            renderer.useProgram(blurProgram);
            renderer.setMeshData(program.meshData);
            renderer.bindFBO(fbo2);
            renderer.uniforms.tMap = fbo0.texture;
            renderer.uniforms.axis = 0;
            renderer.uniforms.filter = 0.7;
            renderer.render();
            // 第三次,对y轴高斯模糊
            renderer.useProgram(blurProgram);
            renderer.bindFBO(fbo1);
            renderer.uniforms.tMap = fbo2.texture;
            renderer.uniforms.axis = 1;
            renderer.uniforms.filter = 0;
            renderer.render();
            // 第四次,对x轴高斯模糊
            renderer.useProgram(blurProgram);
            renderer.bindFBO(fbo2);
            renderer.uniforms.tMap = fbo1.texture;
            renderer.uniforms.axis = 0;
            renderer.uniforms.filter = 0;
            renderer.render();
            // 第五次,对y轴高斯模糊
            renderer.useProgram(blurProgram);
            renderer.bindFBO(fbo1);
            renderer.uniforms.tMap = fbo2.texture;
            renderer.uniforms.axis = 1;
            renderer.uniforms.filter = 0;
            renderer.render();
            // 第六次,叠加辉光
            renderer.useProgram(bloomProgram);
            renderer.setMeshData(program.meshData);
            renderer.bindFBO(null);
            renderer.uniforms.tSource = fbo0.texture;
            renderer.uniforms.tMap = fbo1.texture;
            renderer.uniforms.axis = 1;
            renderer.uniforms.filter = 0;
            renderer.render();
        </script>
    </body>
</html>


9b8d103b94ee4804b88e41359ba98b1a.png



如何用后期处理通道实现烟雾效果?

先构建一个烟雾的扩散模型:每个格子到下一时刻的颜色变化量,等于它周围四个格子的颜色值之和减去它自身颜色值的 4 倍,乘以扩散系数。


9034a403dadb416d94dc560b15a2d581.png


假设扩散系数是常量 0.1,第一轮每一格的颜色值如下:

c218676828594d79aca24898c81b4346.png



按照这个规则不断迭代下去,修改扩散公式的权重以及加入噪声就能得到一个简单的烟雾扩散效果。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>17.如何用后期处理通道实现烟雾效果?</title>
        <style>
            canvas {
                border: 1px dashed salmon;
            }
        </style>
    </head>
    <body>
        <canvas width="512" height="512"></canvas>
        <script src="./common/lib/gl-renderer.js"></script>
        <script>
            const vertex = `
                attribute vec2 a_vertexPosition;
                attribute vec2 uv;
                varying vec2 vUv;
                void main() {
                    gl_PointSize = 1.0;
                    vUv = uv;
                    gl_Position = vec4(a_vertexPosition, 1, 1);
                }
            `;
            const fragment = `
                #ifdef GL_ES
                precision highp float;
                #endif
                varying vec2 vUv;
                uniform sampler2D tMap;
                uniform float uTime;
                vec2 random2(vec2 st){
                    st = vec2( dot(st,vec2(127.1,311.7)),
                            dot(st,vec2(269.5,183.3)) );
                    return -1.0 + 2.0 * fract(sin(st) * 43758.5453123);
                }
                // Gradient Noise by Inigo Quilez - iq/2013
                // https://www.shadertoy.com/view/XdXGW8
                float noise(vec2 st) {
                    vec2 i = floor(st);
                    vec2 f = fract(st);
                    vec2 u = f * f * (3.0 - 2.0 * f);
                    return mix( mix( dot( random2(i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
                        dot( random2(i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
                        mix( dot( random2(i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
                        dot( random2(i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y
                    );
                }
                void main() {
                    vec3 smoke = vec3(0);
                    if(uTime <= 0.0) {
                        vec2 st = vUv - vec2(0.5);
                        float d = length(st);
                        // smoke = vec3(step(d, 0.05));
                        smoke = vec3(1.0 - smoothstep(0.05, 0.055, d));
                    }
                    vec2 st = vUv;
                    float offset = 1.0 / 256.0;
                    vec3 diffuse = texture2D(tMap, st).rgb;
                    vec4 left = texture2D(tMap, st + vec2(-offset, 0.0));
                    vec4 right = texture2D(tMap, st + vec2(offset, 0.0));
                    vec4 up = texture2D(tMap, st + vec2(0.0, -offset));
                    vec4 down = texture2D(tMap, st + vec2(0.0, offset));
                    float rand = noise(st + 5.0 * uTime);
                    float diff = 8.0 * 0.016 * (
                        (1.0 + rand) * left.r + 
                        (1.0 - rand) * right.r + 
                        down.r + 
                        2.0 * up.r - 
                        5.0 * diffuse.r
                    );
                    gl_FragColor.rgb = (diffuse + diff) + smoke;
                    gl_FragColor.a = 1.0;
                }
            `;
            const canvas = document.querySelector("canvas");
            const renderer = new GlRenderer(canvas);
            const program = renderer.compileSync(fragment, vertex);
            renderer.useProgram(program);
            renderer.setMeshData([
                {
                    positions: [
                        [-1, -1],
                        [-1, 1],
                        [1, 1],
                        [1, -1],
                    ],
                    attributes: {
                        uv: [
                            [0, 0],
                            [0, 1],
                            [1, 1],
                            [1, 0],
                        ],
                    },
                    cells: [
                        [0, 1, 2],
                        [2, 0, 3],
                    ],
                },
            ]);
            // 创建两个fbo对象
            const fbo = {
                readFBO: renderer.createFBO(),
                writeFBO: renderer.createFBO(),
                get texture() {
                    return this.readFBO.texture;
                },
                swap() {
                    const tmp = this.writeFBO;
                    this.writeFBO = this.readFBO;
                    this.readFBO = tmp;
                },
            };
            function update(t) {
                renderer.bindFBO(null);
                renderer.uniforms.uTime = t / 1000;
                renderer.uniforms.tMap = fbo.texture;
                renderer.render();
                renderer.bindFBO(fbo.writeFBO);
                renderer.uniforms.tMap = fbo.texture;
                fbo.swap();
                renderer.render();
                requestAnimationFrame(update);
            }
            update(0);
        </script>
    </body>
</html>

cf826b2d85124bff8edf59c3cabb38b0.gif



目录
相关文章
|
9月前
|
编解码 人工智能 测试技术
无需训练,这个新方法实现了生成图像尺寸、分辨率自由
【4月更文挑战第25天】研究人员提出FouriScale方法,解决了扩散模型在生成高分辨率图像时的结构失真问题。通过膨胀卷积和低通滤波,该方法实现不同分辨率下图像的结构和尺度一致性,无需重新训练模型。实验显示FouriScale在保持图像真实性和完整性的同时,能生成任意尺寸的高质量图像,尤其在处理高宽比图像时表现出色。尽管在极高分辨率生成上仍有局限,但为超高清图像合成技术提供了新思路。[链接: https://arxiv.org/abs/2403.12963]
108 5
|
数据挖掘 计算机视觉 Python
Python数据分析中图像处理的实用技术点:图像加载与保存、图像转换与增强、特征提取与描述
Python数据分析中图像处理的实用技术点:图像加载与保存、图像转换与增强、特征提取与描述
106 1
Python数据分析中图像处理的实用技术点:图像加载与保存、图像转换与增强、特征提取与描述
|
1月前
|
人工智能 数据库
Poetry2Image:专为中文古诗词设计的图像生成校正框架,增强了诗歌内容与模型生成图像之间的一致性
Poetry2Image 是一个专为中文古诗词图像生成设计的迭代校正框架,通过自动化反馈和校正循环,提升诗歌与图像之间的一致性,有效捕捉诗歌的语义和艺术精髓。
66 11
Poetry2Image:专为中文古诗词设计的图像生成校正框架,增强了诗歌内容与模型生成图像之间的一致性
|
2月前
|
编解码 人工智能
FreeScale:无需微调即可提升模型的图像生成能力,生成 8K 分辨率的高质量图像
FreeScale是一个无需微调的推理框架,旨在提升扩散模型生成高分辨率图像和视频的能力。该框架通过处理和融合不同尺度的信息,首次实现了8K分辨率图像的生成,显著提高了生成内容的质量和保真度,同时减少了推理时间。
93 20
FreeScale:无需微调即可提升模型的图像生成能力,生成 8K 分辨率的高质量图像
|
机器学习/深度学习
深度学习数据增强方法-内含(亮度增强,对比度增强,旋转图图像,翻转图像,仿射变化扩充图像,错切变化扩充图像,HSV数据增强)七种方式进行增强-每种扩充一张实现7倍扩)+ 图像缩放代码-批量
深度学习数据增强方法-内含(亮度增强,对比度增强,旋转图图像,翻转图像,仿射变化扩充图像,错切变化扩充图像,HSV数据增强)七种方式进行增强-每种扩充一张实现7倍扩)+ 图像缩放代码-批量
|
2月前
|
机器学习/深度学习 人工智能 编解码
OminiControl:AI图像生成框架,实现图像主题控制和空间精确控制
OminiControl 是一个高度通用且参数高效的 AI 图像生成框架,专为扩散变换器模型设计,能够实现图像主题控制和空间精确控制。该框架通过引入极少量的额外参数(0.1%),支持主题驱动控制和空间对齐控制,适用于多种图像生成任务。
94 10
OminiControl:AI图像生成框架,实现图像主题控制和空间精确控制
|
2月前
|
机器学习/深度学习 测试技术 定位技术
新扩散模型OmniGen一统图像生成,架构还高度简化、易用
近期,一篇题为“OmniGen: Unified Image Generation”的论文介绍了一种新型扩散模型OmniGen,旨在统一图像生成任务。OmniGen架构简洁,无需额外模块即可处理多种任务,如文本到图像生成、图像编辑等。该模型通过修正流优化,展现出与现有模型相当或更优的性能,尤其在图像编辑和视觉条件生成方面表现突出。OmniGen仅含3.8亿参数,却能有效处理复杂任务,简化工作流程。尽管如此,OmniGen仍存在对文本提示敏感、文本渲染能力有限等问题,未来研究将继续优化其架构与功能。
86 16
|
8月前
|
编解码 算法 计算机视觉
YOLOv8数据增强预处理方式详解:包括数据增强的作用,数据增强方式与方法
YOLOv8数据增强预处理方式详解:包括数据增强的作用,数据增强方式与方法
|
机器学习/深度学习 传感器 自动驾驶
视觉BEV基本原理和方案解析
视觉BEV在高德高精地图地面要素识别、车道线拓扑构建、车端融合定位等业务场景中都扮演了重要角色。
|
9月前
|
数据可视化 开发工具 计算机视觉
LabVIEW视觉采集软件(VAS)、视觉生成器(VB)和视觉开发模块(VDM)之间有什么不同
LabVIEW视觉采集软件(VAS)、视觉生成器(VB)和视觉开发模块(VDM)之间有什么不同
84 1

热门文章

最新文章