图像卷积Javascript图像处理——图像金字塔

本篇文章是一篇关于图像卷积的帖子

    

言前

    上一篇文章,我们讲解了边缘梯度盘算函数,这篇文章我们来了解图像金字塔。

 

    

图像金字塔?

    

    图像金字塔被普遍用于盘算机视觉用应中。

    图像金字塔是一个图像合集,合集中有所的图像都源于同一个原始图像,而且是通过对原始图像续连降样采取得的。

    ——《学习OpenCV》

    

    罕见的图像金字塔有面下两种:

    

  • 高斯金字塔(Gaussian pyramid): 用来向下样采
  • 拉普拉斯金字塔(Laplacian pyramid): 用来从金字塔低层图像重建下层未样采图像

 

    

高斯金字塔

    图像和卷积

    相似金字塔一样,高斯金字塔从底层原始图渐逐向下样采,越来越小。

    那么如何取得下一层图像呢?

    首先,和高斯内核卷积:

    图像和卷积

    然后,将有所偶数行列删掉。

    可见,这样下一级图像约为上一级的1/4。

    那么向上变换如何变换呢?

    首先先将图片行列扩大为本来的两倍,然后将添加的行列用0充填。

    最后用刚刚的高斯内核乘以4后卷积。

 

    

高斯金字塔实现

var pyrDown = function(__src, __dst){
    __src || error(arguments.callee, IS_UNDEFINED_OR_NULL/* {line} */);
    if(__src.type && __src.type == "CV_RGBA"){
        var width = __src.col,
            height = __src.row,
            dWidth = ((width & 1) + width) / 2,
            dHeight = ((height & 1) + height) / 2,
            sData = __src.data,
            dst = __dst || new Mat(dHeight, dWidth, CV_RGBA),
            dstData = dst.data;
        
        var withBorderMat = copyMakeBorder(__src, 2, 2, 0, 0),
            mData = withBorderMat.data,
            mWidth = withBorderMat.col;
        
        var newValue, nowX, offsetY, offsetI, dOffsetI, i, j;
        
        var kernel = [1,  4,  6,  4, 1,
                      4, 16, 24, 16, 4,
                      6, 24, 36, 24, 6,
                      4, 16, 24, 16, 4,
                      1,  4,  6,  4, 1
                     ];
        
        for(i = dHeight; i--;){
            dOffsetI = i * dWidth;
            for(j = dWidth; j--;){
                for(c = 3; c--;){
                    newValue = 0;
                    for(y = 5; y--;){
                        offsetY = (y + i * 2) * mWidth * 4;
                        for(x = 5; x--;){
                            nowX = (x + j * 2) * 4 + c;
                            newValue += (mData[offsetY + nowX] * kernel[y * 5 + x]);
                        }
                    }
                    dstData[(j + dOffsetI) * 4 + c] = newValue / 256;
                }
                dstData[(j + dOffsetI) * 4 + 3] = mData[offsetY + 2 * mWidth * 4 + (j * 2 + 2) * 4 + 3];
            }
        }
        
    }else{
        error(arguments.callee, UNSPPORT_DATA_TYPE/* {line} */);
    }
    
    return dst;
};
    每日一道理
天又快黑了,这座忙碌的城市又将入睡,让这劳累的“身躯”暂别白日的辛勤,让它入睡,陪伴着城市中的人们进入梦乡。当空的弯月正深情地注视着这座城市与城市中的人们,看着家家户户的灯渐渐熄灭,它在床头悄悄奏响“明月曲”……

    dWidth = ((width & 1) + width) / 2,

    dHeight = ((height & 1) + height) / 2

    这面里a & 1等同于a % 2,即求除以2的余数。

    我们实现时候没有按照面上的骤步,因为这模样效率就低了,而是直接创立一个原矩阵1/4的矩阵,然后卷积时候跳过那些要被删掉的行和列。

    面下也一样,创立后卷积,由于一些地方一定是0,所以际实卷积中程过,内核有些素元是被疏忽的。

    

var pyrUp = function(__src, __dst){
    __src || error(arguments.callee, IS_UNDEFINED_OR_NULL/* {line} */);
    if(__src.type && __src.type == "CV_RGBA"){
        var width = __src.col,
            height = __src.row,
            dWidth = width * 2,
            dHeight = height * 2,
            sData = __src.data,
            dst = __dst || new Mat(dHeight, dWidth, CV_RGBA),
            dstData = dst.data;
        
        var withBorderMat = copyMakeBorder(__src, 2, 2, 0, 0),
            mData = withBorderMat.data,
            mWidth = withBorderMat.col;
        
        var newValue, nowX, offsetY, offsetI, dOffsetI, i, j;
        
        var kernel = [1,  4,  6,  4, 1,
                      4, 16, 24, 16, 4,
                      6, 24, 36, 24, 6,
                      4, 16, 24, 16, 4,
                      1,  4,  6,  4, 1
                     ];
        
        for(i = dHeight; i--;){
            dOffsetI = i * dWidth;
            for(j = dWidth; j--;){
                for(c = 3; c--;){
                    newValue = 0;
                    for(y = 2 + (i & 1); y--;){
                        offsetY = (y + ((i + 1) >> 1)) * mWidth * 4;
                        for(x = 2 + (j & 1); x--;){
                            nowX = (x + ((j + 1) >> 1)) * 4 + c;
                            newValue += (mData[offsetY + nowX] * kernel[(y * 2 + (i & 1 ^ 1)) * 5 + (x * 2 + (j & 1 ^ 1))]);
                        }
                    }
                    dstData[(j + dOffsetI) * 4 + c] = newValue / 64;
                }
                dstData[(j + dOffsetI) * 4 + 3] = mData[offsetY + 2 * mWidth * 4 + (((j + 1) >> 1) + 2) * 4 + 3];
            }
        }
        
    }else{
        error(arguments.callee, UNSPPORT_DATA_TYPE/* {line} */);
    }
    
    return dst;
};
 

    

效果图

    图像和卷积

 

    

系列录目

    Javascript图像处理系列

 

    

参考资料

    Image Pyramids

文章结束给大家分享下程序员的一些笑话语录: Borland说我很有前途,Sun笑了;Sun说我很有钱,IBM笑了;IBM说我很专业,Sybase笑了;Sybase说我数据库很牛,Oracle笑了;Oracle说我是开放的,Linux笑了;Linux说我要打败Unix,微软笑了;微软说我的系统很稳定,我们都笑了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值