2019-02-22 10:29:28 qq_34725005 阅读数 112
  • OpenCV图像分割实战视频教程

    基于OpenCV新版本3.2 讲述,详细解释了KMeans、高斯混合模型(GMM)、分水岭变换、Grabcut等算法基本原理与在图像分割中的应用,基于OpenCV相关API演示每种图像分割方法,通过证件照背景融合替换与视频背景融合替换两个真实案例,讲述了图像分割在实际应用场景中的实现与演示。

    2609 人正在学习 去看看 贾志刚

高斯模糊(高斯平滑)通常用来减少图像噪声以及降低细节层次. 这种模糊技术生成的图像, 其视觉效果就像是经过一个半透明屏幕在观察图像, 这与镜头焦外成像效果散景以及普通照明阴影中的效果都明显不同. 高斯平滑也用于计算机视觉算法中的预先处理阶段, 以增强图像在不同比例大小下的图像效果(参见尺度空间表示以及尺度空间实现). 从数学的角度来看, 图像的高斯模糊过程就是图像与正态分布做卷积. 由于正态分布又叫作高斯分布, 所以这项技术就叫作高斯模糊. 图像与圆形方框模糊做卷积将会生成更加精确的焦外成像效果. 由于高斯函数的傅立叶变换是另外一个高斯函数, 所以高斯模糊对于图像来说就是一个低通滤波器.

机理

高斯模糊是一种图像模糊滤波器, 它用正态分布计算图像中每个像素的变换. N维空间正态分布方程为
G(r)=12πσ2Ner22σ2G(r)=\frac{1}{\sqrt {2πσ^2}^N}e^{\frac{-r^2}{2σ^2}}
在二维空间定义为
G(r)=12πσ2e(u2+v2)2σ2G(r)=\frac{1}{2πσ^2}e^{\frac{-(u^2+v^2)}{2σ^2}}
其中 r 是模糊半径r2=u2+v2r^2=u^2+v^2, σ 是正态分布的标准偏差. 在二维空间中, 这个公式生成的曲面的等高线是从中心开始呈正态分布的同心圆. 分布不为零的像素组成的卷积矩阵与原始图像做变换. 每个像素的值都是周围相邻像素值的加权平均. 原始像素的值有最大的高斯分布值, 所以有最大的权重, 相邻像素随着距离原始像素越来越远, 其权重也越来越小. 这样进行模糊处理比其它的均衡模糊滤波器更高地保留了边缘效果.

import math
import numpy as np
import scipy.signal
import cv2

def get_cv(r, sigma):
    return 1 / (2 * math.pi * sigma ** 2) * math.exp((-r ** 2) / (2 * sigma ** 2))

def get_kernel():
    radius, sigma = 2, 1.5
    kernel = np.zeros((radius * 2 + 1, radius * 2 + 1))
    for i in range(-radius, radius + 1):
        for j in range(-radius, radius + 1):
            r = (i ** 2 + j ** 2) ** 0.5
            kernel[i + radius][j + radius] = get_cv(r, sigma)
    return kernel / np.sum(kernel)

def convert_2d(r):
    kernel = get_kernel()
    s = scipy.signal.convolve2d(r,kernel,mode='same',boundary='symm')
    return s.astype(np.uint8)

def convert_3d(r):
    s_dsplit = []
    for d in range(r.shape[2]):
        rr = r[:,:,d]
        ss = convert_2d(rr)
        s_dsplit.append(ss)
    s = np.dstack(s_dsplit)
    return s

im = cv2.imread('tetet.jpg')
im_convert_mat = convert_3d(im)
cv2.imshow('gaosi',im_convert_mat)
cv2.imwrite('gaosi.jpg',im_convert_mat)
cv2.waitKey()

在这里插入图片描述
在这里插入图片描述

2015-04-21 12:55:30 smtctc 阅读数 4060
  • OpenCV图像分割实战视频教程

    基于OpenCV新版本3.2 讲述,详细解释了KMeans、高斯混合模型(GMM)、分水岭变换、Grabcut等算法基本原理与在图像分割中的应用,基于OpenCV相关API演示每种图像分割方法,通过证件照背景融合替换与视频背景融合替换两个真实案例,讲述了图像分割在实际应用场景中的实现与演示。

    2609 人正在学习 去看看 贾志刚

JAVA图像处理——高斯模糊

