国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問答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技巧

來源:懂視網 責編:小采 時間: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);
}
};

這個函數接受一個輸入矩陣src,每個方向要添加的像素大小top,left,bottom,right,邊緣的類型borderType,還有一個數組value,即如果是常數邊緣時候添加的常數值。
然后我們引入一個邊緣的映射關系函數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;
};

這個函數的意義是對于原長度為len的某一行或者某一列的虛擬像素點p(p一般是負數或者大于或等于該行原長度的數,負數則表示該行左邊的像素點,大于或等于原長度則表示是右邊的像素點),映射成這一行的哪一個像素點。我們拿CV_BORDER_REPLICATE分析一下,其表達式是:
  __p = __p < 0 ? 0 : __len - 1;
也就是說p為負數時(也就是左邊)的時候映射為0,否則映射成len - 1。
然后我們來實現(xiàn)copyMakeBorder_8U函數:
代碼如下:
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));
}

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

然后我們根據ArrayBuffer的性質,將數據轉成無符號32位整數來操作,這樣每個操作單位就對應了每個像素點了。什么意思?
比如對于某個像素點:RGBA,由于某個通道是用無符號8為整數來存儲的,所以實際上一個像素點則對應了32位的存儲大小,由于ArrayBuffer的性質,可以將數據轉成任意類型來處理,這樣我們就可以通過轉成Uint32Array類型,將數據變成每個像素點的數據數組。
那么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

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

文檔

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

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

最新推薦

猜你喜歡

熱門推薦

專題
Top
主站蜘蛛池模板: 日韩a无v码在线播放免费 | 亚洲精品一二三四区 | 黄色小视频免费在线观看 | 亚洲精品免费观看 | 在线观看网站国产 | 91综合网| 欧美日韩综合网 | 欧洲日韩 | 国内精品一级毛片免费看 | 国内精品伊人久久久久妇 | 久久精品成人一区二区三区 | 国产三级福利 | 91精品观看91久久久久久 | 亚洲综合欧美 | 精品一区二区三区在线成人 | 熟年交尾五十路视频在线播放 | 韩国精品一区二区久久 | 精品日韩欧美一区二区三区 | 国产成人精品一区二区三区 | 在线播放一区二区精品产 | 日韩国产欧美视频 | 五月精品| 日韩精品一区二区三区在线观看l | 日韩高清一区二区 | 精品国产欧美一区二区五十路 | 午夜精品久久久久久91 | 青青国产成人久久激情91麻豆 | 日韩欧美一区在线观看 | 欧美小视频在线观看 | 九九久久亚洲综合久久久 | 亚洲欧美日韩在线播放 | 国产精品视频免费 | 欧美成人禁片在线www | 国产成人综合久久精品下载 | 全免费午夜一级毛片一级毛 | 精品久久久久久久久中文字幕 | 最近免费中文字幕大全免费版视频 | 亚洲国产精品婷婷久久久久 | 国产精品美女一区二区三区 | 亚洲午夜久久久久久久久电影网 | 久久国产精品视频一区 |