OpenGL ES入門06-圖像膨脹、腐蝕、模糊

前言

本文是關于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、高斯模糊
在使用簡單平均方案的時候,并不是特別合理,因為圖像都是連續的,越靠近的點關系越密切,越遠離的點關系越疏遠。因此,需要安排合適的權重去取周圍的像素,距離越近的點權重越大,距離越遠的點權重越小。在圖形上,正態分布是一種鐘形曲線,越接近中心,取值越大,越遠離中心,取值越小。計算平均值的時候,我們只需要將中心點作為原點,其他點按照其在正態曲線上的位置,分配權重,就可以得到一個加權平均值。正態分布是一維的,圖像都是二維的,所以我們需要二維的正態分布。正態分布的密度函數叫做高斯函數。高斯模糊就是將二維正態分布用于圖像處理。

一 ![Uploading chart-2_658231.png . . .] 維的正態分布
二維的正態分布
一維高斯函數
二維高斯函數

當中心點的坐標是遠點,假定σ=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);
}
高斯模糊圖
原圖

參考鏈接

http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容