高斯模糊:
高斯模糊简单的说就是让图像的像素点取周围的像素点的平均,达到令图片模糊的效果。
当然,简单的取平均值是不太好的,因为一般与像素点距离近的像素点他们的颜色更接近,距离远的颜色偏离更大,所以可以采用正态分布曲线来取权重。
正态分布的曲线如下图:
这里写图片描述
正好符合中间点权重最高,距离中间点越远距离越低的效果,而且过度很平滑(个人这么认为)。
我们需要2维的正态分布函数,如下图:
这里写图片描述
sigma是方差,从方差的定义我们大概能推测方差越大,图像模糊的越厉害,事实也是这样。
接下来我们要决定应该取一个像素周围多少范围内的像素点来参与高斯权重值得计算呢?
我们取6sigma+1,因为大于6sigma+1的正态分布函数值(也就是权重)太小了,几乎可以忽略不计了。
接下来我们可以计算我们的高斯权重矩阵了。我们用一个二维数组来保存这些权重值。
例如我们只取周围距离一个像素的点来算平均值的画就如下图所示:
高斯权重二维矩阵
每个格子都是一个像素,对应二维矩阵内的就是当前位置像素的权重值,中间红格子是当前要计算的像素,他的颜色值=周围所有像素的 权重*颜色值之和。
根据上面的正态分布函数公式,我们写出了下面的方法求这个二维权重矩阵的所有值。

 private static float[][] getGaos(float sigma) {
        int size = (int) (6*sigma)+1;
        if(size%2==0) {
            size++;
        }
        float[][] res = new float[size][size];
        for(int y=0;y<size;y++)
            for(int x=0;x<size;x++){
                 float zhishu = -1*(((x-size/2)*(x-size/2))+((y-size/2)*(y-size/2)))/(2*sigma*sigma);
                 float a = (float) (1.0f/(2.0f*Math.PI*sigma*sigma));
                 res[x][y] = (float) (a*Math.pow(Math.E, zhishu));
                }
        return res;
    }

然后根据权重矩阵计算各个点的像素颜色值就可以了。
下面是效果图:
原图
模糊图
最后要注意边界的矩阵取不到全部的像素值时只要取能取到的值就可以了。
如果还不明白的话这里也有讲,我也是从这里参考来的:
http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html

2015-12-17 16:49:24 liushaofang 阅读数 565
  • OpenCV图像分割实战视频教程

    基于OpenCV新版本3.2 讲述,详细解释了KMeans、高斯混合模型(GMM)、分水岭变换、Grabcut等算法基本原理与在图像分割中的应用,基于OpenCV相关API演示每种图像分割方法,通过证件照背景融合替换与视频背景融合替换两个真实案例,讲述了图像分割在实际应用场景中的实现与演示。

    2609 人正在学习 去看看 贾志刚

对图像进行高斯模糊的处理类,实际应用效果不错!!!

package util;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Build.VERSION;
import android.renderscript.Allocation;
import android.renderscript.Allocation.MipmapControl;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
import java.lang.reflect.Array;

public class Blur
{
  private static final String TAG = "Blur";

