前言
本文是關于OpenGL ES的系統性學習過程,記錄了自己在學習OpenGL ES時的收獲。
這篇文章的目標是學習OpenGL ES 2.0中的圖像膨脹、腐蝕、模糊。
環境是Xcode8.1+OpenGL ES 2.0
目前代碼已經放到github上面,OpenGLES06-圖像膨脹腐蝕模糊
歡迎關注我的 OpenGL ES入門專題
圖像膨脹
膨脹 是將與物體接觸的所有背景點合并到該物體中,使邊界向外部擴張的過程。可以用來填補物體中的空洞。膨脹的簡單理解就是亮的像素點向著周圍擴散的過程。在OpenGL ES中實現圖像的膨脹也是利用這一原理。在對某個像素點取值的時候,使用周圍最亮的顏色代替本來的顏色來達到膨脹的效果。以下是OpenGL ES著色器代碼的實現:
// 頂點著色器
attribute vec3 position;
attribute vec2 texcoord;
varying vec2 vTexcoord;
void main()
{
gl_Position = vec4(position, 1.0);
vTexcoord = texcoord;
}
// 片元著色器
precision mediump float;
uniform sampler2D image;
varying vec2 vTexcoord;
void main()
{
float block = 100.0;
float delta = 1.0/block;
vec4 maxColor = vec4(-1.0);
for (int i = -1; i <= 1 ; i++) {
for (int j = -1; j <= 1; j++) {
float x = vTexcoord.x + float(i) * delta;
float y = vTexcoord.y + float(i) * delta;
maxColor = max(texture2D(image, vec2(x, y)), maxColor);
}
}
gl_FragColor = maxColor;
}
圖像腐蝕
腐蝕 是一種消除邊界點,使邊界向內部收縮的過程。可以用來消除小且無意義的物體。腐蝕的簡單理解就是暗的像素腐蝕著亮的像素。在OpenGL ES中實現圖像的腐蝕也是利用這一原理。在對某個像素點取值的時候,使用周圍最暗的顏色代替本來的顏色來達到腐蝕周圍的效果。以下是OpenGL ES著色器代碼的實現:
// 頂點著色器
attribute vec3 position;
attribute vec2 texcoord;
varying vec2 vTexcoord;
void main()
{
gl_Position = vec4(position, 1.0);
vTexcoord = texcoord;
}
// 片元著色器
precision mediump float;
uniform sampler2D image;
varying vec2 vTexcoord;
void main()
{
float block = 200.0;
float delta = 1.0/block;
vec4 maxColor = vec4(1.0);
for (int i = -1; i <= 1 ; i++) {
for (int j = -1; j <= 1; j++) {
float x = vTexcoord.x + float(i) * delta;
float y = vTexcoord.y + float(i) * delta;
maxColor = min(texture2D(image, vec2(x, y)), maxColor);
}
}
gl_FragColor = maxColor;
}
![Uploading chart-1_391495.png . . .]
圖像模糊
1、普通模糊
模糊 可以理解成每一個像素都取周邊像素的平均值。中間像素點取周圍像素點的平均值。在數值上,這是一種平滑化。在圖形上,就相當于產生模糊效果,則中間點失去細節。在OpenGL ES中卷積是一種很常見的數字圖像處理操作,可以用來過濾一副圖像,實現過濾的方法是計算原圖像與卷積內核之間的積,所謂卷積內核是指一個MxN的矩陣,N一般為奇數,進行卷積計算時將卷積內核對待處理圖像中的每個像素都應用一次。
著色器實現
attribute vec3 position;
attribute vec2 texcoord;
varying vec2 vTexcoord;
void main()
{
gl_Position = vec4(position, 1.0);
vTexcoord = texcoord;
}
precision mediump float;
uniform sampler2D image;
varying vec2 vTexcoord;
void main()
{
float block = 150.0;
float delta = 1.0/block;
vec4 color = vec4(0.0);
float factor[9];
factor[0] = 1.0; factor[1] = 1.0; factor[2] = 1.0;
factor[3] = 1.0; factor[4] = 1.0; factor[5] = 1.0;
factor[6] = 1.0; factor[7] = 1.0; factor[8] = 1.0;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
float x = max(0.0, vTexcoord.x + float(i) * delta);
float y = max(0.0, vTexcoord.y + float(i) * delta);
color += texture2D(image, vec2(x, y)) * factor[(i+1)*3+(j+1)];
}
}
color = color/9.0;
gl_FragColor = vec4(vec3(color), 1.0);
}
2、高斯模糊
在使用簡單平均方案的時候,并不是特別合理,因為圖像都是連續的,越靠近的點關系越密切,越遠離的點關系越疏遠。因此,需要安排合適的權重去取周圍的像素,距離越近的點權重越大,距離越遠的點權重越小。在圖形上,正態分布是一種鐘形曲線,越接近中心,取值越大,越遠離中心,取值越小。計算平均值的時候,我們只需要將中心點作為原點,其他點按照其在正態曲線上的位置,分配權重,就可以得到一個加權平均值。正態分布是一維的,圖像都是二維的,所以我們需要二維的正態分布。正態分布的密度函數叫做高斯函數。高斯模糊就是將二維正態分布用于圖像處理。
當中心點的坐標是遠點,假定σ=1.5,則模糊半徑為1的權重矩陣如下:
著色器實現
attribute vec3 position;
attribute vec2 texcoord;
varying vec2 vTexcoord;
void main()
{
gl_Position = vec4(position, 1.0);
vTexcoord = texcoord;
}
precision mediump float;
uniform sampler2D image;
varying vec2 vTexcoord;
void main()
{
float block = 150.0;
float delta = 1.0/block;
vec4 color = vec4(0.0);
float factor[9];
factor[0] = 0.0947416; factor[1] = 0.118318; factor[2] = 0.0947416;
factor[3] = 0.118318; factor[4] = 0.147761; factor[5] = 0.118318;
factor[6] = 0.0947416; factor[7] = 0.118318; factor[8] = 0.0947416;
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
float x = max(0.0, vTexcoord.x + float(i) * delta);
float y = max(0.0, vTexcoord.y + float(i) * delta);
color += texture2D(image, vec2(x, y)) * factor[(i+1)*3+(j+1)];
}
}
gl_FragColor = vec4(vec3(color), 1.0);
}