<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        Javascript圖像處理—虛擬邊緣介紹及使用方法_javascript技巧

        來源:懂視網(wǎng) 責編:小采 時間:2020-11-27 21:06:21
        文檔

        Javascript圖像處理—虛擬邊緣介紹及使用方法_javascript技巧

        Javascript圖像處理—虛擬邊緣介紹及使用方法_javascript技巧:前言 上一篇文章,我們來給矩陣添加一些常用方法,這篇文章將講解圖像的虛擬邊緣。虛擬邊緣 虛擬邊緣就是按照一定映射關系,給圖像添加邊緣。 那么虛擬邊緣有什么用呢?比如可以很容易做一個倒影的效果: 當然這只是附帶效果了,虛擬邊緣主要用在圖像卷積運
        推薦度:
        導讀Javascript圖像處理—虛擬邊緣介紹及使用方法_javascript技巧:前言 上一篇文章,我們來給矩陣添加一些常用方法,這篇文章將講解圖像的虛擬邊緣。虛擬邊緣 虛擬邊緣就是按照一定映射關系,給圖像添加邊緣。 那么虛擬邊緣有什么用呢?比如可以很容易做一個倒影的效果: 當然這只是附帶效果了,虛擬邊緣主要用在圖像卷積運

        前言
        上一篇文章,我們來給矩陣添加一些常用方法,這篇文章將講解圖像的虛擬邊緣。

        虛擬邊緣
        虛擬邊緣就是按照一定映射關系,給圖像添加邊緣。
        那么虛擬邊緣有什么用呢?比如可以很容易做一個倒影的效果:

        當然這只是附帶效果了,虛擬邊緣主要用在圖像卷積運算(例如平滑操作)時候,由于卷積運算的特點,需要將圖片擴大才能對邊角進行卷積運算,這時候就需要對圖片進行預處理,添加虛擬邊緣。
        說白了,就是在一些圖片處理前進行預處理。

        邊緣類型
        這里參考OpenCV相關文檔的邊緣描述:
        代碼如下:
        /*
        Various border types, image boundaries are denoted with '|'
        * BORDER_REPLICATE: aaaaaa|abcdefgh|hhhhhhh
        * BORDER_REFLECT: fedcba|abcdefgh|hgfedcb
        * BORDER_REFLECT_101: gfedcb|abcdefgh|gfedcba
        * BORDER_WRAP: cdefgh|abcdefgh|abcdefg
        * BORDER_CONSTANT: iiiiii|abcdefgh|iiiiiii with some specified 'i'
        */

        舉個例子BODER_REFLECT就是對于某一行或某一列像素點:
          abcdefgh
        其左的虛擬邊緣對應為fedcba,右邊對應為hgfedcb,也就是反射映射。上圖就是通過對圖片底部進行添加BORDER_REFLECT類型的虛擬邊緣得到的。
        而BORDER_CONSTANT則是所有邊緣都是固定值i。
        實現(xiàn)
        因為BORDER_CONSTANT比較特殊,所以和其他類型分開處理。
        代碼如下:
        function copyMakeBorder(__src, __top, __left, __bottom, __right, __borderType, __value){
        if(__src.type != "CV_RGBA"){
        console.error("不支持類型!");
        }
        if(__borderType === CV_BORDER_CONSTANT){
        return copyMakeConstBorder_8U(__src, __top, __left, __bottom, __right, __value);
        }else{
        return copyMakeBorder_8U(__src, __top, __left, __bottom, __right, __borderType);
        }
        };

        這個函數(shù)接受一個輸入矩陣src,每個方向要添加的像素大小top,left,bottom,right,邊緣的類型borderType,還有一個數(shù)組value,即如果是常數(shù)邊緣時候添加的常數(shù)值。
        然后我們引入一個邊緣的映射關系函數(shù)borderInterpolate。
        代碼如下:
        function borderInterpolate(__p, __len, __borderType){
        if(__p < 0 || __p >= __len){
        switch(__borderType){
        case CV_BORDER_REPLICATE:
        __p = __p < 0 ? 0 : __len - 1;
        break;
        case CV_BORDER_REFLECT:
        case CV_BORDER_REFLECT_101:
        var delta = __borderType == CV_BORDER_REFLECT_101;
        if(__len == 1)
        return 0;
        do{
        if(__p < 0)
        __p = -__p - 1 + delta;
        else
        __p = __len - 1 - (__p - __len) - delta;
        }while(__p < 0 || __p >= __len)
        break;
        case CV_BORDER_WRAP:
        if(__p < 0)
        __p -= ((__p - __len + 1) / __len) * __len;
        if(__p >= __len)
        __p %= __len;
        break;
        case CV_BORDER_CONSTANT:
        __p = -1;
        default:
        error(arguments.callee, UNSPPORT_BORDER_TYPE/* {line} */);
        }
        }
        return __p;
        };

        這個函數(shù)的意義是對于原長度為len的某一行或者某一列的虛擬像素點p(p一般是負數(shù)或者大于或等于該行原長度的數(shù),負數(shù)則表示該行左邊的像素點,大于或等于原長度則表示是右邊的像素點),映射成這一行的哪一個像素點。我們拿CV_BORDER_REPLICATE分析一下,其表達式是:
          __p = __p < 0 ? 0 : __len - 1;
        也就是說p為負數(shù)時(也就是左邊)的時候映射為0,否則映射成len - 1。
        然后我們來實現(xiàn)copyMakeBorder_8U函數(shù):
        代碼如下:
        function copyMakeBorder_8U(__src, __top, __left, __bottom, __right, __borderType){
        var i, j;
        var width = __src.col,
        height = __src.row;
        var top = __top,
        left = __left || __top,
        right = __right || left,
        bottom = __bottom || top,
        dstWidth = width + left + right,
        dstHeight = height + top + bottom,
        borderType = borderType || CV_BORDER_REFLECT;
        var buffer = new ArrayBuffer(dstHeight * dstWidth * 4),
        tab = new Uint32Array(left + right);
        for(i = 0; i < left; i++){
        tab[i] = borderInterpolate(i - left, width, __borderType);
        }
        for(i = 0; i < right; i++){
        tab[i + left] = borderInterpolate(width + i, width, __borderType);
        }
        var tempArray, data;
        for(i = 0; i < height; i++){
        tempArray = new Uint32Array(buffer, (i + top) * dstWidth * 4, dstWidth);
        data = new Uint32Array(__src.buffer, i * width * 4, width);
        for(j = 0; j < left; j++)
        tempArray[j] = data[tab[j]];
        for(j = 0; j < right; j++)
        tempArray[j + width + left] = data[tab[j + left]];
        tempArray.set(data, left);
        }
        var allArray = new Uint32Array(buffer);
        for(i = 0; i < top; i++){
        j = borderInterpolate(i - top, height, __borderType);
        tempArray = new Uint32Array(buffer, i * dstWidth * 4, dstWidth);
        tempArray.set(allArray.subarray((j + top) * dstWidth, (j + top + 1) * dstWidth));
        }
        for(i = 0; i < bottom; i++){
        j = borderInterpolate(i + height, height, __borderType);
        tempArray = new Uint32Array(buffer, (i + top + height) * dstWidth * 4, dstWidth);
        tempArray.set(allArray.subarray((j + top) * dstWidth, (j + top + 1) * dstWidth));
        }
        return new Mat(dstHeight, dstWidth, new Uint8ClampedArray(buffer));
        }

        這里需要解釋下,邊緣的復制順序是:先對每行的左右進行擴展,然后在此基礎上進行上下擴展,如圖所示。

        然后我們根據(jù)ArrayBuffer的性質,將數(shù)據(jù)轉成無符號32位整數(shù)來操作,這樣每個操作單位就對應了每個像素點了。什么意思?
        比如對于某個像素點:RGBA,由于某個通道是用無符號8為整數(shù)來存儲的,所以實際上一個像素點則對應了32位的存儲大小,由于ArrayBuffer的性質,可以將數(shù)據(jù)轉成任意類型來處理,這樣我們就可以通過轉成Uint32Array類型,將數(shù)據(jù)變成每個像素點的數(shù)據(jù)數(shù)組。
        那么copyMakeConstBorder_8U就比較容易實現(xiàn)了:
        代碼如下:
        function copyMakeConstBorder_8U(__src, __top, __left, __bottom, __right, __value){
        var i, j;
        var width = __src.col,
        height = __src.row;
        var top = __top,
        left = __left || __top,
        right = __right || left,
        bottom = __bottom || top,
        dstWidth = width + left + right,
        dstHeight = height + top + bottom,
        value = __value || [0, 0, 0, 255];
        var constBuf = new ArrayBuffer(dstWidth * 4),
        constArray = new Uint8ClampedArray(constBuf);
        buffer = new ArrayBuffer(dstHeight * dstWidth * 4);
        for(i = 0; i < dstWidth; i++){
        for( j = 0; j < 4; j++){
        constArray[i * 4 + j] = value[j];
        }
        }
        constArray = new Uint32Array(constBuf);
        var tempArray;
        for(i = 0; i < height; i++){
        tempArray = new Uint32Array(buffer, (i + top) * dstWidth * 4, left);
        tempArray.set(constArray.subarray(0, left));
        tempArray = new Uint32Array(buffer, ((i + top + 1) * dstWidth - right) * 4, right);
        tempArray.set(constArray.subarray(0, right));
        tempArray = new Uint32Array(buffer, ((i + top) * dstWidth + left) * 4, width);
        tempArray.set(new Uint32Array(__src.buffer, i * width * 4, width));
        }
        for(i = 0; i < top; i++){
        tempArray = new Uint32Array(buffer, i * dstWidth * 4, dstWidth);
        tempArray.set(constArray);
        }
        for(i = 0; i < bottom; i++){
        tempArray = new Uint32Array(buffer, (i + top + height) * dstWidth * 4, dstWidth);
        tempArray.set(constArray);
        }
        return new Mat(dstHeight, dstWidth, new Uint8ClampedArray(buffer));
        }

        效果圖
        CV_BORDER_REPLICATE

        CV_BORDER_REFLECT

        CV_BORDER_WRAP

        CV_BORDER_CONSTANT

        聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        Javascript圖像處理—虛擬邊緣介紹及使用方法_javascript技巧

        Javascript圖像處理—虛擬邊緣介紹及使用方法_javascript技巧:前言 上一篇文章,我們來給矩陣添加一些常用方法,這篇文章將講解圖像的虛擬邊緣。虛擬邊緣 虛擬邊緣就是按照一定映射關系,給圖像添加邊緣。 那么虛擬邊緣有什么用呢?比如可以很容易做一個倒影的效果: 當然這只是附帶效果了,虛擬邊緣主要用在圖像卷積運
        推薦度:
        標簽: 圖片 介紹 js
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 亚洲制服丝袜中文字幕| 亚洲精品视频免费在线观看| 亚洲国产精品成人午夜在线观看 | 噜噜嘿在线视频免费观看| 日韩免费观看的一级毛片| 国产偷伦视频免费观看| 免费精品久久天干天干| 亚洲综合国产一区二区三区| 一级a性色生活片久久无少妇一级婬片免费放 | 嫩草在线视频www免费观看| 亚洲avav天堂av在线不卡| 日本免费大黄在线观看| 亚洲国产理论片在线播放| 性一交一乱一视频免费看| 亚洲熟伦熟女专区hd高清| 成人永久免费福利视频网站| 无码人妻一区二区三区免费视频 | 亚洲成a人片毛片在线| 在线视频免费观看高清| 国产成人人综合亚洲欧美丁香花| 亚洲国产电影av在线网址| 免费无码又爽又刺激网站直播 | a级成人免费毛片完整版| 亚洲第一香蕉视频| 国产在线国偷精品产拍免费| 在线亚洲精品视频| 亚洲人成人无码网www电影首页 | 深夜a级毛片免费无码| 亚洲精品无码永久在线观看你懂的| 亚洲欧洲免费视频| 亚洲日韩亚洲另类激情文学| 亚洲狠狠爱综合影院婷婷| 无码成A毛片免费| 毛片亚洲AV无码精品国产午夜 | 亚洲精品一区二区三区四区乱码| 免费涩涩在线视频网| 中国性猛交xxxxx免费看| 亚洲国产综合自在线另类| 国产一区二区三区在线免费观看| baoyu777永久免费视频| 亚洲乱码av中文一区二区|