  @SuppressLint({"NewApi"})
  public static Bitmap fastblur(Context paramContext, Bitmap paramBitmap, int paramInt)
  {
    if (Build.VERSION.SDK_INT > 16)
    {
      Bitmap localBitmap2 = paramBitmap.copy(paramBitmap.getConfig(), true);
      RenderScript localRenderScript = RenderScript.create(paramContext);
      Allocation localAllocation1 = Allocation.createFromBitmap(localRenderScript, paramBitmap, Allocation.MipmapControl.MIPMAP_NONE, 1);
      Allocation localAllocation2 = Allocation.createTyped(localRenderScript, localAllocation1.getType());
      ScriptIntrinsicBlur localScriptIntrinsicBlur = ScriptIntrinsicBlur.create(localRenderScript, Element.U8_4(localRenderScript));
      localScriptIntrinsicBlur.setRadius(paramInt);
      localScriptIntrinsicBlur.setInput(localAllocation1);
      localScriptIntrinsicBlur.forEach(localAllocation2);
      localAllocation2.copyTo(localBitmap2);
      return localBitmap2;
    }
    Bitmap localBitmap1 = paramBitmap.copy(paramBitmap.getConfig(), true);
    if (paramInt < 1)
      return null;
    int i = localBitmap1.getWidth();
    int j = localBitmap1.getHeight();
    int[] arrayOfInt1 = new int[i * j];
    localBitmap1.getPixels(arrayOfInt1, 0, i, 0, 0, i, j);
    int k = i - 1;
    int m = j - 1;
    int n = i * j;
    int i1 = 1 + (paramInt + paramInt);
    int[] arrayOfInt2 = new int[n];
    int[] arrayOfInt3 = new int[n];
    int[] arrayOfInt4 = new int[n];
    int[] arrayOfInt5 = new int[Math.max(i, j)];
    int i2 = i1 + 1 >> 1;
    int i3 = i2 * i2;
    int[] arrayOfInt6 = new int[i3 * 256];
    for (int i4 = 0; ; i4++)
    {
      int i5 = i3 * 256;
      if (i4 >= i5)
        break;
      arrayOfInt6[i4] = (i4 / i3);
    }
    int i6 = 0;
    int i7 = 0;
    int[] arrayOfInt7 = { i1, 3 };
    int[][] arrayOfInt = (int[][])Array.newInstance(Integer.TYPE, arrayOfInt7);
    int i8 = paramInt + 1;
    for (int i9 = 0; i9 < j; i9++)
    {
      int i37 = 0;
      int i38 = 0;
      int i39 = 0;
      int i40 = 0;
      int i41 = 0;
      int i42 = 0;
      int i43 = 0;
      int i44 = 0;
      int i45 = 0;
      int i46 = -paramInt;
      if (i46 <= paramInt)
      {
        int i59 = arrayOfInt1[(i6 + Math.min(k, Math.max(i46, 0)))];
        int[] arrayOfInt13 = arrayOfInt[(i46 + paramInt)];
        arrayOfInt13[0] = ((0xFF0000 & i59) >> 16);
        arrayOfInt13[1] = ((0xFF00 & i59) >> 8);
        arrayOfInt13[2] = (i59 & 0xFF);
        int i60 = i8 - Math.abs(i46);
        i39 += i60 * arrayOfInt13[0];
        i38 += i60 * arrayOfInt13[1];
        i37 += i60 * arrayOfInt13[2];
        if (i46 > 0)
        {
          i45 += arrayOfInt13[0];
          i44 += arrayOfInt13[1];
          i43 += arrayOfInt13[2];
        }
        while (true)
        {
          i46++;
          break;
          i42 += arrayOfInt13[0];
          i41 += arrayOfInt13[1];
          i40 += arrayOfInt13[2];
        }
      }
      int i47 = paramInt;
      for (int i48 = 0; i48 < i; i48++)
      {
        arrayOfInt2[i6] = arrayOfInt6[i39];
        arrayOfInt3[i6] = arrayOfInt6[i38];
        arrayOfInt4[i6] = arrayOfInt6[i37];
        int i49 = i39 - i42;
        int i50 = i38 - i41;
        int i51 = i37 - i40;
        int[] arrayOfInt11 = arrayOfInt[((i1 + (i47 - paramInt)) % i1)];
        int i52 = i42 - arrayOfInt11[0];
        int i53 = i41 - arrayOfInt11[1];
        int i54 = i40 - arrayOfInt11[2];
        if (i9 == 0)
          arrayOfInt5[i48] = Math.min(1 + (i48 + paramInt), k);
        int i55 = arrayOfInt1[(i7 + arrayOfInt5[i48])];
        arrayOfInt11[0] = ((0xFF0000 & i55) >> 16);
        arrayOfInt11[1] = ((0xFF00 & i55) >> 8);
        arrayOfInt11[2] = (i55 & 0xFF);
        int i56 = i45 + arrayOfInt11[0];
        int i57 = i44 + arrayOfInt11[1];
        int i58 = i43 + arrayOfInt11[2];
        i39 = i49 + i56;
        i38 = i50 + i57;
        i37 = i51 + i58;
        i47 = (i47 + 1) % i1;
        int[] arrayOfInt12 = arrayOfInt[(i47 % i1)];
        i42 = i52 + arrayOfInt12[0];
        i41 = i53 + arrayOfInt12[1];
        i40 = i54 + arrayOfInt12[2];
        i45 = i56 - arrayOfInt12[0];
        i44 = i57 - arrayOfInt12[1];
        i43 = i58 - arrayOfInt12[2];
        i6++;
      }
      i7 += i;
    }
    for (int i10 = 0; i10 < i; i10++)
    {
      int i11 = 0;
      int i12 = 0;
      int i13 = 0;
      int i14 = 0;
      int i15 = 0;
      int i16 = 0;
      int i17 = 0;
      int i18 = 0;
      int i19 = 0;
      int i20 = i * -paramInt;
      int i21 = -paramInt;
      if (i21 <= paramInt)
      {
        int i35 = i10 + Math.max(0, i20);
        int[] arrayOfInt10 = arrayOfInt[(i21 + paramInt)];
        arrayOfInt10[0] = arrayOfInt2[i35];
        arrayOfInt10[1] = arrayOfInt3[i35];
        arrayOfInt10[2] = arrayOfInt4[i35];
        int i36 = i8 - Math.abs(i21);
        i13 += i36 * arrayOfInt2[i35];
        i12 += i36 * arrayOfInt3[i35];
        i11 += i36 * arrayOfInt4[i35];
        if (i21 > 0)
        {
          i19 += arrayOfInt10[0];
          i18 += arrayOfInt10[1];
          i17 += arrayOfInt10[2];
        }
        while (true)
        {
          if (i21 < m)
            i20 += i;
          i21++;
          break;
          i16 += arrayOfInt10[0];
          i15 += arrayOfInt10[1];
          i14 += arrayOfInt10[2];
        }
      }
      int i22 = i10;
      int i23 = paramInt;
      for (int i24 = 0; i24 < j; i24++)
      {
        arrayOfInt1[i22] = (0xFF000000 & arrayOfInt1[i22] | arrayOfInt6[i13] << 16 | arrayOfInt6[i12] << 8 | arrayOfInt6[i11]);
        int i25 = i13 - i16;
        int i26 = i12 - i15;
        int i27 = i11 - i14;
        int[] arrayOfInt8 = arrayOfInt[((i1 + (i23 - paramInt)) % i1)];
        int i28 = i16 - arrayOfInt8[0];
        int i29 = i15 - arrayOfInt8[1];
        int i30 = i14 - arrayOfInt8[2];
        if (i10 == 0)
          arrayOfInt5[i24] = (i * Math.min(i24 + i8, m));
        int i31 = i10 + arrayOfInt5[i24];
        arrayOfInt8[0] = arrayOfInt2[i31];
        arrayOfInt8[1] = arrayOfInt3[i31];
        arrayOfInt8[2] = arrayOfInt4[i31];
        int i32 = i19 + arrayOfInt8[0];
        int i33 = i18 + arrayOfInt8[1];
        int i34 = i17 + arrayOfInt8[2];
        i13 = i25 + i32;
        i12 = i26 + i33;
        i11 = i27 + i34;
        i23 = (i23 + 1) % i1;
        int[] arrayOfInt9 = arrayOfInt[i23];
        i16 = i28 + arrayOfInt9[0];
        i15 = i29 + arrayOfInt9[1];
        i14 = i30 + arrayOfInt9[2];
        i19 = i32 - arrayOfInt9[0];
        i18 = i33 - arrayOfInt9[1];
        i17 = i34 - arrayOfInt9[2];
        i22 += i;
      }
    }
    localBitmap1.setPixels(arrayOfInt1, 0, i, 0, 0, i, j);
    return localBitmap1;
  }
}
2018-08-20 14:16:47 qinghuaci666 阅读数 1672
  • OpenCV图像分割实战视频教程

    基于OpenCV新版本3.2 讲述,详细解释了KMeans、高斯混合模型(GMM)、分水岭变换、Grabcut等算法基本原理与在图像分割中的应用,基于OpenCV相关API演示每种图像分割方法,通过证件照背景融合替换与视频背景融合替换两个真实案例,讲述了图像分割在实际应用场景中的实现与演示。

    2609 人正在学习 去看看 贾志刚

