OpenGL ES 图像基本处理:腐蚀、膨胀、边缘检测
前文我们详细讲了图像锐化的基本原理,本文再介绍一下图像基本处理之腐蚀、膨胀和边缘检测,它们在图像处理和计算机视觉领域有着广泛的应用。
图像腐蚀(Image Erosion):用于缩小或消除图像中物体的边界。主要用于去除图像中的小细节、噪声或不规则物体。
实现图像腐蚀的片段着色器代码,基本原理就是寻找附近的最小 color 作为输出:
precision highp float;
varying highp vec2 vTextureCoord;
uniform lowp sampler2D sTexture;
uniform highp vec2 inputSize;
void main() {
vec2 uv = vTextureCoord;
float step = 1.0;
vec2 uvOffsets[25];
float dx = step / inputSize.x;
float dy = step / inputSize.y;
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
uvOffsets[((i*5)+j)].x = (-2.0 * dx) + (float(i) * dx);
uvOffsets[((i*5)+j)].y = (-2.0 * dy) + (float(j) * dy);
}
}
vec4 result = vec4(1.0);
for (int i = 0; i < 25; i++)
{
vec4 col = texture2D(sTexture, uv + uvOffsets[i]);
result = min(result, col);
}
gl_FragColor = result;
}
图像腐蚀效果对比:
图像膨胀(Image Dilation):用于增大或突出图像中物体的边界。主要用于连接图像中的物体,填充小孔或缝隙,以及强调物体的边缘。
实现图像膨胀的片段着色器代码,基本原理就是寻找附近的最大 color 作为输出:
precision highp float;
varying highp vec2 vTextureCoord;
uniform lowp sampler2D sTexture;
uniform highp vec2 inputSize;
void main() {
vec2 uv = vTextureCoord;
float step = 1.0;
vec2 uvOffsets[25];
float dx = step / inputSize.x;
float dy = step / inputSize.y;
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
uvOffsets[((i*5)+j)].x = (-2.0 * dx) + (float(i) * dx);
uvOffsets[((i*5)+j)].y = (-2.0 * dy) + (float(j) * dy);
}
}
vec4 result = vec4(0.0);
for (int i = 0; i < 25; i++)
{
vec4 col = texture2D(sTexture, uv + uvOffsets[i]);
result = max(result, col);
}
gl_FragColor = result;
}
图像膨胀效果对比:
边缘检测(Edge Detection):用于识别图像中物体之间的边界。常用于目标检测、图像分割和计算机视觉任务。常见的边缘检测算法包括Sobel、Prewitt、Canny等。
实现图像边缘检测的片段着色器代码,代码基本上跟上节降到的锐化的实现方式一样,都是使用一个卷积核(高通滤波):
precision highp float;
varying highp vec2 vTextureCoord;
uniform lowp sampler2D sTexture;
uniform highp vec2 inputSize;
void main() {
vec2 uv = vTextureCoord;
float step = 5.0;
vec2 uvOffsets[9];
float dx = step / inputSize.x;
float dy = step / inputSize.y;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
uvOffsets[((i*5)+j)].x = (-1.0 * dx) + (float(i) * dx);
uvOffsets[((i*5)+j)].y = (-1.0 * dy) + (float(j) * dy);
}
}
vec4 sampleCols[9];
for (int i = 0; i < 9; i++)
{
// 采样邻域的网格
sampleCols[i] = texture2D(sTexture, uv + uvOffsets[i]);
}
// 锐化卷积核 3x3
// -1 -1 -1
// -1 8 -1
// -1 -1 -1
vec4 result = 8.0 * sampleCols[4];
for (int i = 0; i < 9; i++)
{
if (i != 4)
result -= sampleCols[i];
}
gl_FragColor = result;
}
边缘检测效果对比:
参考链接:
https://blog.csdn.net/weixin_44225182/article/details/101310131
https://blog.csdn.net/panda1234lee/article/details/52320832
-- END --
进技术交流群,扫码添加我的微信:Byte-Flow
获取相关资料和源码
推荐:
Android FFmpeg 实现带滤镜的微信小视频录制功能
全网最全的 Android 音视频和 OpenGL ES 干货,都在这了
面试官:如何利用 Shader 实现 RGBA 到 NV21 图像格式转换?
项目疑难问题解答、大厂内部推荐、面试指导、简历指导、代码指导、offer 选择建议、学习路线规划,可以点击找我一对一解答。