手机版

Javascript图像处理-虚拟边缘的介绍和使用

时间:2021-10-06 来源:互联网 编辑:宝哥软件园 浏览:

前言在最后一篇文章中,我们将向矩阵中添加一些常见的方法。本文将解释图像的虚拟边缘。虚拟边缘虚拟边缘是根据一定的映射关系给图像添加一条边缘。那么虚边有什么用呢?比如你可以很容易的做出一个反射效果:

当然,这只是副作用。虚拟边缘主要用于图像卷积运算(如平滑运算)。由于卷积运算的特点,在对角点进行卷积运算之前,需要对图像进行放大。此时,需要对图像进行预处理并添加虚拟边缘。说白了,就是对一些图片进行处理前的预处理。类型参考此处OpenCV相关文档的边缘描述:复制代码如下: /*各种边框类型,图像边界用“| * BOrder _ replicatee : AAA | abcdefgh | hhhhhhh * BOrder _ REFLECT : fed ba | abcdefgh | hgfedcb * BOrder _ REFLECT _ 101: gfedcb | abcdefgh | gfedcba * BOrder _ wrap : cdefgh | abcdefgh | abcdefgh上图是通过在图片底部添加一个BORDER _ REFLECT类型的虚拟边得到的。而BORDER_CONSTANT是所有边的固定值I。因为BORDER _ CONSTANT的实现是特殊的,所以它与其他类型分开处理。复制的代码如下:函数copy make border(_ src,_ _ top,_ _ left,_ _ bottom,_ _ right,_ _ bordertype,_ _ value){ if(_ src . type!='CV_RGBA'){ console.error('类型不受支持!'。);} if(_ BORDER type===CV _ BORDER _ CONSTANT){返回copymakecontborder _ 8U(_ src,__top,__left,__bottom,__right,_ _ value);}else{返回copyMakeBorder_8U(__src,__top,__left,__bottom,__right,_ _ Bordertype);} };该函数接受一个输入矩阵src、要在每个方向上添加的像素大小(顶部、左侧、底部、右侧)、边缘borderType的类型和一个数组值,也就是说,如果它是恒定边缘,则是要添加的常数值。然后我们引入一个边缘映射函数,borderInterpolate。复制代码如下:函数border insert(_ p,_ _ len,_ _ border type){ if(_ P0 | | _ _ p=_ _ len){ switch(_ border type){ casecv _ border _ replicate : _ _ p=_ _ p . 0 : _ _ len-1;打破;案例CV_BORDER_REFLECT:案例CV _ BORDER _ REFLECT _ 101: var delta=_ _ BORDER type==CV _ BORDER _ REFLECT _ 101;if(_ len==1)返回0;do { if(_ p 0)_ p=-_ _ p-1;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;打破;case CV _ BOrder _ constant : _ _ p=-1;default:错误(arguments.callee,UNSPORT _ BORDER _ TYPE/* { line } */);} } return _ _ p;};该函数的意义是将一行或一列中的虚拟像素p映射为原始长度len (p一般为负数或大于或等于该行原始长度的数字,负数代表该行左侧的像素,大于或等于原始长度的代表右侧的像素)。我们来分析一下CV_BORDER_REPLICATE,它的表达式是:__p=__p 0?0 : _ _ len-1;也就是说,当p为负(即向左)时,映射为0,否则映射为len-1。

然后我们来实现copyMakeBorder_8U函数:复制代码代码如下:函数CopyMakeBorder _ 8U(_ src,__top,__left,__bottom,__right,__borderType){ var i,j;var width=__src.col,height=_ _ src.rowvar top=__top,left=_ _ left | | _ _ top,right=__right || left,bottom=__bottom || top,dstWidth=width left right,dstHeight=height top bottom,BORDER type=BORDER type | | CV _ BORDER _ REFLECT;var buffer=new ArrayBuffer(dst高度* dst宽度* 4),tab=new Uint32Array(左右);for(I=0;我离开了;I){ tab[I]=border periplite(I-left,width,_ _边框类型);} for(I=0;我是对的;I){ tab[I left]=border periplite(宽度I,宽度,_ _边框类型);} var tempArray,data for(I=0;一、身高;i ){ tempArray=new Uint32Array(缓冲区,(I顶)* DsWidth * 4,DsWidth);数据=新的uint 32数组(_ src。缓冲区,i * width * 4,宽度);for(j=0;j向左;j)tempArray[j]=data[tab[j]];for(j=0;j右;j ) tempArray[j宽度左]=数据[选项卡[j]左]];tempArray.set(数据,左侧);} var allArray=new Uint32Array(缓冲区);for(I=0;我顶;I){ j=border interpilote(I-top,height,_ _边框类型);tempArray=new Uint32Array(缓冲区,i * dstWidth * 4,DsWidth);temparray。设置(allarray。subarray((j top)* DsWidth,(j top 1)* DsWidth));} for(I=0;我垫底;I){ j=border interpilote(I高度,高度,_ _边框类型);tempArray=new Uint32Array(缓冲区,(我顶部高度)* dstWidth * 4,DsWidth);temparray。设置(allarray。subarray((j top)* DsWidth,(j top 1)* DsWidth));}返回新Mat(数据高度,数据间距,新uint 8夹紧阵列(缓冲区));} 这里需要解释下,边缘的复制顺序是:先对每行的左右进行扩展,然后在此基础上进行上下扩展,如图所示

然后我们根据ArrayBuffer的性质,将数据转成无符号32位整数来操作,这样每个操作单位就对应了每个像素点了。什么意思?比如对于某个像素点:RGBA,由于某个通道是用无符号8为整数来存储的,所以实际上一个像素点则对应了32位的存储大小,由于ArrayBuffer的性质,可以将数据转成任意类型来处理,这样我们就可以通过转成Uint32Array类型,将数据变成每个像素点的数据数组。那么copyMakeConstBorder _ 8U就比较容易实现了:复制代码代码如下:函数copymakecontborder _ 8U(_ src,__top,__left,__bottom,__right,__value){ var i,j;var width=__src.col,height=_ _ src.rowvar top=__top,left=__left || __top,right=__right || left,bottom=__bottom || top,dstWidth=width left right,dstHeight=height top bottom,value=__value || [0,0,255];var const buf=new ArrayBuffer(dstWidth * 4),const array=new uint 8 clapped array(const buf);buffer=new ArrayBuffer(dsth高度* dst宽度* 4);for(I=0;I DsTwidTi){ for(j=0;j4;j){ constraint[I * 4j]=value[j];} } const array=new uint 32 array(const buf);var tempArrayfor(I=0;一、身高;i ){ tempArray=new Uint32Array(缓冲区,(我顶部)* dstWidth * 4,左侧);temparray。set(constarray。子阵列(0,左));tempArray=new Uint32Array(缓冲区,((I top 1)* DsWidth-right)* 4,right);temparray。set(constarray。子阵列(0,右));tempArray=新的uint 32数组(缓冲区,((I top)* DsWidth left)* 4,width);temparray。set(新的Uint 32数组(_ src。缓冲区,i * width * 4,width));} for(I=0;我顶;i ){ tempArray=new Uint32Array(缓冲区,i * dstWidth * 4,dst宽度);tempArray.set(常量数组);} for(I=0;我垫底;i ){ tempArray=new Uint32Array(缓冲区,(我顶部高度)* dstWidth * 4,DsWidth);tempArray.set(常量数组);}返回新Mat(数据高度,数据间距,新uint 8夹紧阵列(缓冲区));} 效果图CV _ BORDER _ REPLICATE(9502 . 163.com)

CV _ BOrder _ REFLOW(9503 . 163.com)

CV _ BORDER _ WRAP

循环边界常数

版权声明:Javascript图像处理-虚拟边缘的介绍和使用是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。