转自:1.高斯模糊的算法:http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html

 

通常,图像处理软件会提供"模糊"(blur)滤镜,使图片产生模糊的效果。

 

"模糊"的算法有很多种,其中有一种叫做"高斯模糊"(Gaussian Blur)。它将正态分布(又名"高斯分布")用于图像处理。

本文介绍"高斯模糊"的算法,你会看到这是一个非常简单易懂的算法。本质上,它是一种数据平滑技术(data smoothing),适用于多个场合,图像处理恰好提供了一个直观的应用实例。

一、高斯模糊的原理

所谓"模糊",可以理解成每一个像素都取周边像素的平均值。

上图中,2是中间点,周边点都是1。

"中间点"取"周围点"的平均值,就会变成1。在数值上,这是一种"平滑化"。在图形上,就相当于产生"模糊"效果,"中间点"失去细节。

显然,计算平均值时,取值范围越大,"模糊效果"越强烈。

上面分别是原图、模糊半径3像素、模糊半径10像素的效果。模糊半径越大,图像就越模糊。从数值角度看,就是数值越平滑。

接下来的问题就是,既然每个点都要取周边像素的平均值,那么应该如何分配权重呢?

如果使用简单平均,显然不是很合理,因为图像都是连续的,越靠近的点关系越密切,越远离的点关系越疏远。因此,加权平均更合理,距离越近的点权重越大,距离越远的点权重越小。

二、正态分布的权重

正态分布显然是一种可取的权重分配模式。

在图形上,正态分布是一种钟形曲线,越接近中心,取值越大,越远离中心,取值越小。

计算平均值的时候,我们只需要将"中心点"作为原点,其他点按照其在正态曲线上的位置,分配权重,就可以得到一个加权平均值。

三、高斯函数

上面的正态分布是一维的,图像都是二维的,所以我们需要二维的正态分布。

正态分布的密度函数叫做"高斯函数"(Gaussian function)。它的一维形式是:

其中,μ是x的均值,σ是x的方差。因为计算平均值的时候,中心点就是原点,所以μ等于0。

根据一维高斯函数,可以推导得到二维高斯函数:

有了这个函数 ,就可以计算每个点的权重了。

四、权重矩阵

假定中心点的坐标是(0,0),那么距离它最近的8个点的坐标如下:

更远的点以此类推。

为了计算权重矩阵,需要设定σ的值。假定σ=1.5,则模糊半径为1的权重矩阵如下:

这9个点的权重总和等于0.4787147,如果只计算这9个点的加权平均,还必须让它们的权重之和等于1,因此上面9个值还要分别除以0.4787147,得到最终的权重矩阵。

五、计算高斯模糊

有了权重矩阵,就可以计算高斯模糊的值了。

假设现有9个像素点,灰度值(0-255)如下:

每个点乘以自己的权重值:

得到

将这9个值加起来,就是中心点的高斯模糊的值。

对所有点重复这个过程,就得到了高斯模糊后的图像。如果原图是彩色图片,可以对RGB三个通道分别做高斯模糊。

六、边界点的处理

如果一个点处于边界,周边没有足够的点,怎么办?

一个变通方法,就是把已有的点拷贝到另一面的对应位置,模拟出完整的矩阵。

参考文献

1.高斯模糊的算法:http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html

2.How to program a Gaussian Blur without using 3rd party libraries

 

2016-07-21 13:49:27 u013718120 阅读数 1620
  • OpenCV图像分割实战视频教程

    基于OpenCV新版本3.2 讲述,详细解释了KMeans、高斯混合模型(GMM)、分水岭变换、Grabcut等算法基本原理与在图像分割中的应用,基于OpenCV相关API演示每种图像分割方法,通过证件照背景融合替换与视频背景融合替换两个真实案例,讲述了图像分割在实际应用场景中的实现与演示。

    2609 人正在学习 去看看 贾志刚

高斯模糊想必大家都听说过,百度百科对于高斯模糊的解释为:

高斯模糊(英语:Gaussian Blur),也叫高斯平滑,是在Adobe PhotoshopGIMP以及Paint.NET图像处理软件中广泛使用的处理效果,通常用它来减少图像噪声以及降低细节层次。所谓"模糊",可以理解成每一个像素都取周边像素的平均值。

在Android中实现快速高斯模糊,我们采用StackBlur开源的FastBlur。使用该方法时,如果我们传入的Bitmap过大可能会导致内存oom。所以,我们需要对图片进行一些操作。常见的方法是缩放图片或者裁剪图片。

BitmapFactory为我们提供一个缩放的函数:createScaledBitmap。那么我们就可以使用该函数对图片进行缩放,然后实现高斯模糊。

该方式的优点:

(1)有利于减少内存的占用(图片变小)。

(2)更加利于图片的模糊度。模糊处理时间变短。

下面来看今天的效果,带给你们一只美美的妹子:

这就是利用高斯模糊的原理做成的,是不是非常赞!

总结:核心原理就是利用FastBlur的doBlur算法,然后对原图进行相应的处理就可以搞定啦!

好了,下面我贴出一个StackBlur的体验链接,大家可以亲身体会高斯模糊多带来的魅力,OK,今天的内容就到这里,thks~

StackBlurForCanvas

源码下载




高斯模糊算法

阅读数 226

图像中的高斯模糊

阅读数 782

高斯模糊

阅读数 730

没有更多推荐了,返回首页