精华内容
下载资源
问答
  • 图像卷积与滤波的一些知识

    万次阅读 多人点赞 2015-10-12 21:24:06
    图像卷积与滤波的一些知识zouxy09@qq.comhttp://blog.csdn.net/zouxy09 之前在学习CNN的时候,有对卷积经常一些学习和整理,后来就烂尾了,现在稍微整理下,先放上来,以提醒和交流。一、线性滤波与卷积的基本...

    图像卷积与滤波的一些知识点

    zouxy09@qq.com

    http://blog.csdn.net/zouxy09

     

          之前在学习CNN的时候,有对卷积进行一些学习和整理,后来就烂尾了,现在稍微整理下,先放上来,以提醒和交流。

    一、线性滤波与卷积的基本概念

          线性滤波可以说是图像处理最基本的方法,它可以允许我们对图像进行处理,产生很多不同的效果。做法很简单。首先,我们有一个二维的滤波器矩阵(有个高大上的名字叫卷积核)和一个要处理的二维图像。然后,对于图像的每一个像素点,计算它的邻域像素和滤波器矩阵的对应元素的乘积,然后加起来,作为该像素位置的值。这样就完成了滤波过程。

          对图像和滤波矩阵进行逐个元素相乘再求和的操作就相当于将一个二维的函数移动到另一个二维函数的所有位置,这个操作就叫卷积或者协相关。卷积和协相关的差别是,卷积需要先对滤波矩阵进行180的翻转,但如果矩阵是对称的,那么两者就没有什么差别了。

          Correlation 和 Convolution可以说是图像处理最基本的操作,但却非常有用。这两个操作有两个非常关键的特点:它们是线性的,而且具有平移不变性shift-invariant。平移不变性指我们在图像的每个位置都执行相同的操作。线性指这个操作是线性的,也就是我们用每个像素的邻域的线性组合来代替这个像素。这两个属性使得这个操作非常简单,因为线性操作是最简单的,然后在所有地方都做同样的操作就更简单了。

          实际上,在信号处理领域,卷积有广泛的意义,而且有其严格的数学定义,但在这里不关注这个。

          2D卷积需要4个嵌套循环4-double loop,所以它并不快,除非我们使用很小的卷积核。这里一般使用3x3或者5x5。而且,对于滤波器,也有一定的规则要求:

          1)滤波器的大小应该是奇数,这样它才有一个中心,例如3x3,5x5或者7x7。有中心了,也有了半径的称呼,例如5x5大小的核的半径就是2。

          2)滤波器矩阵所有的元素之和应该要等于1,这是为了保证滤波前后图像的亮度保持不变。当然了,这不是硬性要求了。

          3)如果滤波器矩阵所有元素之和大于1,那么滤波后的图像就会比原图像更亮,反之,如果小于1,那么得到的图像就会变暗。如果和为0,图像不会变黑,但也会非常暗。

          4)对于滤波后的结构,可能会出现负数或者大于255的数值。对这种情况,我们将他们直接截断到0和255之间即可。对于负数,也可以取绝对值。

    二、神奇的卷积核

          上面说到,对图像的滤波处理就是对图像应用一个小小的卷积核,那这个小小的卷积核到底有哪些魔法,能让一个图像从惨不忍睹变得秀色可餐。下面我们一起来领略下一些简单但不简单的卷积核的魔法。

    2.1、啥也不做

          哈哈,大家可以看到啥了吗?这个滤波器啥也没有做,得到的图像和原图是一样的。因为只有中心点的值是1。邻域点的权值都是0,对滤波后的取值没有任何影响。

          下面我们动点真格的。

    2.2、图像锐化滤波器Sharpness Filter

          图像的锐化和边缘检测很像,首先找到边缘,然后把边缘加到原来的图像上面,这样就强化了图像的边缘,使图像看起来更加锐利了。这两者操作统一起来就是锐化滤波器了,也就是在边缘检测滤波器的基础上,再在中心的位置加1,这样滤波后的图像就会和原始的图像具有同样的亮度了,但是会更加锐利。

          我们把核加大,就可以得到更加精细的锐化效果

          另外,下面的滤波器会更强调边缘:

          主要是强调图像的细节。最简单的3x3的锐化滤波器如下:

          实际上是计算当前点和周围点的差别,然后将这个差别加到原来的位置上。另外,中间点的权值要比所有的权值和大于1,意味着这个像素要保持原来的值。

    2.3、边缘检测Edge Detection

          我们要找水平的边缘:需要注意的是,这里矩阵的元素和是0,所以滤波后的图像会很暗,只有边缘的地方是有亮度的。

          为什么这个滤波器可以寻找到水平边缘呢?因为用这个滤波器卷积相当于求导的离散版本:你将当前的像素值减去前一个像素值,这样你就可以得到这个函数在这两个位置的差别或者斜率。下面的滤波器可以找到垂直方向的边缘,这里像素上和下的像素值都使用:

          再下面这个滤波器可以找到45度的边缘:取-2不为了什么,只是为了让矩阵的元素和为0而已。

          那下面这个滤波器就可以检测所有方向的边缘:

          为了检测边缘,我们需要在图像对应的方向计算梯度。用下面的卷积核来卷积图像,就可以了。但在实际中,这种简单的方法会把噪声也放大了。另外,需要注意的是,矩阵所有的值加起来要是0.

    2.4、浮雕Embossing Filter

          浮雕滤波器可以给图像一种3D阴影的效果。只要将中心一边的像素减去另一边的像素就可以了。这时候,像素值有可能是负数,我们将负数当成阴影,将正数当成光,然后我们对结果图像加上128的偏移。这时候,图像大部分就变成灰色了。

          下面是45度的浮雕滤波器

          我们只要加大滤波器,就可以得到更加夸张的效果了

          这种效果非常的漂亮,就像是将一副图像雕刻在一块石头上面一样,然后从一个方向照亮它。它和前面的滤波器不同,它是非对称的。另外,它会产生负数值,所以我们需要将结果偏移,以得到图像灰度的范围。

          A:原图像。B:锐化。C:边缘检测。D:浮雕

    2.5、均值模糊Box Filter (Averaging)

          我们可以将当前像素和它的四邻域的像素一起取平均,然后再除以5,或者直接在滤波器的5个地方取0.2的值即可,如下图:

          可以看到,这个模糊还是比较温柔的,我们可以把滤波器变大,这样就会变得粗暴了:注意要将和再除以13.

          所以,如果你想要更模糊的效果,加大滤波器的大小即可。或者对图像应用多次模糊也可以。


    2.6、高斯模糊

          均值模糊很简单,但不是很平滑。高斯模糊就有这个优点,所以被广泛用在图像降噪上。特别是在边缘检测之前,都会用来移除细节。高斯滤波器是一个低通滤波器。


    2.7、运动模糊Motion Blur

          运动模糊可以通过只在一个方向模糊达到,例如下面9x9的运动模糊滤波器。注意,求和结果要除以9。

          这个效果就好像,摄像机是从左上角移动的右下角。

    三、卷积的计算

          对图像处理而言,存在两大类的方法:空域处理和频域处理!空域处理是指直接对原始的像素空间进行计算,频率处理是指先对图像变换到频域,再做滤波等处理。

    3.1、空域计算-直接2D卷积

    3.1.1、2D卷积

          直接2D卷积就是一开始说的那样,对于图像的每一个像素点,计算它的邻域像素和滤波器矩阵的对应元素的乘积,然后加起来,作为该像素位置的值。

          直接的实现也称为暴力实现brute force,因为它严格按照定义来实现,没有任何优化。当然了,在并行实现里面,它也是比较灵活的。另外,也存在一个优化版本,如果我们的kernel是separable可分的,那么就可以得到一个快5倍左右的卷积方法。

    2.1.2、边界处理

          那卷积核遇到图像边缘怎么办?例如图像顶部的像素,它的上面已经没有像素了,那么它的值如何计算?目前有四种主流的处理方法,我们用一维卷积和均值滤波来说明下。

          我们在1D图像中,用每个像素和它的二邻域的平均值来取代它的值。假设我们有个1D的图像I是这样的:

          对非图像边界的像素的操作比较简单。假设我们对I的第四个像素3做局部平均。也就是我们用2,3和7做平均,来取代这个位置的像素值。也就是,平均会产生一副新的图像J,这个图像在相同位置J (4) = (I(3)+I(4)+I(5))/3 = (2+3+7)/3 = 4。同样,我们可以得到J(3) = (I(2)+I(3)+I(4))/3 =(4+2+3)/3 = 3。需要注意的是,新图像的每个像素都取决于旧的图像,在计算J (4)的时候用J (3)是不对的,而是用I(3),I(4)和I(5)。所以每个像素都是它和它邻域两个像素的平均。平均是线性的操作,因为每个新的像素都是旧像素的线性组合。

          对卷积,也有必须要考虑的情况是,在图像边界的时候,怎么办?J(1)的值应该是什么?它取决于I(0),I(1)和I(2)。但是我们没有I(0)呀!图像左边没有值了。有四种方式来处理这个问题:

          1)第一种就是想象I是无限长的图像的一部分,除了我们给定值的部分,其他部分的像素值都是0。在这种情况下,I(0)=0。所以J(1) = (I(0) + I(1) + I(2))/3 = (0 + 5 + 4)/3= 3. 同样,J(10) = (I(9)+I(10)+I(11))/3 = (3+ 6 + 0)/3 = 3.

          2)第二种方法也是想象I是无限图像的一部分。但没有指定的部分是用图像边界的值进行拓展。在我们的例子中,因为图像I最左边的值I(1)=5,所以它左边的所有值,我们都认为是5 。而图像右边的所有的值,我们都认为和右边界的值I(10)一样,都是6。这时候J(1) = (I(0) + I(1) + I(2))/3 = (5 + 5 + 4)/3= 14/3. 而J(10) = (I(9)+I(10)+I(11))/3 = (3 + 6 + 6)/3 = 5。

          3)第三种情况就是认为图像是周期性的。也就是I不断的重复。周期就是I的长度。在我们这里,I(0)和I(10)的值就是一样的,I(11)的值和I(1)的值也是一样的。所以J(1) = (I(0) + I(1) + I(2))/3= (I(10) + I(1)+ I(2))/3 = (6 + 5 + 4)/3 = 5 。

          4)最后一种情况就是不管其他地方了。我们觉得I之外的情况是没有定义的,所以没办法使用这些没有定义的值,所以要使用图像I没有定义的值的像素都没办法计算。在这里,J(1)和J(10)都没办法计算,所以输出J会比原图像I要小。

          这四种方法有各自的优缺点。如果我们想象我们使用的图像只是世界的一个小窗口,然后我们需要使用窗口边界外的值,那么一般来说,外面的值和边界上的值是几乎相似的,所以第二种方法可能更说得过去。

    2.2、频域计算-快速傅里叶变换FFT卷积

          这个快速实现得益于卷积定理:时域上的卷积等于频域上的乘积。所以将我们的图像和滤波器通过算法变换到频域后,直接将他们相乘,然后再变换回时域(也就是图像的空域)就可以了。

          o表示矩阵逐元素相乘。那用什么方法将空域的图像和滤波器变换到频域了。那就是鼎鼎大名的Fast Fourier Transformation 快速傅里叶变换FFT(其实,在CUDA里面,已经实现了FFT了)。

          要在频域中对一副图像进行滤波,滤波器的大小和图像的大小必须要匹配,这样两者的相乘才容易。因为一般滤波器的大小比图像要小,所以我们需要拓展我们的kernel,让它和图像的大小一致。

          因为CUDA中的FFT实现是周期的,所以kernel的值也要安排成这样,以支持这种周期性。

          为了保证图像边界的像素也可以得到响应输出,我们也需要拓展我们的输入图像。同时,拓展的方式也要支持周期表达。

          如果只是使用卷积定理,没有对输入进行任何修改的话,那么我们得到的是周期卷积的结果。但这可能不是我们要的,因为周期卷积会对输入数据进行周期填补,引入一些artifacts。

          给定N长度的I和K,为了得到线性卷积,我们需要对I和K进行zero padding。为什么要补0,因为DFT假定了输入是无限和周期的,周期是N。 

          如上图,对于I和K,如果没有padding的话,隐含着会假定I和K是周期的,以他们的长度N为周期。图中本来N长度的I和K都是黑色虚线的部分,然后如果没有padding,隐含着就会在N之外,加上同样的无数个I,如红色虚线部分,加上了一个周期。对K也是这样。如果是zero padding的话,在黑色虚线的其他地方都全是0了,如图中蓝色部分。将I和K卷积,如果没有padding,如黑色虚线,会有红色那部分的artifact。如果有padding,就是蓝色实线。

     四、实验代码

          这是第二部分的Matlab实验代码:

    clear,close all, clc
     
    %% readimage
    image =imread('test.jpg');
     
    %% definefilter
    % -----Identity filter -----
    kernel =[0, 0, 0
                         0, 1, 0
                         0, 0, 0];
     
    % -----Average Blur -----
    kernel =[0, 1, 0
                         1, 1, 1
                         0, 1, 0] / 5;
     
    % -----Gaussian Blur -----
    kernel =fspecial('gaussian', 5 , 0.8);
     
    % -----Motion Blur -----
    kernel =[1, 0, 0, 0, 0
                         0, 1, 0, 0, 0
                         0, 0, 1, 0, 0
                         0, 0, 0, 1, 0
                         0, 0, 0, 0, 1] / 5;
                        
    % -----Edges Detection -----
    kernel =[-1, -1, -1
                         -1, 8, -1
                         -1, -1, -1];
     
    % -----Sharpen filter -----
    kernel =[-1, -1, -1
                         -1, 9, -1
                         -1, -1, -1];
                        
    % -----Emboss filter -----
    kernel =[-1, -1, 0
                         -1,  0,1
                         0,   1,1];
                        
    %% convolethe image with defined kernel or filter
    result =zeros(size(image));
    result(:,:, 1) = conv2(double(image(:, :, 1)), double(kernel), 'same');
    result(:,:, 2) = conv2(double(image(:, :, 2)), double(kernel), 'same');
    result(:,:, 3) = conv2(double(image(:, :, 3)), double(kernel), 'same');
     
    %% showthe result
    imshow(image);
    figure
    imshow(uint8(result))

    五、参考文献

    [1] Correlation and Convolution.pdf

    [2] Lode's Computer GraphicsTutorial Image Filtering


    展开全文
  • Android 实现水波特效

    千次阅读 2010-09-01 13:30:00
    本文水波算法部分整理自 GameRes 的资料,原作者 Imagic。我只是在学习 Android 的过程中,想到这个特效,然后就在Android 实现出来,并在源算法的基础添加了雨滴滴落特效,以及划过水面时的涟漪特效。 该程序...

     

    Android 上实现水波特效    

    罗朝辉(http://www.cppblog.com/kesalin

    转载请注明出处

    说明:

           本文水波算法部分整理自 GameRes 上的资料,原作者 Imagic。我只是在学习 Android 的过程中,想到这个特效,然后就在Android 上实现出来,并在源算法的基础上添加了雨滴滴落特效,以及划过水面时的涟漪特效。 该程序在模拟器和真机上运行速度都较慢,需要进一步优化或使用 JNI 实现,如果你想到好的优化算法,请联系我:kesalin@gmail.com

     

        示例程序下载:http://www.cppblog.com/Files/kesalin/RippleDemo.zip

        本文pdf文档下载:点击这里    


    基础知识:

    在讲解代码之前,我们来回顾一下在高中的物理课上我们所学的关于水波的知识。水波有扩散,衰减,折射,反射,衍射等几个特性:

     

    扩散:当你投一块石头到水中,你会看到一个以石头入水点为圆心所形成的一圈圈的水波,这里,你可能会被这个现象所误导,以为水波上的每一点都是以石头入水点为中心向外扩散的,这是错误的。实际上,水波上的任何一点在任何时候都是以自己为圆心向四周扩散的,之所以会形成一个环状的水波,是因为水波的内部因为扩散的对称而相互抵消了。

    衰减:因为水是有阻尼的,否则,当你在水池中投入石头,水波就会永不停止的震荡下去。

    折射:因为水波上不同地点的倾斜角度不同,所以我们从观察点垂直往下看到的水底并不是在观察点的正下方,而有一定的偏移。如果不考虑水面上部的光线反射,这就是我们能感觉到水波形状的原因。

    反射:水波遇到障碍物会反射。

    衍射:在水池中央放上一块礁石,或放一个中间有缝的隔板,那么就能看到水波的衍射现象了。

     

    算法推导:

    好了,有了这几个特性,再运用数学和几何知识,我们就可以模拟出真实的水波了。但是,如果你曾用3DMax做过水波的动画,你就会知道要渲染出一幅真实形状的水波画面少说也得好几十秒,而我们现在需要的是实时的渲染,每秒种至少也得渲染20帧才能使得水波得以平滑的显示。考虑到电脑运算的速度,我们不可能按照正弦函数或精确的公式来构造水波,不能用乘除法,更不能用sincos等三角函数,只能用一种取近似值的快速算法,尽管这种算法存在一定误差,但是为了满足实时动画的要求,我们不得不这样做。

     

    首先我们要建立两个与水池图象一样大小的数组buf1[PoolWidth * PoolHeight]buf2[PoolWidth * PoolHeight]PoolWidth 为水池图象的象素宽度、PoolHeight 为水池图象的象素高度),用来保存水面上每一个点的前一时刻和后一时刻波幅数据,因为波幅也就代表了波的能量,所以在后面我们称这两个数组为波能缓冲区。水面在初始状态时是一个平面,各点的波幅都为0,所以,这两个数组的初始值都等于0

    下面来推导计算波幅的公式

    我们假设存在这样一个一次公式,可以在任意时刻根据某一个点周围前、后、左、右四个点以及该点自身的振幅来推算出下一时刻该点的振幅,那么,我们就有可能用归纳法求出任意时刻这个水面上任意一点的振幅。如左图,你可以看到,某一时刻,X0点的振幅除了受X0点自身振幅的影响外,同时受来自它周围前、后、左、右四个点(X1X2X3X4)的影响(为了简化,我们忽略了其它所有点),而且,这四个点对X0点的影响力可以说是机会均等的。那么我们可以假设这个一次公式为:

     

    X0’ = a * (X1 + X2 + X3 + X4) + b * X0            (公式1)

     

    a, b为待定系数,X0’ X0点下一时刻的振幅,

    X0X1X2X3X4为当前时刻的振幅

     

    下面我们来求解ab

    假设水的阻尼为0。在这种理想条件下,水的总势能将保持不变,水波永远波动。也就是说在任何时刻,所有点的振幅的和保持不变。那么可以得到下面这个公式:

     

    X0’ + X1’ + ... + Xn’  =  X0 + X1 + ... + Xn

     

    将每一个点用公式1替代,代入上式,得到:

     

    (4a + b) * X0 + (4a + b) * X1 + ... (4a + b) * Xn = X0 + X1 + ... + Xn  => 4a + b = 1

     

    找出一个最简解:a = 1/2b = -1

     

    因为1/2可以用移位运算符 “>>” 来进行,不用进行乘除法,所以,这组解是最适用的而且是最快的。那么最后得到的公式就是:

     

    X0’=X1 + X2 + X3 + X4/ 2 - X0

     

    好了,有了上面这个近似公式,你就可以推广到下面这个一般结论:已知某一时刻水面上任意一点的波幅,那么,在下一时刻,任意一点的波幅就等于与该点紧邻的前、后、左、右四点的波幅的和除以2、再减去该点的波幅。

     

    应该注意到,水在实际中是存在阻尼的,否则,用上面这个公式,一旦你在水中增加一个波源,水面将永不停止的震荡下去。所以,还需要对波幅数据进行衰减处理,让每一个点在经过一次计算后,波幅都比理想值按一定的比例降低。这个衰减率经过测试,用1/32比较合适,也就是1/2^5。可以通过移位运算很快的获得。


    到这里,水波特效算法中最艰难的部分已经明了,下面是Android 源程序中计算波幅数据的代码。

     

    // 某点下一时刻的波幅算法为:上下左右四点的波幅和的一半减去当前波幅,即

    //    X0' =X1 + X2 + X3 + X4/ 2 - X0

    //  +----x3----+

    //  +     |      +

    //  +     |      +

    // x1---x0----x2

    //  +     |      +

    //  +     |      +

    //  +----x4----+

    //

    void rippleSpread()

    {

        int pixels = m_width * (m_height - 1);

        for (int i = m_width; i < pixels; ++i) {

           // 波能扩散:上下左右四点的波幅和的一半减去当前波幅

           // X0' =X1 + X2 + X3 + X4/ 2 - X0

           //

           m_buf2[i] =

    (short)(((m_buf1[i - 1] + m_buf1[i + 1]+

              m_buf1[i - m_width] + m_buf1[i + m_width]) >> 1)

    m_buf2[i]);

     

           // 波能衰减 1/32

          //

           m_buf2[i] -= m_buf2[i] >> 5;

        }

     

        //交换波能数据缓冲区

        short[] temp = m_buf1;

        m_buf1 = m_buf2;

        m_buf2 = temp;

    }


    渲染:

    然后我们可以根据算出的波幅数据对页面进行渲染。

     

    因为水的折射,当水面不与我们的视线相垂直的时候,我们所看到的水下的景物并不是在观察点的正下方,而存在一定的偏移。偏移的程度与水波的斜率,水的折射率和水的深度都有关系,如果要进行精确的计算的话,显然是很不现实的。同样,我们只需要做线性的近似处理就行了。因为水面越倾斜,所看到的水下景物偏移量就越大,所以,我们可以近似的用水面上某点的前后、左右两点的波幅之差来代表所看到水底景物的偏移量。

     

    在程序中,用一个页面装载原始的图像,用另外一个页面来进行渲染。先取得指向两个页面内存区的指针 src  dst,然后用根据偏移量将原始图像上的每一个象素复制到渲染页面上。进行页面渲染的代码如下:

     

    void rippleRender()

    {

        int offset;

        int i = m_width;

        int length = m_width * m_height;

        for (int y = 1; y < m_height - 1; ++y) {

           for (int x = 0; x < m_width; ++x, ++i) {

              // 计算出偏移象素和原始象素的内存地址偏移量 :

              //offset = width * yoffset + xoffset

              offset = (m_width * (m_buf1[i - m_width] - m_buf1[i +m_width])) + (m_buf1[i - 1] - m_buf1[i + 1]);

                

              // 判断坐标是否在范围内

              if (i + offset > 0 && i + offset < length) {

                 m_bitmap2[i] = m_bitmap1[i + offset];

              }

              else {

                 m_bitmap2[i] = m_bitmap1[i];

              }

           }

        }

    }

     

    增加波源:

    俗话说:无风不起浪,为了形成水波,我们必须在水池中加入波源,你可以想象成向水中投入石头,形成的波源的大小和能量与石头的半径和你扔石头的力量都有关系。知道了这些,那么好,我们只要修改波能数据缓冲区buf,让它在石头入水的地点来一个负的尖脉冲,即让buf[x,y] = -n。经过实验,n的范围在(32 ~ 128)之间比较合适。

     

    控制波源半径也好办,你只要以石头入水中心点为圆心,画一个以石头半径为半径的圆,让这个圆中所有的点都来这么一个负的尖脉冲就可以了(这里也做了近似处理)。

    增加波源的代码如下:

     

    // stoneSize    : 波源半径

    // stoneWeight : 波源能量

    //

    void dropStone(int x, int y, int stoneSize, int stoneWeight)

    {

        // 判断坐标是否在范围内

        if ((x + stoneSize) > m_width || (y + stoneSize) > m_height

              || (x - stoneSize) < 0 || (y - stoneSize) < 0) {

           return;

        }

     

        int value = stoneSize * stoneSize;

        short weight = (short)-stoneWeight;

       for (int posx = x - stoneSize; posx < x + stoneSize; ++posx)   {

          for (int posy = y - stoneSize; posy < y + stoneSize; ++posy)       {

             if ((posx - x) * (posx - x) + (posy - y) * (posy - y)

                < value)

             {

                    m_buf1[m_width * posy + posx] = weight;

             }

          }

       }

    }

     

    如果我们想要模拟在水面划过时引起的涟漪效果,那么我们还需要增加新的算法函数 breasenhamDrop

     

    void dropStoneLine(int x, int y, int stoneSize, intstoneWeight) {

       // 判断坐标是否在屏幕范围内

       if ((x + stoneSize) > m_width || (y + stoneSize) > m_height

          || (x - stoneSize) < 0 || (y - stoneSize) < 0) {

             return;

       }

     

       for (int posx = x - stoneSize; posx < x + stoneSize; ++posx)   {

          for (int posy = y - stoneSize; posy < y + stoneSize; ++posy)       {

             m_buf1[m_width * posy + posx] = -40;

          }

       }

    }

     

    // xsys : 起始点,xeye : 终止点

    // size : 波源半径,weight : 波源能量

    void breasenhamDrop (int xs, int ys, int xe, int ye, int size,int weight)

    {

       int dx = xe - xs;

       int dy = ye - ys;

       dx = (dx >= 0) ? dx : -dx;

       dy = (dy >= 0) ? dy : -dy;

     

       if (dx == 0 && dy == 0) {

          dropStoneLine(xs, ys, size, weight);

       }

       else if (dx == 0) {

           int yinc = (ye - ys != 0) ? 1 : -1;

           for(int i = 0; i < dy; ++i){

               dropStoneLine(xs, ys, size, weight);

               ys += yinc;

           }

       }

       else if (dy == 0) {

          int xinc = (xe - xs != 0) ? 1 : -1;

          for(int i = 0; i < dx; ++i){

             dropStoneLine(xs, ys, size, weight);

             xs += xinc;

          }

       }

       else if (dx > dy) {

          int p = (dy << 1) - dx;

          int inc1 = (dy << 1);

          int inc2 = ((dy - dx) << 1);

          int xinc = (xe - xs != 0) ? 1 : -1;

          int yinc = (ye - ys != 0) ? 1 : -1;

     

          for(int i = 0; i < dx; ++i) {

             dropStoneLine(xs, ys, size, weight);

             xs += xinc;

             if (p < 0) {

                p += inc1;

             }

             else {

                ys += yinc;

                p += inc2;

             }

          }

       }

       else {

          int p = (dx << 1) - dy;

          int inc1 = (dx << 1);

          int inc2 = ((dx - dy) << 1);

          int xinc = (xe - xs != 0) ? 1 : -1;

          int yinc = (ye - ys != 0) ? 1 : -1;

     

          for(int i = 0; i < dy; ++i) {

             dropStoneLine(xs, ys, size, weight);

             ys += yinc;

             if (p < 0) {

                p += inc1;

             }

             else {

                xs += xinc;

                p += inc2;

             }

          }

       }

    }

     

     

    效果图:


    划过水面时的涟漪特效


    雨滴滴落水面特效

     

    结语:

    这种用数据缓冲区对图像进行水波处理的方法,有个最大的好处就是,程序运算和显示的速度与水波的复杂程度是没有关系的,无论水面是风平浪静还是波涛汹涌,程序的fps始终保持不变,这一点你研究一下程序就应该可以看出来。

     

    展开全文
  • 在示器之前加入To Workspace 模块,即可将波形的数值保存到工作空间,然后将得到的数据转换成矩阵,对相应矩阵进行操作即可下面给出一个例子:如上图所示,要在scope1中的波形取几个,可搭建如图所示模块,...

    在示波器之前加入To Workspace 模块,即可将波形上的数值保存到工作空间,然后将得到的数据转换成矩阵,对相应矩阵进行操作即可

    下面给出一个例子:


    如上图所示,要在scope1中的波形上取几个点,可搭建如图所示模块,运行之后,在工作空间可以看到下面形式的数据


    将simout中的数据保存为矩阵形式:

    a =


             0         0
        0.0000    0.0000
        0.0002    0.0000
        0.0012    0.0000
        0.0062    0.0000
        0.0313    0.0001
        0.1010    0.0026
        0.1836    0.0146
        0.2685    0.0434
        0.3768    0.1135
        0.5219    0.2827
        0.7112    0.6689
        0.9112    1.3069
        1.0836    1.8807
        1.2735    1.9543
        1.4670    1.3465
        1.6613    0.7041
        1.8613    0.2731
        2.0613    0.0565
        2.2613    0.0066
        2.4613    0.0769
        2.6613    0.2218
        2.8613    0.4045
        3.0613    0.5974
        3.2613    0.7754
        3.4613    0.9119
        3.6613    0.9847
        3.8613    0.9892
        4.0613    0.9437
        4.2613    0.8775
        4.4613    0.8154
        4.6613    0.7705
        4.8613    0.7466
        5.0613    0.7414
        5.2613    0.7496
        5.4613    0.7655
        5.6613    0.7834
        5.8613    0.7992
        6.0613    0.8102
        6.2613    0.8155
        6.4613    0.8158
        6.6613    0.8126
        6.8613    0.8077
        7.0613    0.8027
        7.2613    0.7987
        7.4613    0.7963
        7.6613    0.7954
        7.8613    0.7958
        8.0613    0.7970
        8.2613    0.7984
        8.4613    0.7997
        8.6613    0.8007
        8.8613    0.8012
        9.0613    0.8013
        9.2613    0.8011
        9.4613    0.8007
        9.6613    0.8003
        9.8613    0.8000

       10.0000    0.7998

    使用a_1=a(:,1),a_2=a(:,2)取矩阵a的每一列元素,再根据自己的需求去相应的值即可。


    展开全文
  • 使用小分析方法检测信号的奇异的matlab代码,亲测有效。
  • 卡尔曼滤波

    万次阅读 2017-01-06 16:44:40
    (1) GPS变形监测动态数据处理中的应用:现阶段GPS用于变形观测中,通常是在确定的瞬间静态研究监测的状态,而没有考虑到监测随时间改变位移的动态特性。并且在观测过程中,观测数据往往不连续,这样就无法对...

    卡尔曼滤波

    一、          卡尔曼滤波的起源

    谈到信号的分析与处理,就离不开滤波两个字。通常,信号的频谱处于有限的频率范围内而噪声的频谱则散布在很广的频率范围内,为了消除噪声,可以把FIR滤波器或者IIR滤波器设计成合适的频带滤波器,进行频域滤波。但在许多应用场合,需要直接进行时域滤波,从带噪声的信号中提取有用信号。虽然这样的过程其实也算是对信号的滤波,但其所依据的理论,即针对随机信号的估计理论,是自成体系的。人们对于随机信号干扰下的有用信号不能“确知”,只能“估计”。为了“估计”,要事先确定某种准则以评定估计的好坏程度。

    最小均方误差是一种常用的比较简单的经典准则。对于平稳时间序列的最小均方误差估计的第一个明确解是维纳在1942年2月首先给出的。当时美国的一个战争研究团体发表了一个秘密文件,其中就包括维纳关于滤波问题的研究工作,这项研究是用于防空火力控制系统的。维纳滤波器是基于最小均方误差准则的估计器。为了寻求维纳滤波器的冲激响应,需要求解著名的维纳–霍夫方程。这种滤波理论所求的是使均方误差最小的系统最佳冲激响应的明确表达式。

    从维纳–霍夫方程来看,维纳滤波算法是十分低效的。这种算法要求设置大量的存储器来保存过去的测量数据,一个新的数据到来后,要进行刷新,重新计算自相关和互相关序列。再者,求解这个方程需要耗费大量时间对高阶矩阵求逆。因此,维纳滤波算法难以运用于实时处理中,尤其是无法用于军事、航空航天等领域。

    为此,许多科技工作者进行了多方探索,但在解决非平稳过程的滤波问题时,能给出的方法很少。到20世纪50年代中期,随着空间技术的发展,要求对卫星轨道进行精确地测量,这种方法越来越不能满足实际应用的需要。为此,人们将滤波问题以微分方程表示,提出了一系列适应空间技术应用的精炼算法。1960年和1961年,卡尔曼(R.E. Kalman)和布西(R.S. Bucy)提出了递推滤波算法,成功的将状态变量引入到滤波理论中来,用消息与干扰的状态空间模型代替了通常用来描述它们的协方差函数,将状态空间描述与离散数间刷新联系起来,适于计算机直接进行计算,而不是去寻求滤波器冲激响应的明确公式。这种方法得出的是表征状态估计值及其均方误差的微分方程,给出的是递推算法。这就是著名的卡尔曼理论。

    卡尔曼滤波不要求保存过去的测量数据,当新的数据到来时,根据新的数据和前一时刻的储值的估计,借助于系统本身的状态转移方程,按照一套递推公式,即可算出新的估值。这一点说明卡尔曼滤波器属于IIR滤波器的范畴。这就是说,与维纳滤波器不同,卡尔曼滤波器能够利用先前的运算结果,再根据当前数据提供的最新消息,即可得到当前的估值。卡尔曼递推算法大大减少了滤波装置的存储量和计算量,并且突破了平稳随机过程的限制,使卡尔曼滤波器适用于对时变信号的实时处理

    二、          卡尔曼滤波的原理

    卡尔曼滤波的含义是现时刻的最佳估计为在前一时刻的最佳估计的基础上根据现时刻的观测值作线性修正。卡尔曼滤波在数学上是一种线性最小方差统计估算方法,它是通过处理一系列带有误差的实际测量数据而得到物理参数的最佳估算。其实质要解决的问题是要寻找在最小均方误差下的估计值。它的特点是可以用递推的方法计算,其所需数据存储量较小,便于进行实时处理。具体来说,卡尔曼滤波就是要用预测方程和测量方程对系统状态进行估计。

    设动态系统的状态方程和测量方程分别为:

           

         

        上两式子中,是k时刻的系统状态,和是k-1时刻到k时刻的状态转移矩阵,是k时刻的测量值,是测量系统的参数,和分别表示过程和测量的噪声,他们被假设成高斯白噪声。如果被估计状态和观测量是满足上述第一式,系统过程噪声和观测噪声满足第二式的假设,k时刻的观测的估计可按下述方程求解。

    进一步预测:                                  (1)

    状态估计:                        (2)

        滤波增益矩阵:                               (3)

        一步预测误差方差阵:    (4)

        估计误差方差阵:                          (5)

    上述就是卡尔曼滤波器的5条基本公式,只有给定初值和,根据k时刻的观测值,就可以递推计算得k时刻的状态估计(K=1,2,N)。

    三、          卡尔曼滤波的发展

    自卡尔曼滤波提出以来,经过40多年的发展,卡尔曼滤波已经形成了一个比较完整的理论体系,并且成功应用于航空航天、工业控制等领域,美国空军还将卡尔曼滤波定为标准滤波器。

    但是,随着应用领域的不断扩大,滤波对象不确定性的不断提高,传统KF已经不能满足更高的要求,它的主要不足在于:(1)滤波限制条件比较苛刻,它要求系统模型精确以及系统误差模型和观测误差模型已知,这在实际应用中是很难满足的,或者在系统工作过程中,模型发生变化,这些都导致传统KF的滤波发散或精度下降。(2)计算机字长的限制,这种情况可能导致计算过程中出现舍入误差,从而导致方差阵P( k | k)不对称引起滤波发散。(3)观测数据发生突变,由于传感器故障或外部条件发生改变,极有可能出现数据突变,即野值,这会对滤波器的收敛性产生严重影响,甚至导致发散,可以说,野值是对滤波器稳定性的一个考验。

    针对上述不足,很多学者提出了不同的方法加以克服,如限定记忆法、平方根滤波、渐消记忆滤波、自适应卡尔曼滤波(Adaptive Kalman Filtering,AKF)、抗野值滤波等。其中,AKF因为具有自适应特性非常适合动态系统滤波而受到广泛重视。因此,在采用卡尔曼滤波处理动态测量数据时,一般都要考虑采取适当的自适应滤波方法来解决这一问题。

    自适应卡尔曼滤波最新发展的几个分支包括:相关自适应卡尔曼滤波、多模型自适应卡尔曼滤波、基于信息的自适应卡尔曼滤波、神经网络自适应卡尔曼滤波、模糊逻辑自适应卡尔曼滤波。

    相关法是最基本的一种AKF方法,在许多文献中都有详细的论述,相关法分为两类:输出相关法和信息相关法。输出相关法的主要思想是利用观测向量的相关性M(k) =E[Z(k)ZT(k)]自适应调整增益矩阵K(k),这种方法的主要缺陷是计算复杂,实时性难以满足要求。对于高动态系统(如GPS/INS组合导航系统),这种复杂性就更加突出。信息相关法自适应滤波的主要思想是利用信息的相关性M(k) = E[(V(k)VT(k)]自动调整增益矩阵K(k),其中V(k)= Z(k) - C(k) X^( k)。信息相关法比输出相关法更加有效,因为信息更能反映观测数据特性,但是信息相关法计算复杂度却有所增加,很难满足工程需要。

    但是在高动态系统中(如GPS/INS组合导航、靶场数据测量等),测量数据经常发生突变产生野值,导致状态估计明显偏离真实状态。抗野值的AKF通过对信息的监测判断是否有野值出现,当有野值出现时,通过自适应调整增益矩阵,达到消除野值影响的目的,虚警概率为4.5%。这种方法不仅可以消除野值的影响,而且还可以用于对传感器的故障诊断。但是它仅仅解决了由于野值引起滤波发散的情况,而对其它原因引起的滤波发散无能为力。如果将这种方法与其它AKF方法结合,那么将得到更完善的自适应滤波方法。

    多模型AKF(MultipleModel AKF)最早由Magill在1965年提出的。它由一组卡尔曼滤波器组成,每一个卡尔曼滤波器使用不同的系统模型,各个卡尔曼滤波器并行运行,根据观测向量估计各自的状态。随着时间的不断增加,系统会选出最优的一个滤波器并将其权值增大,而其它权值相应减小。多模型AKF性能最优的前提条件是所用的模型集包含了系统所有可能的模式,但是这个前提条件往往是很难满足的。

    基于信息的AKF主要是通过调整噪声统计特性达到自适应的目的,解决了因为噪声统计特性不明确或噪声发生变化的情况。但是对于系统其它模型发生变化不能达到自适应的目的。

    卡尔曼滤波器需要精确已知系统模型才能得到系统状态的最优估计,但是这种要求在实际当中很难得到。在上述方法中,大部分方法只是对噪声的统计特性进行了自适应估计,如果系统的其它模型不正确或发生变化时,就不能自适应估计了。将人工智能技术和滤波技术融合是滤波技术的发展趋势。神经网络作为人工智能技术中的一个领域,其主要优点在于它对系统的模型没有特别要求,只要有足够的用于训练的先验数据,就可以用训练的神经网络近似代替原系统。神经网络AKF正是为了满足这一需求而提出的。

    AKF是一种很有效的状态滤波技术,已经在目标跟踪、组合导航、故障诊断、图像处理等方面得到成功应用。随着AKF的应用范围不断扩大,AKF已经成为解决工程滤波(估计)问题的主要研究方向。

    AKF的发展趋势大概有以下几个方面:

    (1)深入研究NNAKF。神经网络与AKF结合不仅可以解决模型不确定问题,而且由于神经网络的并行计算,使NNAKF的实时性得到保证。在应用神经网络时,还有许多问题需要进一步解决:NNAKF的结构、训练样本的获取及其鲁棒性研究。

    (2)AKF与其它智能方法结合。神经网络、模糊逻辑与AKF结合使我们看到智能方法与AKF的结合是一个很有前途的研究方向。其它的智能方法包括专家系统、遗传算法以及小波变换等。

    (3)AKF与新方法的结合。

    (4)AKF与自适应控制的结合。

    (5)寻找对放松假设条件系统的滤波方法,如考虑噪声相关模型等。目前的AKF均是在一定的假设条件下的滤波算法。如果假设条件发生变化,或假设条件不能满足,AKF就可能失效,即滤波发散、精度达不到要求等。

    (6)自适应算法性能评估。面对如此众多的AKF,针对特定的滤波对象,如何选择恰当的滤波算法是另外一个研究方向。其中滤波器的滤波精度、鲁棒性、实时性是性能评估的三个重要标准。从工程应用角度考虑,鲁棒性、实时性要求比精度要求更高。

    四、          卡尔曼滤波的应用

    卡尔曼滤波器(KalmanFilter)是一个最优化自回归数据处理算法(optimalrecursive data processing algorithm),它的广泛应用已经超过30年,包括航空器轨道修正、机器人系统控制、雷达系统与导弹追踪等。近年来更被应用于组合导航与动态定位,传感器数据融合、微观经济学等应用研究领域。特别是在图像处理领域如头脸识别、图像分割、图像边缘检测等当前热门研究领域占有重要地位。

    卡尔曼滤波作为一种数值估计优化方法,与应用领域的背景结合性很强。因此在应用卡尔曼滤波解决实际问题时,重要的不仅仅是算法的实现与优化问题,更重要的是利用获取的领域知识对被认识系统进行形式化描述,建立起精确的数学模型,再从这个模型出发,进行滤波器的设计与实现工作。

    滤波器实际实现时,测量噪声协方差R一般可以观测得到,是滤波器的已知条件。它可以通过离线获取一些系统观测值计算出来。通常,难确定的是过程激励噪声协方差的Q值,因为我们无法直接观测到过程信号。一种方法是通过设定一个合适的Q,给过程信号“注入”足够的不确定性来建立一个简单的可以产生可接受结果的过程模型。为了提高滤波器的性能,通常要按一定标准进行系数的选择与调整。基本卡尔曼滤波(KF)器限定在线性的条件下,在大多数的非线性情形下,使用扩展的卡尔曼滤波(EKF)器来对系统状态进行估计。

    随着卡尔曼滤波理论的发展,一些实用卡尔曼滤波技术被提出来,如自适应滤波,次优滤波以及滤波发散抑制技术等逐渐得到广泛应用。其它的滤波理论也迅速发展,如线性离散系统的分解滤波(信息平方根滤波,序列平方根滤波,UD分解滤波),鲁棒滤波(H∞ 波)。

    下面给出几个具体应用的例子。

    (1)      GPS变形监测动态数据处理中的应用:现阶段GPS用于变形观测中,通常是在确定的瞬间静态研究监测点的状态,而没有考虑到监测点随时间改变位移的动态特性。并且在观测过程中,观测数据往往不连续,这样就无法对动态变形进行实时准确描述。卡尔曼滤波(Kalman,1960)是当前应用最广的一种动态数据处理方法,它具有最小无偏方差。在GPS变形监测中,如果将变形体视为一个动态就可以用来描述这个变形体的运动情况。并能在这个系统中分别找出表示它们的状态参数与其观测值之间的函数关系,那么就可以利用卡尔曼滤波来减弱随机噪声的干扰,进而达到提高GPS变形观测数据精度的目的。

    (2)      现代汽车中的悬架分为从动悬架和主动悬架两种。从动悬架即传统式的悬架,是由弹簧、减震器、导向机构等组成,它的功能是减弱路面传给车身的冲击力,衰减由冲击力而引起的承载系统的震动。其中弹簧主要起减缓冲击力的左右,减震器的作用是衰减震动。从动悬架是由外力驱动而起作用的。主动悬架是近十几年发展起来的由电脑控制的一种新型悬架。主动悬架的控制环节中安装了能够产生主动力的装置,采用一种以力抑制力的方式来抑制路面对车身的冲击力及车身的倾斜力。汽车的液压主动悬架系统在控制过程中不可避免的受到噪声的影响。应用卡尔曼滤波对系统的状态向量做最优估计,并应用到系统的全状态反馈控制中,可以有效的提高系统的鲁棒性,

    (3)      以探测搜索、捕获跟踪、激光瞄准为技术依托的机载光电稳定跟踪系统已成为发展新一代光电装备的战略基点之一,对于国防安全、社会稳定、现代化生产和生活有着非常重要的意义。在机载光电稳定跟踪系统中,图像跟踪是一个关键技术,直接决定了跟踪系统的性能。同时,图像跟踪也是计算机视觉领域的一个热点研究问题,在视觉监控、人机互动、机器人导航等领域有着广泛的应用。图像跟踪方法大致可分为两大类:概率跟踪方法和确定性跟踪方法。概率跟踪方法由于跟踪性能稳定、可靠,已成为图像跟踪的主流方法,卡尔曼滤波和粒子滤波是这类方法的典型代表。卡尔曼滤波对系统模型和后验分布有严格限制,只能处理线性、高斯、单模态的情况。

    五、          我对卡尔曼滤波的体会

    通过对卡尔曼滤波相关内容的学习,我对卡尔曼滤波的起源、原理、发展过程以及在实际中的广泛应用有了全新的认识。由于专业原因,平时在专业相关内容的学习、仿真和项目研究过程中还没有在实际中用到卡尔曼滤波,在课堂上的学习和这次大作业相关资料的查阅之后,我总结了自己对卡尔曼滤波的一些认识。下面抛开卡尔曼滤波的公式,用一个简单的例子来进行说明。

    假定我们研究的对象是某个物品在市场上的平均价格,根据我们的经验,该物品的平均价格不会发生变化,即是恒定不变的,某天的平均价格和前一天的一样。但是我们对于我们的经验也不是百分之百的肯定,就可能出现上下几元的偏差,可以把这个偏差当做是我们做信号处理中所遇到的噪声,若这些偏差和前后时间没有关系而且服从高斯分配的,就把这个偏差看成是高斯白噪声。同时,我们会有专门的人员来反馈市场上该物品的价格,当然,这个价格中也存在高斯白噪声的偏差。

    那么现在,对于某一天该物品的平均价格,我们就有两个值,一个是根据经验的预测值,如同系统的预测值,一个是人员反馈回来的值,如同测量值。若要估计第d天的平均价格,首先要根据d-1天的平均价格来预测第d天的平均价格。由于我们估计价格是不变的,即这两天的平均价格相同,设为100元,同时该值的高斯噪声的偏差是5元。我们从人员反馈回来的价格是107元,偏差是3元。那么,实际平均价格是多少呢?我们是该相信自己的推断还是相信人员的反馈?或者是相信哪个多一点呢?

    我们可以用他们的协方差来判断。因为d02=52/(52+32)=0.735,所以d0=0.86,我们可以估算出第d天的实际平均价格是:100+0.86*(107-100)=106.02。可以看出,因为人员反馈的协方差比较小,即比较相信人员反馈,所以估算出的最优平均价格偏向人员反馈的价格。此外,还要计算这个最优平均价格的偏差,算法为((1-d0)*52)^0.5=2.57。这个偏差就是继续估算第d+1天平均价格的偏差。通过这样的方法,卡尔曼滤波器就不断的进行递归,从而估算出最优的值。

    当然这样的比喻并不是很恰当,实际中卡尔曼滤波的应用过程远远比这个要复杂的多,同时现在根据实际情况对卡尔曼滤波器的改进也很多,使得其越来越适应实际的需求。关于卡尔曼滤波的学习对我的帮助是很大的,我不仅掌握了结合课堂内容进行扩展学习的方法,也为日后进行信息处理的研究打下了基础。这种方法也可以运用于其他方面的学习,令我受益匪浅。



     

    展开全文
  • Python小分析库Pywavelets的一点使用心得

    万次阅读 多人点赞 2018-06-14 08:33:31
    将数据序列进行小分解,每一层分解的结果是上次分解得到的低频信号再分解成低频和高频两个部分。如此进过N层分解后源信号X被分解为:X = D1 + D2 + … + DN + AN 其中D1,D2,…,DN分别为第一层、第二层到等N层分解...
  • 点云滤波——半径滤波

    千次阅读 2018-08-31 22:29:30
    如图1所示,有助于形象化理解RadiusOutlierRemoval的作用,在点云数据中,用户指定每个的一定范围内周围至少要有足够多的近邻。例如,如果指定至少要有1个邻居,只有黄色的会被删除,如果指定至少要有2个邻居,...
  • 均值滤波vs中值滤波

    千次阅读 2017-04-08 10:13:16
    中值滤波也是一种很常用的数字滤波器,它通过窗内的所有像素值的中值然后赋给中心像素,然后得到输出图像,这样做的好处是,它不创造新的像素值,只是取周围像素值作为它的输出,这一方法可以有效的消除脉冲噪声...
  • 脉搏特征提取

    热门讨论 2014-02-21 13:06:17
    脉搏的数据以及特征提取,提取到最高最低,周期。可以看下。
  • bool cmpx(Point a,Point b){ //先把n个从左到右排序一 if(a.x!=b.x) return a.x; return a.y; } double Dis(Point a, Point b) { return sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)); } double ...
  • 去噪基本概念

    万次阅读 多人点赞 2018-10-19 22:17:11
    一、前言 在现实生活和工作中,噪声无处不在,在许多领域中,如天文、医学图像和计算机视觉方面收集到的数据常常是含有噪声的。噪声可能来自获取数据的... 小分析是近年来发展起来的一种新的信号处理工具,这...
  • 利用STM32F103单片机输出SPWM

    万次阅读 多人点赞 2019-11-29 14:43:31
    最近需要用到单片机输出SPWM功能,在网上了好多资料,发现都不完整,有算法的没有代码,有代码的看不懂算法。于是只好自己摸索,现将方法整理如下。 关于什么是SPWM,为什么要用SPWM,网上的介绍有很多,就...
  • SPWM在单片机的实现与调节(基于MSP430F5529)

    万次阅读 热门讨论 2016-09-10 20:41:42
    先弄清楚SPWM在单片机如何产生,比如你要输出100HZ的SPWM正弦,每个周期100个,则定时器B的中断频率为100*100=10K,用于载波(定时器A)的PWM频率应>=10K(这里我建议载波为1M,因为定时器的配合问题会有+-1的...
  • 关于点云滤波去噪的方法

    万次阅读 多人点赞 2019-01-24 23:04:04
    (2) 因为遮挡等问题造成离群需要去除 (3) 大量数据需要下采样 (4) 噪声数据需要去除 点云数据去噪滤波方法: 双边滤波、高斯滤波、分箱去噪、KD-Tree、直通滤波、随机采样一致性滤波等 方法定义以及...
  • 计算一堆(术语叫做sigma point),通过一定的手段产生的这些sigma能够代表当前的分布,然后将这些通过非线性函数(处理模型)变换成一些新的,然后基于这些新的sigma计算出一个高斯分布(带有权重地计算...
  • 水波模拟算法

    千次阅读 2015-10-03 07:08:35
    之所以从干扰向外扩散,是因为内部的各能量互相抵消而看不到震荡。重要的是,每个都在以自己为中心进行震荡,并向四周扩散能量。 衰减:水波在传播过程中能量会逐渐的衰减,因为水的震荡是有阻尼的。 折
  • 转自网易博客:... ... 高斯函数在图像增强中起到什么作用,麻烦具体,就比如傅立叶变化在图像增强中可以有去除噪声的作用 主要是平滑图像~~~
  • 一:频率上限(即最高可... ②:要知道一个采样正弦的频率,那么我们至少要在半个周期内有两个采样(香农采样定理) 结合上面两个前提可以列式:tn+1 - tn = 0.5 Tmin ,其中tn+1和tn表示前一个采样时刻和...
  • Python之小分析

    万次阅读 2018-01-08 18:54:11
    讲小的原理讲解得还不错,我实际中运用了小分解对于我已有的波形进行了一个实际的操作。由于只学过基本的信号知识,对于信号基本不太理解,所以只能从运用上面直观的讲解。 小顾名思义就是一个很小的,其...
  • 2012毕业工作记录点滴

    万次阅读 多人点赞 2011-10-25 22:40:00
    从2011年9月18日工作至今,一个多月的奔波总算告一段落,签了经过综合考虑,自己还算比较满意的公司,除此外,手里也拿了若干个offer, 相对于其它同学来说,或许可以称得“小牛”的称号。几年的辛苦与汗水在这一...
  • PCL 几种滤波方法

    万次阅读 多人点赞 2018-07-19 10:51:09
    在获取点云数据时,由于设备精度、操作者经验、环境因素等带来的影响,以及电磁衍射特性、被测物体表面性质变化和数据拼接配准操作过程的影响,点云数据中将不可避免地出现一些噪声,属于随机误差。除此之外,...
  • 可是这样的题目并不常见,一次见到是什么时候我已经不记得了,昨天,一道让人忍不住叫好的作业题目摆在我的面前。先看题目,是某大学大四学生的课程作业:-------题目Heart Beat Period Detecti...
  • 中值滤波matlab

    万次阅读 多人点赞 2016-04-07 09:13:30
    (4) 出排在中间的一个值; (5) 将这个中间值赋给对应模板中心位置的像素。 中值滤波的输出像素是由领域图像的中间值决定的,因而中值滤波对极限像素值(与周围像素灰度值差别较大的像素)远不如平均值那么...
  • 图像处理之Mean Shift滤波(边缘保留的低通滤波)

    万次阅读 热门讨论 2012-11-22 23:27:53
     本文Mean Shift滤波在YIQ颜色空间完成,关于RGB与YIQ颜色空间转换可以参考 这里: http://en.wikipedia.org/wiki/YIQ 我google来的转换公式截屏: 三:程序效果 滤镜源代码: ...
  • 水波的模拟

    千次阅读 2015-10-03 07:22:20
    (精品技术文摘)水波的模拟 original writer:Imagic 2001-3-5 序(by EmilMatthew):这是一篇非常老的技术文档,但是时间的流逝却无法...现在,用baidu搜水波摸拟之类已不到这篇文章了,故转载之,以分享精品。 KEY
  • stm32简易示器(标准库)

    万次阅读 多人点赞 2020-02-16 11:59:28
    此项案例是基于正点原子精英板制作的一个简易示器,可以读取信号的频率和幅值,并可以通过按键改变采样频率和控制屏幕的更新暂停。也是通过学习网上大佬的经验加以改编。下面将介绍所用到的基本原理以及相关代码的...
  • 傅里叶变换和滤波

    千次阅读 2019-10-25 10:04:50
    傅里叶变换就是将实域响应转换成频域的转换。傅立叶变换就是把一个信号,分解成无数的...换的目的就是出这些基本正弦(余弦)信号中振幅较大(能量较高)信号对应的频率,从而出杂乱无章的信号中的主要振动频 ...
  • MATLAB--数字图像处理 中值滤波

    万次阅读 多人点赞 2019-09-14 16:23:46
    中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,中值滤波的基本原理是把数字图像或数字序列中一点的值用该的一个邻域中各值的中值代替,让周围的像素值接近的真实值,从而消除孤立的噪声...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 73,797
精华内容 29,518
关键字:

上波找点