Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

图像处理的滤镜算法 #50

Open
huruji opened this issue Sep 14, 2018 · 0 comments
Open

图像处理的滤镜算法 #50

huruji opened this issue Sep 14, 2018 · 0 comments

Comments

@huruji
Copy link
Owner

huruji commented Sep 14, 2018

灰度滤镜

将颜色的RGB设置为相同的值即可使得图片为灰色,一般处理方法有:
1、取三种颜色的平均值
2、取三种颜色的最大值(最小值)
3、加权平均值:0.3R + 0.59G + 0.11*B

for(var i = 0; i < data.length; i+=4) {
     var grey = (data[i] + data[i+1] + data[i+2]) / 3;
     data[i] = data[i+1] = data[i+2] = grey;
}

image.png

黑白滤镜

顾名思义,就是图片的颜色只有黑色和白色,可以计算rgb的平均值arg,arg>=100,r=g=b=255,否则均为0

for(var i = 0; i < data.length; i += 4) {
     var avg = (data[i] + data[i+1] + data[i+2]) / 3;
     data[i] = data[i+1] = data[i+2] = avg >= 100 ? 255 : 0;
}

image.png

反向滤镜

就是RGB三种颜色分别取255的差值。

for(var i = 0; i < data.length; i+= 4) {
      data[i] = 255 - data[i];
      data[i + 1] = 255 - data[i + 1];
      data[i + 2] = 255 - data[i + 2];
}

image.png

去色滤镜

rgb三种颜色取三种颜色的最值的平均值。

for(var i = 0; i < data.length; i++) {
   var avg = Math.floor((Math.min(data[i], data[i+1], data[i+2]) + Math.max(data[i], data[i+1], data[i+2])) / 2 );
   data[i] = data[i+1] = data[i+2] = avg;
}

单色滤镜

就是只保留一种颜色,其他颜色设为0

for(var i = 0; i < canvas.height * canvas.width; i++) {
    data[i*4 + 2] = 0;
    data[i*4 + 1] = 0;
}

高斯模糊滤镜

高斯模糊的原理就是根据正态分布使得每个像素点周围的像素点的权重不一致,将各个权重(各个权重值和为1)与对应的色值相乘,所得结果求和为中心像素点新的色值。我们需要了解的高斯模糊的公式:

function gaussBlur(imgData, radius, sigma) {
    var pixes = imgData.data,
        height = imgData.height,
        width = imgData.width,
        radius = radius || 5;
        sigma = sigma || radius / 3;
    
    var gaussEdge = radius * 2 + 1;

    var gaussMatrix = [],
        gaussSum = 0,
        a = 1 / (2 * sigma * sigma * Math.PI),
        b = -a * Math.PI;
    
    for(var i = -radius; i <= radius; i++) {
        for(var j = -radius; j <= radius; j++) {
            var gxy = a * Math.exp((i * i + j * j) * b);
            gaussMatrix.push(gxy);
            gaussSum += gxy;
        }
    }
    var gaussNum = (radius + 1) * (radius + 1);
    for(var i = 0; i < gaussNum; i++) {
        gaussMatrix[i] /= gaussSum;
    }

    for(var x = 0; x < width; x++) {
        for(var y = 0; y < height; y++) {
            var r = g = b = 0;
            for(var i = -radius; i<=radius; i++) {
                var m = handleEdge(i, x, width);
                for(var j = -radius; j <= radius; j++) {
                    var mm = handleEdge(j, y, height);
                    var currentPixId = (mm * width + m) * 4;
                    var jj = j + radius;
                    var ii = i + radius;
                    r += pixes[currentPixId] * gaussMatrix[jj * gaussEdge + ii];
                    g += pixes[currentPixId + 1] * gaussMatrix[jj * gaussEdge + ii];
                    b += pixes[currentPixId + 2] * gaussMatrix[jj * gaussEdge + ii];
                }
            }
            var pixId = (y * width + x) * 4;

            pixes[pixId] = ~~r;
            pixes[pixId + 1] = ~~g;
            pixes[pixId + 2] = ~~b;
        }
    }
    imgData.data = pixes;
    return imgData;
}

function handleEdge(i, x, w) {
    var m = x + i;
    if(m < 0) {
        m = -m;
    } else if(m >= w) {
        m = w + i -x;
    }
    return m;
}

怀旧滤镜

怀旧滤镜公式

for(var i = 0; i < imgData.height * imgData.width; i++) {
    var r = imgData.data[i*4],
        g = imgData.data[i*4+1],
        b = imgData.data[i*4+2];

    var newR = (0.393 * r + 0.769 * g + 0.189 * b);
    var newG = (0.349 * r + 0.686 * g + 0.168 * b);
    var newB = (0.272 * r + 0.534 * g + 0.131 * b);
    var rgbArr = [newR, newG, newB].map((e) => {
        return e < 0 ? 0 : e > 255 ? 255 : e;
    });
    [imgData.data[i*4], imgData.data[i*4+1], imgData.data[i*4+2]] = rgbArr;
}

熔铸滤镜

公式:
r = r128/(g+b +1);
g = g
128/(r+b +1);
b = b*128/(g+r +1);

for(var i = 0; i < imgData.height * imgData.width; i++) {
    var r = imgData.data[i*4],
        g = imgData.data[i*4+1],
        b = imgData.data[i*4+2];

    var newR = r * 128 / (g + b + 1);
    var newG = g * 128 / (r + b + 1);
    var newB = b * 128 / (g + r + 1);
    var rgbArr = [newR, newG, newB].map((e) => {
        return e < 0 ? 0 : e > 255 ? 255 : e;
    });
    [imgData.data[i*4], imgData.data[i*4+1], imgData.data[i*4+2]] = rgbArr;
}

image.png

冰冻滤镜

公式:
r = (r-g-b)*3/2;
g = (g-r-b)*3/2;
b = (b-g-r)*3/2;

for(var i = 0; i < imgData.height * imgData.width; i++) {
    var r = imgData.data[i*4],
        g = imgData.data[i*4+1],
        b = imgData.data[i*4+2];

    var newR = (r - g -b) * 3 /2;
    var newG = (g - r -b) * 3 /2;
    var newB = (b - g -r) * 3 /2;
    var rgbArr = [newR, newG, newB].map((e) => {
        return e < 0 ? 0 : e > 255 ? 255 : e;
    });
    [imgData.data[i*4], imgData.data[i*4+1], imgData.data[i*4+2]] = rgbArr;
}

连环画滤镜

公式:
R = |g – b + g + r| * r / 256

G = |b – g + b + r| * r / 256;

B = |b – g + b + r| * g / 256;

for(var i = 0; i < imgData.height * imgData.width; i++) {
    var r = imgData.data[i*4],
        g = imgData.data[i*4+1],
        b = imgData.data[i*4+2];

    var newR = Math.abs(g - b + g + r) * r / 256;
    var newG = Math.abs(b -g + b + r) * r / 256;
    var newB =  Math.abs(b -g + b + r) * g / 256;
    var rgbArr = [newR, newG, newB];
    [imgData.data[i*4], imgData.data[i*4+1], imgData.data[i*4+2]] = rgbArr;
}

image.png

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant