中文字幕在线一区二区在线,久久久精品免费观看国产,无码日日模日日碰夜夜爽,天堂av在线最新版在线,日韩美精品无码一本二本三本,麻豆精品三级国产国语,精品无码AⅤ片,国产区在线观看视频

      使用JavaScript進行基本圖形操作與處理

      時間:2024-10-17 06:22:09 JavaScript 我要投稿
      • 相關推薦

      使用JavaScript進行基本圖形操作與處理

        前言

        上一篇文章,我們講解了圖像的虛擬邊緣,這篇文章開始進行平滑(也就是模糊)處理。

        基本原理

        這里直接引用OpenCV 2.4+ C++ 平滑處理和OpenCV 2.4+ C++ 邊緣梯度計算的相關內容:

        平滑也稱模糊, 是一項簡單且使用頻率很高的圖像處理方法。

        平滑處理時需要用到一個濾波器

        。 最常用的濾波器是線性濾波器,線性濾波處理的輸出像素值(例如:

        )是輸入像素值(例如:

        )的加權平均:

        稱為核

        , 它僅僅是一個加權系數。

        這里涉及一種叫做“卷積”的運算,那么卷積是什么呢?

        卷積是在每一個圖像塊與某個算子(核)之間進行的運算。

        核?!

        nbsp;

        dsds

        核就是一個固定大小的數值數組。該數組帶有一個錨點

        ,一般位于數組中央。

        可是這怎么運算啊?

        假如你想得到圖像的某個特定位置的卷積值,可用下列方法計算:

        將核的錨點放在該特定位置的像素上,同時,核內的其他值與該像素鄰域的各像素重合;將核內各值與相應像素值相乘,并將乘積相加;將所得結果放到與錨點對應的像素上;對圖像所有像素重復上述過程。

        用公式表示上述過程如下:

        在圖像邊緣的卷積怎么辦呢?

        計算卷積前,需要通過復制源圖像的邊界創建虛擬像素,這樣邊緣的地方也有足夠像素計算卷積了。這就是為什么上一篇文章需要做虛擬邊緣函數。

        均值平滑

        均值平滑實際上就是內核元素全是1的卷積運算,然后再除以內核的大小,用數學表達式來表示就是:

        下面我們來實現均值平滑函數blur:

        復制代碼 代碼如下:

        function blur(__src, __size1, __size2, __borderType, __dst){

        if(__src.type && __src.type == "CV_RGBA"){

        var height = __src.row,

        width = __src.col,

        dst = __dst || new Mat(height, width, CV_RGBA),

        dstData = dst.data;

        var size1 = __size1 || 3,

        size2 = __size2 || size1,

        size = size1 * size2;

        if(size1 % 2 !== 1 || size2 % 2 !== 1){

        console.error("size大小必須是奇數");

        return __src;

        }

        var startX = Math.floor(size1 / 2),

        startY = Math.floor(size2 / 2);

        var withBorderMat = copyMakeBorder(__src, startY, startX, 0, 0, __borderType),

        mData = withBorderMat.data,

        mWidth = withBorderMat.col;

        var newValue, nowX, offsetY, offsetI;

        var i, j, c, y, x;

        for(i = height; i--;){

        offsetI = i * width;

        for(j = width; j--;){

        for(c = 3; c--;){

        newValue = 0;

        for(y = size2; y--;){

        offsetY = (y + i) * mWidth * 4;

        for(x = size1; x--;){

        nowX = (x + j) * 4 + c;

        newValue += mData[offsetY + nowX];

        }

        }

        dstData[(j + offsetI) * 4 + c] = newValue / size;

        }

        dstData[(j + offsetI) * 4 + 3] = mData[offsetY + startY * mWidth * 4 + (j + startX) * 4 + 3];

        }

        }

        }else{

        console.error("不支持類型。");

        }

        return dst;

        }

        其中size1和size2分別是核的橫向和縱向大小,并且必須是正奇數。

        高斯平滑

        最有用的濾波器 (盡管不是最快的)。 高斯濾波是將輸入數組的每一個像素點與高斯內核

        卷積將卷積和當作輸出像素值。

        參考一維高斯函數,我們可以看見,他是個中間大兩邊小的函數。

        所以高斯濾波器其加權數是中間大,四周小的。

        其二維高斯函數為:

        其中

        為均值 (峰值對應位置),

        代表標準差 (變量

        和 變量

        各有一個均值,也各有一個標準差)。

        這里參考OpenCV的實現,不過應該還有優化空間,因為還沒用到分離濾波器。

        首先我們做一個getGaussianKernel來返回高斯濾波器的一維數組。

        復制代碼 代碼如下:

        function getGaussianKernel(__n, __sigma){

        var SMALL_GAUSSIAN_SIZE = 7,

        smallGaussianTab = [[1],

        [0.25, 0.5, 0.25],

        [0.0625, 0.25, 0.375, 0.25, 0.0625],

        [0.03125, 0.109375, 0.21875, 0.28125, 0.21875, 0.109375, 0.03125]

        ];

        var fixedKernel = __n & 2 == 1 && __n <= SMALL_GAUSSIAN_SIZE && __sigma <= 0="" __n="">> 1] : 0;

        var sigmaX = __sigma > 0 ? __sigma : ((__n - 1) * 0.5 - 1) * 0.3 + 0.8,

        scale2X = -0.5 / (sigmaX * sigmaX),

        sum = 0;

        var i, x, t, kernel = [];

        for(i = 0; i < __n; i++){

        x = i - (__n - 1) * 0.5;

        t = fixedKernel ? fixedKernel[i] : Math.exp(scale2X * x * x);

        kernel[i] = t;

        sum += t;

        }

        sum = 1 / sum;

        for(i = __n; i--;){

        kernel[i] *= sum;

        }

        return kernel;

        };

        然后通過兩個這個一維數組,便可以計算出一個完整的高斯內核,再利用blur里面用到的循環方法,就可以算出高斯平滑后的矩陣了。

        復制代碼 代碼如下:

        function GaussianBlur(__src, __size1, __size2, __sigma1, __sigma2, __borderType, __dst){

        if(__src.type && __src.type == "CV_RGBA"){

        var height = __src.row,

        width = __src.col,

        dst = __dst || new Mat(height, width, CV_RGBA),

        dstData = dst.data;

        var sigma1 = __sigma1 || 0,

        sigma2 = __sigma2 || __sigma1;

        var size1 = __size1 || Math.round(sigma1 * 6 + 1) | 1,

        size2 = __size2 || Math.round(sigma2 * 6 + 1) | 1,

        size = size1 * size2;

        if(size1 % 2 !== 1 || size2 % 2 !== 1){

        console.error("size必須是奇數。");

        return __src;

        }

        var startX = Math.floor(size1 / 2),

        startY = Math.floor(size2 / 2);

        var withBorderMat = copyMakeBorder(__src, startY, startX, 0, 0, __borderType),

        mData = withBorderMat.data,

        mWidth = withBorderMat.col;

        var kernel1 = getGaussianKernel(size1, sigma1),

        kernel2,

        kernel = new Array(size1 * size2);

        if(size1 === size2 && sigma1 === sigma2)

        kernel2 = kernel1;

        else

        kernel2 = getGaussianKernel(size2, sigma2);

        var i, j, c, y, x;

        for(i = kernel2.length; i--;){

        for(j = kernel1.length; j--;){

        kernel[i * size1 + j] = kernel2[i] * kernel1[j];

        }

        }

        var newValue, nowX, offsetY, offsetI;

        for(i = height; i--;){

        offsetI = i * width;

        for(j = width; j--;){

        for(c = 3; c--;){

        newValue = 0;

        for(y = size2; y--;){

        offsetY = (y + i) * mWidth * 4;

        for(x = size1; x--;){

        nowX = (x + j) * 4 + c;

        newValue += (mData[offsetY + nowX] * kernel[y * size1 + x]);

        }

        }

        dstData[(j + offsetI) * 4 + c] = newValue;

        }

        dstData[(j + offsetI) * 4 + 3] = mData[offsetY + startY * mWidth * 4 + (j + startX) * 4 + 3];

        }

        }

        }else{

        console.error("不支持的類型");

        }

        return dst;

        }

        中值平滑

        中值濾波將圖像的每個像素用鄰域 (以當前像素為中心的正方形區域)像素的

        中值代替 。

        依然使用blur里面用到的循環,只要得到核中的所有值,再通過sort排序便可以得到中值,然后錨點由該值替代。

        復制代碼 代碼如下:

        function medianBlur(__src, __size1, __size2, __borderType, __dst){

        if(__src.type && __src.type == "CV_RGBA"){

        var height = __src.row,

        width = __src.col,

        dst = __dst || new Mat(height, width, CV_RGBA),

        dstData = dst.data;

        var size1 = __size1 || 3,

        size2 = __size2 || size1,

        size = size1 * size2;

        if(size1 % 2 !== 1 || size2 % 2 !== 1){

        console.error("size必須是奇數");

        return __src;

        }

        var startX = Math.floor(size1 / 2),

        startY = Math.floor(size2 / 2);

        var withBorderMat = copyMakeBorder(__src, startY, startX, 0, 0, __borderType),

        mData = withBorderMat.data,

        mWidth = withBorderMat.col;

        var newValue = [], nowX, offsetY, offsetI;

        var i, j, c, y, x;

        for(i = height; i--;){

        offsetI = i * width;

        for(j = width; j--;){

        for(c = 3; c--;){

        for(y = size2; y--;){

        offsetY = (y + i) * mWidth * 4;

        for(x = size1; x--;){

        nowX = (x + j) * 4 + c;

        newValue[y * size1 + x] = mData[offsetY + nowX];

        }

        }

        newValue.sort();

        dstData[(j + offsetI) * 4 + c] = newValue[Math.round(size / 2)];

        }

        dstData[(j + offsetI) * 4 + 3] = mData[offsetY + startY * mWidth * 4 + (j + startX) * 4 + 3];

        }

        }

        }else{

        console.error("類型不支持");

        }

        return dst;

        };

      【使用JavaScript進行基本圖形操作與處理】相關文章:

      javascript編程異常處理的方法08-04

      使用ajax操作JavaScript對象的方法09-28

      詳解JavaScript中的splice()使用方法08-20

      javascript中for/in循環以及常見的使用技巧06-24

      Javascript中arguments對象的詳解和使用方法08-20

      有關深入理解JavaScript中的并行處理的介紹10-14

      電腦使用的幾個基本技巧10-18

      華為的基本使用命令10-22

      使用幻燈片進行演講的技巧07-03

      關于javascript對象之內置和對象Math的使用方法10-08

      主站蜘蛛池模板: 加勒比在线中文字幕一区二区| 午夜无码无遮挡在线视频| 亚洲国产一区二区三区,| 久久精品国产精品亚洲艾| 女同在线观看免费网站| 枣强县| 人妻少妇人人丰满视频网站| 国产精品系列亚洲第一| 中文字幕第一页在线无码一区二区| 通城县| 亚洲精品中文字幕一区二区三区| 一本大道人妻中文字幕| 中文字幕人妻一区二区三区四区| 日本一级淫片免费啪啪| 启东市| 武鸣县| 南投市| 亚洲av永久青草无码精品| 一区二区三区福利在线视频| 亚洲高清美女久久av| 亚洲一区二区三在线播放| 亚洲国产不卡av一区二区三区 | 亚洲成人精品一区免费| 涩涩国产在线不卡无码| 国产色婷婷亚洲99精品| 日韩人妻中文字幕一区二区| 国产美女丝袜高潮白浆| 国产激情一区二区三区在线蜜臀| а的天堂网最新版在线| 滦南县| 蜜桃成人午夜激情网站| 亚洲激情在线观看第三页| 国产美女黑丝嫩草在线| 免费人妻精品一区二区| 国产精品美女黑丝流水| 亚洲AV乱码毛片在线播放| 插进去内射视频免费观看| 97久久综合区小说区图片专区 | 国产亚洲精品综合一区| 激情综合五月天开心久久| 国产自产21区激情综合一区|