2018-11-19 15:49:46 weixin_39121325 阅读数 101
  • 学习OpenCV3.2+QT5+ffmpeg实战开发视频编辑视频教程

    OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现),双线性插值,图像金字塔)、颜色格式(灰度图,二值化(阈值)),旋转镜像,视频裁剪(ROI),视频水印(ROI+weight),导出处理后的视频(包含音频,使用ffmpeg工具对音频进行抽取、剪切和终于opencv处理的视频合并)。

    19573 人正在学习 去看看 夏曹俊

     滤波器在图像处理中的应用非常广泛,OpenCV也有个直接使用滤波器掩码(核)的函数filter2D,将图像与核进行卷积运算得到目标图像。卷积是在每一个图像块与某个算子(核)之间进行的运算,而核就是一个固定大小的数值数组。

     实际上,在OpenCV中很多算法都是用卷积实现的,包括一些边缘检测的算法。本文无意列举这些算法的原理,仅仅是考察一下OpenCV的实现,再尝试用Python调用这些算法,看看其效果。


 直接利用 filter2D得到图片的滤波

# -*- coding: utf-8 -*-
# !/usr/bin/env python
# @Time    : 2018/11/19 15:42
# @Author  : xhh
# @Desc    : 图片滤波器
# @File    : opencv_filterImg.py
# @Software: PyCharm
import cv2
import numpy as np

# filter2D
img = cv2.imread('../tupian/green.png')
cv2.imshow('src', img)

 # 直接给出图片的滤波矩阵
kernel = np.array([ [-1, -1, -1],
                    [-1,  8, -1],
                    [-1, -1, -1] ])

filter_dst = cv2.filter2D(img, -1, kernel)

cv2.imshow('dst', filter_dst)
cv2.waitKey(0)

结果:

        

 

2015-06-04 23:59:42 u014030117 阅读数 14330
  • 学习OpenCV3.2+QT5+ffmpeg实战开发视频编辑视频教程

    OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现),双线性插值,图像金字塔)、颜色格式(灰度图,二值化(阈值)),旋转镜像,视频裁剪(ROI),视频水印(ROI+weight),导出处理后的视频(包含音频,使用ffmpeg工具对音频进行抽取、剪切和终于opencv处理的视频合并)。

    19573 人正在学习 去看看 夏曹俊

注:本系列来自于图像处理课程实验,用Matlab实现最基本的图像处理算法

本文章是Matlab图像处理系列的第二篇文章,介绍了空间域图像处理最基本的概念————模版和滤波器,给出了均值滤波起和中值滤波器的Matlab实现,最后简要讨论去躁效果。


1.空间域增强

(1)模版运算

图像处理中,模版可以看作是n*n(n一般是奇数)的窗口,模版连续地运动于整个图像中,对模版窗口范围内的像素做相应处理。

模版运算主要分为:

  • 模版卷积
  • 模版排序

模版卷积是把模版内像素的灰度值和模版中对应的灰度值相乘,求平均值赋给当前模版窗口的中心像素,作为它的灰度值;

模版排序是把模版内像素的灰度值排序,取某个顺序统计量作为模版中心像素灰度值。

Matlab中做模版卷积十分高效,取出模版内子矩阵和模版权重点乘求平均即可

我们很容易想到模版的中心点是边界的特殊情况,处理边界有很多种做法:

  • 忽略边界
  • 外插边界
  • 改变模版领域

忽略边界是模版直接在非边界点运动操作,直接忽略这些边界点。这么做的好处当然是效率高,比较适合图像尺寸较大或人们感兴趣部分不在图像边缘的情况;

外插边界顾名思义就是补齐边界点作为模版中心时缺失的像素部分,可以赋予补边像素一定的灰度值并作计算。优点在于不牺牲性能的情况下,对边界进行了处理,但是补边像素的灰度值设定势必导致边界的像素点的不连贯性,严重情况下导致失真;

改变模版领域是指在边界处理中改变模版窗口的大小,为边界做特殊处理,如3*3模版在处理最左上角像素点时只考虑图像内点2*2的模版运算。这样为边界特殊考虑既不失真又没有忽略任何像素点,但是在判断边界时势必会产生一定的开销,略微会影响图像处理的性能(可以分情况写,在牺牲程序复杂度的情况下弥补判断带来的开销)。

任何的边界处理都不是完美的,都在一定程度上重新分配了模版权重。

(2)空间域滤波

把模版运算运用于图像的空间域增强的技术称为空间域滤波,根据滤波频率空间域滤波分为平滑滤波(减弱和去除高频分量)和锐化滤波(减弱和去除低频分量),根据滤波计算特点又分为线性滤波非线性滤波

因此空间域滤波可分为:

分类 线性 非线性
平滑 线性平滑 非线性平滑
锐化 线性锐化 非线性锐化

2.均值滤波

(1)均值滤波器

领域均值滤波顾名思义是就是求模版内像素点灰度的均值,是最经典的线性平滑滤波。空域滤波常用于去除加性噪声,通常把滤波算法封装的模块称作滤波器。

均值滤波的模版就是ones(n, n),模版内所有元素均是一,即他们的权重一模一样。

其他常用的线性滤波还有:

  • 加权滤波:通常中心元素权重较大,且对称向外递减
  • 高斯滤波:加权滤波的特例,根据高斯分布确定模版系数

(2)代码实现

先调用Matlab函数给图像添加3%的椒盐噪声

salt = imnoise(original,'salt & pepper',0.03);

接下来构造我们的均值滤波器,我采用改变模版领域,也就是对边界条件判断做特殊处理:

function [ filtered ] = MeanFilter( noise )

    filtered = noise;

    h = size(filtered, 1);
    w = size(filtered, 2);

    for i = 1 : h
        for j = 1 : w
            up = max(i - 1, 1);
            down = min(i + 1, h);
            left = max(j - 1, 1);
            right = min(j + 1, w);
            filtered(i, j) = mean(mean(noise(up : down, left : right)));
        end
    end

end

这里我调用了一系列的maxmin函数避免写起来比较繁杂的if语句,确定了模版边界后直接调用mean函数求均值,淡化了模版卷积的概念(后面边缘检测中会显式地做模版卷积)。

3.中值滤波

(1)中值滤波器

中值滤波选取模版中像素灰度值的中位数赋给模版中心像素,是经典的非线性平滑滤波。理想情况下,中值滤波的椒盐去噪效果优于均值滤波,是因为它能有效的消除孤立阶跃脉冲噪声,后面将比较分析。

2-D中值滤波也可以选取各种各样的模版,我在这里就选取最简单的8-领域模版做演示。

(2)代码实现

同样我检测边界,做特殊处理:

function [ filtered ] = MedianFilter( noise )
    filtered = noise;

    h = size(filtered, 1);
    w = size(filtered, 2);

    for i = 1 : h
        for j = 1 : w
            up = max(i - 1, 1);
            down = min(i + 1, h);
            left = max(j - 1, 1);
            right = min(j + 1, w);
            sub = noise(up : down, left : right);
            sub = sub(:);
            filtered(i, j) = median(sub);
        end
    end

end

只需要将子矩阵转成向量,再求median即可。

注:我没有仔细研究Matlab median函数实现方式,假设它是一个平方量级的算法,那么我们有以下两种优化方式,来提升中值滤波的速度:

  • 寻求效率更高的顺序统计量算法,见算法导论——期望为线性时间的选择算法最坏情况为线性时间的选择算法
  • 利用模版移动的连续性,邻近移动区域只有少量像素点不同,可以根据模版的这个性质构造线性时间的增量式顺序统计量算法

4.两种滤波器结果对比讨论

(1)平滑结果展示

下面是椒盐噪声的去除效果,中值滤波的效果更优:

这里写图片描述

下面是高斯噪声的去除效果,均值滤波的效果更优:

这里写图片描述

(2)讨论

这里并没有数学理论的数学分析,也没有给出例子,只是从直观理解角度简要分析:

  1. 中值滤波去除椒盐效果更好,因为椒盐噪声是阶跃脉冲噪声(取值0或255且小概率出现),中值滤波是去中位数,不会被阶跃值影响,所以几乎能完全过滤掉阶跃脉冲噪声。而均值滤波处理阶跃值时分配权重不会变化,那么求平均值时受阶跃值影响而产生的误差就较大,因此效果不理想。
  2. 高斯噪声是图像中每个像素点都从原灰度值根据高斯分布做随机噪声,那么选取中值的代表意义并不大,因为各个像素都是独立同分布的。中值滤波相当于在模版内再选出了一个经过高斯噪声变换后的灰度值,滤波效果和噪声图像没有明显改善,所以比较之下均值滤波较优。
2014-01-09 10:37:18 u013371735 阅读数 2307
  • 学习OpenCV3.2+QT5+ffmpeg实战开发视频编辑视频教程

    OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现),双线性插值,图像金字塔)、颜色格式(灰度图,二值化(阈值)),旋转镜像,视频裁剪(ROI),视频水印(ROI+weight),导出处理后的视频(包含音频,使用ffmpeg工具对音频进行抽取、剪切和终于opencv处理的视频合并)。

    19573 人正在学习 去看看 夏曹俊

1. 平滑滤波器用于模糊处理和减小噪声。模糊处理经常用于预处理,例如,在提取大的目标之前去除图像中一些琐碎的细节、桥接直线或曲线的缝隙。通过线型滤波器和非线性滤波器的模糊处理可以减少噪声。

2. 平滑线性空间滤波器的输出(响应)是包含在滤波掩膜领域内像素的简单平均值。因此这些滤波器也称为均值滤波器,也指的是低通滤波器。

    平滑滤波器的概念非常直观。它用滤波掩膜确定的领域内像素的平均灰度值去代替图像每个像素点的值,这种处理减小了图像灰度的“尖锐”变化。由于典型的随机噪声由灰度级的尖锐变化组成,因此,常见的平滑处理应用就是减噪。然而,由于图像边缘也是由图像灰度尖锐变化带来的特性,所以均值滤波器处理还是存在着不希望的边缘模糊的负面效应。这里要理解这句话很重要,均值滤波器的主要应用是去除图像中的不相干的细节,其中“不相干”是指与滤波掩膜尺寸相比,较小的像素区域

3. 以3*3的平滑滤波器为例,我们一般采用两种滤波器:

   (1)系数都取1。在滤波处理之后,整个图像被9除。所有系数都相等的空间均值滤波器有时称为盒滤波器。

   (2)第二种掩膜更有价值。这个掩膜也叫做加权平均,使用这一术语是指用不同的系数乘以像素,这样,从权值上看,一些像素比另一些更为重要。

                                   

一幅M*N的图像经过一个m*n(m和n是奇数)的加权均值滤波器滤波过程可由下式给出:

                                         

3. 下面用各种尺寸的掩膜平滑图像

   这里对n*n的掩膜进行赋值,实验中别分赋予3,15来观察平滑效果,由图可以看到,到n=3时,整幅图像中有轻微的模糊,但是正如所希望的那种,当图像细节与滤波器掩膜近似相同时,图像中一些细节受到的影响比较大。咯如用3*3掩膜时,较小的字母"a"和细的科里要比图像其他部分更为模糊。一个正面的意义就体现了,对于噪声的去除作用。而在n=15时,这种极端情况下,图像已经比较模糊,但是一个作用就是去除一些小物体。

#include "dipHeader.h"

/************************************************************************/
/* 各种尺寸的均值滤波 3,5,9,16,35                                                                    */
/************************************************************************/
void main()
{
	IplImage* a = cvLoadImage("a1.tif",0);

	IplImage* a3 = cvCreateImage(cvGetSize(a),8,a->nChannels);

	cvSmooth(a, a3, CV_BLUR,3,a->nChannels);

	IplImage* a15 = cvCreateImage(cvGetSize(a),8,a->nChannels);
	
	cvSmooth(a, a15, CV_BLUR,15,15);
	cvNamedWindow("a");
	cvShowImage("a",a);

	cvNamedWindow("a3");
	cvShowImage("a3",a3);
	
	
	cvNamedWindow("a15");
	cvShowImage("a15",a15);
	cvWaitKey(0);

	cvReleaseImage(&a);
	cvReleaseImage(&a3);
	cvReleaseImage(&a15);
}

2019-03-05 18:19:13 hhaowang 阅读数 226
  • 学习OpenCV3.2+QT5+ffmpeg实战开发视频编辑视频教程

    OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现),双线性插值,图像金字塔)、颜色格式(灰度图,二值化(阈值)),旋转镜像,视频裁剪(ROI),视频水印(ROI+weight),导出处理后的视频(包含音频,使用ffmpeg工具对音频进行抽取、剪切和终于opencv处理的视频合并)。

    19573 人正在学习 去看看 夏曹俊

Table of Contents

1.常用滤波器列表:

bilateralFilter()双边滤波器

blur()平滑滤波器

boxFilter()box平滑滤波器

filter2D()图像卷积操作

GaussianBlur()高斯滤波-平滑

medainBlur()中值滤波-去噪/平滑

Laplican()拉普拉斯(二阶)微分算子

Sobel()计算一阶、二阶、高阶微分算子

2.滤波器参数及使用

bilateralFilter()

blur()平滑

boxFilter()

filter2D()

GaussianBlur()

getDerivKernels()

getGaborKernel()

getGaussianKernel()

Laplacian()

medianBlur()

Scharr()

Sobel算子

函数列表

色彩空间转换问题,请上传送门:https://blog.csdn.net/keith_bb/article/details/53470170


.常用滤波器列表:

  • bilateralFilter()双边滤波器

  • blur()平滑滤波器

  • boxFilter()box平滑滤波器

  • filter2D()图像卷积操作

  • GaussianBlur()高斯滤波-平滑

  • medainBlur()中值滤波-去噪/平滑

  • Laplican()拉普拉斯(二阶)微分算子

  • Sobel()计算一阶、二阶、高阶微分算子

2.滤波器参数及使用

bilateralFilter()

void cv::bilateralFilter ( InputArray  src,
    OutputArray  dst,
    int  d,
    double  sigmaColor,
    double  sigmaSpace,
    int  borderType = BORDER_DEFAULT 
  )    
Python:
  dst = cv.bilateralFilter( src, d, sigmaColor, sigmaSpace[, dst[, borderType]] )

该功能将双边滤波应用于输入图像,如http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html中所述,bilateralFilter可以很好地减少不需要的噪声,同时保持边缘相当清晰。但是,与大多数过滤器相比,它非常慢。

Sigma值:为简单起见,您可以将2 sigma值设置为相同。如果它们很小(<10),过滤器将没有太大的影响,而如果它们很大(> 150),它们将具有非常强烈的效果,使图像看起来“卡通”​​。

滤波器大小:大滤波器(d> 5)非常慢,因此建议对实时应用使用d = 5,对于需要大量噪声滤波的离线应用,可能需要d = 9。

此过滤器无法正常工作。

参数

SRC 源8位或浮点,1通道或3通道图像。
DST 与src具有相同大小和类型的目标映像。
d 过滤期间使用的每个像素邻域的直径。如果它是非正数,则从sigmaSpace计算。
sigmaColor 过滤颜色空间中的西格玛。参数的值越大意味着像素邻域内的更远的颜色(参见sigmaSpace)将混合在一起,从而产生更大的半等颜色区域。
sigmaSpace 在坐标空间中过滤西格玛。较大的参数值意味着只要它们的颜色足够接近,更远的像素就会相互影响(参见sigmaColor)。当d> 0时,无论sigmaSpace如何,它都指定邻域大小。否则,d与sigmaSpace成比例。
borderType 用于外推图像外部像素的边框模式

例子

#include <iostream>
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
using namespace std;
using namespace cv;
int DELAY_CAPTION = 1500;
int DELAY_BLUR = 100;
int MAX_KERNEL_LENGTH = 31;
Mat src; Mat dst;
char window_name[] = "Smoothing Demo";
int display_caption( const char* caption );
int display_dst( int delay );
int main( int argc, char ** argv )
{
    namedWindow( window_name, WINDOW_AUTOSIZE );
    const char* filename = argc >=2 ? argv[1] : "../data/lena.jpg";
    src = imread( filename, IMREAD_COLOR );
    if(src.empty())
    {
        printf(" Error opening image\n");
        printf(" Usage: ./Smoothing [image_name -- default ../data/lena.jpg] \n");
        return -1;
    }
    if( display_caption( "Original Image" ) != 0 )
    {
        return 0;
    }
    dst = src.clone();
    if( display_dst( DELAY_CAPTION ) != 0 )
    {
        return 0;
    }
    if( display_caption( "Homogeneous Blur" ) != 0 )
    {
        return 0;
    }
    for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
    {
        blur( src, dst, Size( i, i ), Point(-1,-1) );
        if( display_dst( DELAY_BLUR ) != 0 )
        {
            return 0;
        }
    }
    if( display_caption( "Gaussian Blur" ) != 0 )
    {
        return 0;
    }
    for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
    {
        GaussianBlur( src, dst, Size( i, i ), 0, 0 );
        if( display_dst( DELAY_BLUR ) != 0 )
        {
            return 0;
        }
    }
    if( display_caption( "Median Blur" ) != 0 )
    {
        return 0;
    }
    for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
    {
        medianBlur ( src, dst, i );
        if( display_dst( DELAY_BLUR ) != 0 )
        {
            return 0;
        }
    }
    if( display_caption( "Bilateral Blur" ) != 0 )
    {
        return 0;
    }
    for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
    {
        bilateralFilter ( src, dst, i, i*2, i/2 );
        if( display_dst( DELAY_BLUR ) != 0 )
        {
            return 0;
        }
    }
    display_caption( "Done!" );
    return 0;
}
int display_caption( const char* caption )
{
    dst = Mat::zeros( src.size(), src.type() );
    putText( dst, caption,
             Point( src.cols/4, src.rows/2),
             FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255) );
    return display_dst(DELAY_CAPTION);
}
int display_dst( int delay )
{
    imshow( window_name, dst );
    int c = waitKey ( delay );
    if( c >= 0 ) { return -1; }
    return 0;
}

blur()平滑

Blurs an image using the normalized box filter.

The function smooths an image using the kernel:

The call blur(src, dst, ksize, anchor, borderType) is equivalent to 

boxFilter(src, dst, src.type(), anchor, true, borderType).

C++实例

/* This program demonstrates usage of the Canny edge detector */

/* include related packages */
#include "opencv2/core/utility.hpp"  
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <stdio.h>


using namespace cv;  //namesapce cv
using namespace std;  //standard namespace std

int edgeThresh = 1;
int edgeThreshScharr=1;
cv::Mat image, gray, blurImage, edge1, edge2, cedge;
const char* window_name1 = "Edge map : Canny default (Sobel gradient)";
const char* window_name2 = "Edge map : Canny with custom gradient (Scharr)";

static void onTrackbar(int, void*)
{/* define a trackbar callback, by using onTrackbar function*/
    blur(gray, blurImage, Size(3,3));
    // Run the edge detector on grayscale
    Canny(blurImage, edge1, edgeThresh, edgeThresh*3, 3);
    cedge = Scalar::all(0);
    image.copyTo(cedge, edge1);
    imshow(window_name1, cedge);
    Mat dx,dy;
    Scharr(blurImage,dx,CV_16S,1,0);
    Scharr(blurImage,dy,CV_16S,0,1);
    Canny( dx,dy, edge2, edgeThreshScharr, edgeThreshScharr*3 );
    cedge = Scalar::all(0);
    image.copyTo(cedge, edge2);
    imshow(window_name2, cedge);
}//onTrackbar

static void help()
{ /* help and info display */
    cout<<"\nThis sample demonstrates Canny edge detection\n"
        <<"Call:\n"
        <<"    /.edge [image_name -- Default is ../data/fruits.jpg]\n"<<endl;
}//help

const char* keys =
{
    "{help h||}{@image |../data/fruits.jpg|input image name}"
};

int main( int argc, const char** argv )
{
/*  the main funciton */

    help();
    CommandLineParser parser(argc, argv, keys);
    string filename = parser.get<string>(0);
    image = imread(filename, IMREAD_COLOR);

    if(image.empty()) // open file check
    {
        cout<<"Cannot read image file: "
            << filename.c_str()<<endl;
        help();
        return -1;
    }
    cedge.create(image.size(), image.type());
    cvtColor(image, gray, COLOR_BGR2GRAY);
    // Create a window
    namedWindow(window_name1, 1);
    namedWindow(window_name2, 1);
    // create a toolbar
    createTrackbar("Canny threshold default", window_name1, &edgeThresh, 100, onTrackbar);
    createTrackbar("Canny threshold Scharr", window_name2, &edgeThreshScharr, 400, onTrackbar);
    // Show the image
    onTrackbar(0, 0);
    // Wait for a key stroke; the same function arranges events processing
    waitKey(0);
    return 0;
}

An example using drawContours to clean up a background segmentation result

#include "opencv2/imgproc.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/video/background_segm.hpp"
#include <stdio.h>
#include <string>
using namespace std;
using namespace cv;
static void help()
{
    printf("\n"
            "This program demonstrated a simple method of connected components clean up of background subtraction\n"
            "When the program starts, it begins learning the background.\n"
            "You can toggle background learning on and off by hitting the space bar.\n"
            "Call\n"
            "./segment_objects [video file, else it reads camera 0]\n\n");
}
static void refineSegments(const Mat& img, Mat& mask, Mat& dst)
{
    int niters = 3;
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;
    Mat temp;
    dilate(mask, temp, Mat(), Point(-1,-1), niters);
    erode(temp, temp, Mat(), Point(-1,-1), niters*2);
    dilate(temp, temp, Mat(), Point(-1,-1), niters);
    findContours( temp, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE );
    dst = Mat::zeros(img.size(), CV_8UC3);
    if( contours.size() == 0 )
        return;
    // iterate through all the top-level contours,
    // draw each connected component with its own random color
    int idx = 0, largestComp = 0;
    double maxArea = 0;
    for( ; idx >= 0; idx = hierarchy[idx][0] )
    {
        const vector<Point>& c = contours[idx];
        double area = fabs(contourArea(Mat(c)));
        if( area > maxArea )
        {
            maxArea = area;
            largestComp = idx;
        }
    }
    Scalar color( 0, 0, 255 );
    drawContours( dst, contours, largestComp, color, FILLED, LINE_8, hierarchy );
}
int main(int argc, char** argv)
{
    VideoCapture cap;
    bool update_bg_model = true;
    CommandLineParser parser(argc, argv, "{help h||}{@input||}");
    if (parser.has("help"))
    {
        help();
        return 0;
    }
    string input = parser.get<std::string>("@input");
    if (input.empty())
        cap.open(0);
    else
        cap.open(input);
    if( !cap.isOpened() )
    {
        printf("\nCan not open camera or video file\n");
        return -1;
    }
    Mat tmp_frame, bgmask, out_frame;
    cap >> tmp_frame;
    if(tmp_frame.empty())
    {
        printf("can not read data from the video source\n");
        return -1;
    }
    namedWindow("video", 1);
    namedWindow("segmented", 1);
    Ptr<BackgroundSubtractorMOG2> bgsubtractor=createBackgroundSubtractorMOG2();
    bgsubtractor->setVarThreshold(10);
    for(;;)
    {
        cap >> tmp_frame;
        if( tmp_frame.empty() )
            break;
        bgsubtractor->apply(tmp_frame, bgmask, update_bg_model ? -1 : 0);
        refineSegments(tmp_frame, bgmask, out_frame);
        imshow("video", tmp_frame);
        imshow("segmented", out_frame);
        char keycode = (char)waitKey(30);
        if( keycode == 27 )
            break;
        if( keycode == ' ' )
        {
            update_bg_model = !update_bg_model;
            printf("Learn background is in state = %d\n",update_bg_model);
        }
    }
    return 0;
}

boxFilter()

Blurs an image using the box filter.

The function smooths an image using the kernel:

Unnormalized box filter is useful for computing various integral characteristics over each pixel neighborhood, such as covariance matrices of image derivatives (used in dense optical flow algorithms, and so on). If you need to compute pixel sums over variable-size windows, use integral.

非标准化盒式滤波器可用于计算每个像素邻域上的各种积分特性,例如图像导数的协方差矩阵(用于密集光流算法等)。 如果需要在可变大小的窗口上计算像素总和,请使用积分。


filter2D()

Convolves an image with the kernel.

The function applies an arbitrary linear filter to an image. In-place operation is supported. When the aperture is partially outside the image, the function interpolates outlier pixel values according to the specified border mode.

The function does actually compute correlation, not the convolution:

That is, the kernel is not mirrored around the anchor point. If you need a real convolution, flip the kernel using flip and set the new anchor to (kernel.cols - anchor.x - 1, kernel.rows - anchor.y - 1).

The function uses the DFT-based algorithm in case of sufficiently large kernels (~11 x 11 or larger) and the direct algorithm for small kernels.

 

Applies a separable linear filter to an image.

The function applies a separable linear filter to the image. That is, first, every row of src is filtered with the 1D kernel kernelX. Then, every column of the result is filtered with the 1D kernel kernelY. The final result shifted by delta is stored in dst .

 


GaussianBlur()

Blurs an image using a Gaussian filter.

The function convolves the source image with the specified Gaussian kernel. In-place filtering is supported.

C++实例:

#include <iostream>
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
using namespace std;
using namespace cv;
int DELAY_CAPTION = 1500;
int DELAY_BLUR = 100;
int MAX_KERNEL_LENGTH = 31;
Mat src; Mat dst;
char window_name[] = "Smoothing Demo";
int display_caption( const char* caption );
int display_dst( int delay );
int main( int argc, char ** argv )
{
    namedWindow( window_name, WINDOW_AUTOSIZE );
    const char* filename = argc >=2 ? argv[1] : "../data/lena.jpg";
    src = imread( filename, IMREAD_COLOR );
    if(src.empty())
    {
        printf(" Error opening image\n");
        printf(" Usage: ./Smoothing [image_name -- default ../data/lena.jpg] \n");
        return -1;
    }
    if( display_caption( "Original Image" ) != 0 )
    {
        return 0;
    }
    dst = src.clone();
    if( display_dst( DELAY_CAPTION ) != 0 )
    {
        return 0;
    }
    if( display_caption( "Homogeneous Blur" ) != 0 )
    {
        return 0;
    }
    for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
    {
        blur( src, dst, Size( i, i ), Point(-1,-1) );
        if( display_dst( DELAY_BLUR ) != 0 )
        {
            return 0;
        }
    }
    if( display_caption( "Gaussian Blur" ) != 0 )
    {
        return 0;
    }
    for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
    {
        GaussianBlur( src, dst, Size( i, i ), 0, 0 );
        if( display_dst( DELAY_BLUR ) != 0 )
        {
            return 0;
        }
    }
    if( display_caption( "Median Blur" ) != 0 )
    {
        return 0;
    }
    for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
    {
        medianBlur ( src, dst, i );
        if( display_dst( DELAY_BLUR ) != 0 )
        {
            return 0;
        }
    }
    if( display_caption( "Bilateral Blur" ) != 0 )
    {
        return 0;
    }
    for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
    {
        bilateralFilter ( src, dst, i, i*2, i/2 );
        if( display_dst( DELAY_BLUR ) != 0 )
        {
            return 0;
        }
    }
    display_caption( "Done!" );
    return 0;
}
int display_caption( const char* caption )
{
    dst = Mat::zeros( src.size(), src.type() );
    putText( dst, caption,
             Point( src.cols/4, src.rows/2),
             FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255) );
    return display_dst(DELAY_CAPTION);
}
int display_dst( int delay )
{
    imshow( window_name, dst );
    int c = waitKey ( delay );
    if( c >= 0 ) { return -1; }
    return 0;
}

getDerivKernels()

Returns filter coefficients for computing spatial image derivatives.

The function computes and returns the filter coefficients for spatial image derivatives. When ksize=CV_SCHARR, the Scharr 3×3 kernels are generated (see Scharr). Otherwise, Sobel kernels are generated (see Sobel). The filters are normally passed to sepFilter2D or to


getGaborKernel()

Returns Gabor filter coefficients.

For more details about gabor filter equations and parameters, see: Gabor Filter.


getGaussianKernel()

 

Returns Gaussian filter coefficients.

The function computes and returns the ?????×1 matrix of Gaussian filter coefficients:

Two of such generated kernels can be passed to sepFilter2D. Those functions automatically recognize smoothing kernels (a symmetrical kernel with sum of weights equal to 1) and handle them accordingly. You may also use the higher-level GaussianBlur.


Laplacian()

C++实例:

An example using Laplace transformations for edge detection

#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <ctype.h>
#include <stdio.h>
#include <iostream>
using namespace cv;
using namespace std;
static void help()
{
    cout <<
            "\nThis program demonstrates Laplace point/edge detection using OpenCV function Laplacian()\n"
            "It captures from the camera of your choice: 0, 1, ... default 0\n"
            "Call:\n"
            "./laplace -c=<camera #, default 0> -p=<index of the frame to be decoded/captured next>\n" << endl;
}
enum {GAUSSIAN, BLUR, MEDIAN};
int sigma = 3;
int smoothType = GAUSSIAN;
int main( int argc, char** argv )
{
    VideoCapture cap;
    cv::CommandLineParser parser(argc, argv, "{ c | 0 | }{ p | | }");
    help();
    if( parser.get<string>("c").size() == 1 && isdigit(parser.get<string>("c")[0]) )
        cap.open(parser.get<int>("c"));
    else
        cap.open(parser.get<string>("c"));
    if( cap.isOpened() )
        cout << "Video " << parser.get<string>("c") <<
            ": width=" << cap.get(CAP_PROP_FRAME_WIDTH) <<
            ", height=" << cap.get(CAP_PROP_FRAME_HEIGHT) <<
            ", nframes=" << cap.get(CAP_PROP_FRAME_COUNT) << endl;
    if( parser.has("p") )
    {
        int pos = parser.get<int>("p");
        if (!parser.check())
        {
            parser.printErrors();
            return -1;
        }
        cout << "seeking to frame #" << pos << endl;
        cap.set(CAP_PROP_POS_FRAMES, pos);
    }
    if( !cap.isOpened() )
    {
        cout << "Could not initialize capturing...\n";
        return -1;
    }
    namedWindow( "Laplacian", 0 );
    createTrackbar( "Sigma", "Laplacian", &sigma, 15, 0 );
    Mat smoothed, laplace, result;
    for(;;)
    {
        Mat frame;
        cap >> frame;
        if( frame.empty() )
            break;
        int ksize = (sigma*5)|1;
        if(smoothType == GAUSSIAN)
            GaussianBlur(frame, smoothed, Size(ksize, ksize), sigma, sigma);
        else if(smoothType == BLUR)
            blur(frame, smoothed, Size(ksize, ksize));
        else
            medianBlur(frame, smoothed, ksize);
        Laplacian(smoothed, laplace, CV_16S, 5);
        convertScaleAbs(laplace, result, (sigma+1)*0.25);
        imshow("Laplacian", result);
        char c = (char)waitKey(30);
        if( c == ' ' )
            smoothType = smoothType == GAUSSIAN ? BLUR : smoothType == BLUR ? MEDIAN : GAUSSIAN;
        if( c == 'q' || c == 'Q' || c == 27 )
            break;
    }
    return 0;
}

medianBlur()

Blurs an image using the median filter.

The function smoothes an image using the median filter with the ?????×????? aperture. Each channel of a multi-channel image is processed independently. In-place operation is supported.

C++实例:

An example using the Hough circle detector


#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
    const char* filename = argc >=2 ? argv[1] : "../data/smarties.png";
    // Loads an image
    Mat src = imread( filename, IMREAD_COLOR );
    // Check if image is loaded fine
    if(src.empty()){
        printf(" Error opening image\n");
        printf(" Program Arguments: [image_name -- default %s] \n", filename);
        return -1;
    }
    Mat gray;
    cvtColor(src, gray, COLOR_BGR2GRAY);
    medianBlur(gray, gray, 5);
    vector<Vec3f> circles;
    HoughCircles(gray, circles, HOUGH_GRADIENT, 1,
                 gray.rows/16,  // change this value to detect circles with different distances to each other
                 100, 30, 1, 30 // change the last two parameters
            // (min_radius & max_radius) to detect larger circles
    );
    for( size_t i = 0; i < circles.size(); i++ )
    {
        Vec3i c = circles[i];
        Point center = Point(c[0], c[1]);
        // circle center
        circle( src, center, 1, Scalar(0,100,100), 3, LINE_AA);
        // circle outline
        int radius = c[2];
        circle( src, center, radius, Scalar(255,0,255), 3, LINE_AA);
    }
    imshow("detected circles", src);
    waitKey();
    return 0;
}

Scharr()

Calculates the first x- or y- image derivative using Scharr operator.

The function computes the first x- or y- spatial image derivative using the Scharr operator. The call

??????(???, ???, ??????, ??, ??, ?????, ?????, ??????????)

is equivalent to

?????(???, ???, ??????, ??, ??, ??_??????, ?????, ?????, ??????????).

C++实例:

This program demonstrates usage of the Canny edge detector

#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <stdio.h>
using namespace cv;
using namespace std;
int edgeThresh = 1;
int edgeThreshScharr=1;
Mat image, gray, blurImage, edge1, edge2, cedge;
const char* window_name1 = "Edge map : Canny default (Sobel gradient)";
const char* window_name2 = "Edge map : Canny with custom gradient (Scharr)";
// define a trackbar callback
static void onTrackbar(int, void*)
{
    blur(gray, blurImage, Size(3,3));
    // Run the edge detector on grayscale
    Canny(blurImage, edge1, edgeThresh, edgeThresh*3, 3);
    cedge = Scalar::all(0);
    image.copyTo(cedge, edge1);
    imshow(window_name1, cedge);
    Mat dx,dy;
    Scharr(blurImage,dx,CV_16S,1,0);
    Scharr(blurImage,dy,CV_16S,0,1);
    Canny( dx,dy, edge2, edgeThreshScharr, edgeThreshScharr*3 );
    cedge = Scalar::all(0);
    image.copyTo(cedge, edge2);
    imshow(window_name2, cedge);
}
static void help()
{
    printf("\nThis sample demonstrates Canny edge detection\n"
           "Call:\n"
           "    /.edge [image_name -- Default is ../data/fruits.jpg]\n\n");
}
const char* keys =
{
    "{help h||}{@image |../data/fruits.jpg|input image name}"
};
int main( int argc, const char** argv )
{
    help();
    CommandLineParser parser(argc, argv, keys);
    string filename = parser.get<string>(0);
    image = imread(filename, IMREAD_COLOR);
    if(image.empty())
    {
        printf("Cannot read image file: %s\n", filename.c_str());
        help();
        return -1;
    }
    cedge.create(image.size(), image.type());
    cvtColor(image, gray, COLOR_BGR2GRAY);
    // Create a window
    namedWindow(window_name1, 1);
    namedWindow(window_name2, 1);
    // create a toolbar
    createTrackbar("Canny threshold default", window_name1, &edgeThresh, 100, onTrackbar);
    createTrackbar("Canny threshold Scharr", window_name2, &edgeThreshScharr, 400, onTrackbar);
    // Show the image
    onTrackbar(0, 0);
    // Wait for a key stroke; the same function arranges events processing
    waitKey(0);
    return 0;
}

 


Sobel算子

Calculates the first, second, third, or mixed image derivatives using an extended Sobel operator.

In all cases except one, the ?????×????? separable kernel is used to calculate the derivative. When ????? = ?, the 3×1 or 1×3 kernel is used (that is, no Gaussian smoothing is done). ksize = 1 can only be used for the first or the second x- or y- derivatives.

C++实例:

Sample code using Sobel and/or Scharr OpenCV functions to make a simple Edge Detector

#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main( int argc, char** argv )
{
  cv::CommandLineParser parser(argc, argv,
                               "{@input   |../data/lena.jpg|input image}"
                               "{ksize   k|1|ksize (hit 'K' to increase its value)}"
                               "{scale   s|1|scale (hit 'S' to increase its value)}"
                               "{delta   d|0|delta (hit 'D' to increase its value)}"
                               "{help    h|false|show help message}");
  cout << "The sample uses Sobel or Scharr OpenCV functions for edge detection\n\n";
  parser.printMessage();
  cout << "\nPress 'ESC' to exit program.\nPress 'R' to reset values ( ksize will be -1 equal to Scharr function )";
  // First we declare the variables we are going to use
  Mat image,src, src_gray;
  Mat grad;
  const String window_name = "Sobel Demo - Simple Edge Detector";
  int ksize = parser.get<int>("ksize");
  int scale = parser.get<int>("scale");
  int delta = parser.get<int>("delta");
  int ddepth = CV_16S;
  String imageName = parser.get<String>("@input");
  // As usual we load our source image (src)
  image = imread( imageName, IMREAD_COLOR ); // Load an image
  // Check if image is loaded fine
  if( image.empty() )
  {
    printf("Error opening image: %s\n", imageName.c_str());
    return 1;
  }
  for (;;)
  {
    // Remove noise by blurring with a Gaussian filter ( kernel size = 3 )
    GaussianBlur(image, src, Size(3, 3), 0, 0, BORDER_DEFAULT);
    // Convert the image to grayscale
    cvtColor(src, src_gray, COLOR_BGR2GRAY);
    Mat grad_x, grad_y;
    Mat abs_grad_x, abs_grad_y;
    Sobel(src_gray, grad_x, ddepth, 1, 0, ksize, scale, delta, BORDER_DEFAULT);
    Sobel(src_gray, grad_y, ddepth, 0, 1, ksize, scale, delta, BORDER_DEFAULT);
    // converting back to CV_8U
    convertScaleAbs(grad_x, abs_grad_x);
    convertScaleAbs(grad_y, abs_grad_y);
    addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad);
    imshow(window_name, grad);
    char key = (char)waitKey(0);
    if(key == 27)
    {
      return 0;
    }
    if (key == 'k' || key == 'K')
    {
      ksize = ksize < 30 ? ksize+2 : -1;
    }
    if (key == 's' || key == 'S')
    {
      scale++;
    }
    if (key == 'd' || key == 'D')
    {
      delta++;
    }
    if (key == 'r' || key == 'R')
    {
      scale =  1;
      ksize = -1;
      delta =  0;
    }
  }
  return 0;
}


函数列表

void  cv::bilateralFilter (InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT)
  Applies the bilateral filter to an image. 
 
void  cv::blur (InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT)
  Blurs an image using the normalized box filter. 
 
void  cv::boxFilter (InputArray src, OutputArray dst, int ddepth, Size ksize, Point anchor=Point(-1,-1), bool normalize=true, int borderType=BORDER_DEFAULT)
  Blurs an image using the box filter. 
 
void  cv::buildPyramid (InputArray src, OutputArrayOfArrays dst, int maxlevel, int borderType=BORDER_DEFAULT)
  Constructs the Gaussian pyramid for an image. 
 
void  cv::dilate (InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar &borderValue=morphologyDefaultBorderValue())
  Dilates an image by using a specific structuring element. 
 
void  cv::erode (InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar &borderValue=morphologyDefaultBorderValue())
  Erodes an image by using a specific structuring element. 
 
void  cv::filter2D (InputArray src, OutputArray dst, int ddepth, InputArray kernel, Point anchor=Point(-1,-1), double delta=0, int borderType=BORDER_DEFAULT)
  Convolves an image with the kernel. 
 
void  cv::GaussianBlur (InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT)
  Blurs an image using a Gaussian filter. 
 
void  cv::getDerivKernels (OutputArray kx, OutputArray ky, int dx, int dy, int ksize, bool normalize=false, int ktype=CV_32F)
  Returns filter coefficients for computing spatial image derivatives. 
 
Mat  cv::getGaborKernel (Size ksize, double sigma, double theta, double lambd, double gamma, double psi=CV_PI *0.5, int ktype=CV_64F)
  Returns Gabor filter coefficients.
 
Mat  cv::getGaussianKernel (int ksize, double sigma, int ktype=CV_64F)
  Returns Gaussian filter coefficients. 
 
Mat  cv::getStructuringElement (int shape, Size ksize, Point anchor=Point(-1,-1))
  Returns a structuring element of the specified size and shape for morphological operations. 
 
void  cv::Laplacian (InputArray src, OutputArray dst, int ddepth, int ksize=1, double scale=1, double delta=0, int borderType=BORDER_DEFAULT)
  Calculates the Laplacian of an image. 
 
void  cv::medianBlur (InputArray src, OutputArray dst, int ksize)
  Blurs an image using the median filter. 
 
static Scalar  cv::morphologyDefaultBorderValue ()
  returns "magic" border value for erosion and dilation. It is automatically transformed to Scalar::all(-DBL_MAX) for dilation. 
 
void  cv::morphologyEx (InputArray src, OutputArray dst, int op, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar &borderValue=morphologyDefaultBorderValue())
  Performs advanced morphological transformations. More...
 
void  cv::pyrDown (InputArray src, OutputArray dst, const Size &dstsize=Size(), int borderType=BORDER_DEFAULT)
  Blurs an image and downsamples it. 
 
void  cv::pyrMeanShiftFiltering (InputArray src, OutputArray dst, double sp, double sr, int maxLevel=1, TermCriteriatermcrit=TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 5, 1))
  Performs initial step of meanshift segmentation of an image. 
 
void  cv::pyrUp (InputArray src, OutputArray dst, const Size &dstsize=Size(), int borderType=BORDER_DEFAULT)
  Upsamples an image and then blurs it. More...
 
void  cv::Scharr (InputArray src, OutputArray dst, int ddepth, int dx, int dy, double scale=1, double delta=0, int borderType=BORDER_DEFAULT)
  Calculates the first x- or y- image derivative using Scharr operator. More...
 
void  cv::sepFilter2D (InputArray src, OutputArray dst, int ddepth, InputArray kernelX, InputArray kernelY, Point anchor=Point(-1,-1), double delta=0, int borderType=BORDER_DEFAULT)
  Applies a separable linear filter to an image. 
 
void  cv::Sobel (InputArray src, OutputArray dst, int ddepth, int dx, int dy, int ksize=3, double scale=1, double delta=0, int borderType=BORDER_DEFAULT)
  Calculates the first, second, third, or mixed image derivatives using an extended Sobel operator. 
 
void  cv::spatialGradient (InputArray src, OutputArray dx, OutputArray dy, int ksize=3, int borderType=BORDER_DEFAULT)
  Calculates the first order image derivative in both x and y using a Sobel operator. 
 
void  cv::sqrBoxFilter (InputArray _src, OutputArray _dst, int ddepth, Size ksize, Point anchor=Point(-1, -1), bool normalize=true, int borderType=BORDER_DEFAULT)
  Calculates the normalized sum of squares of the pixel values overlapping the filter. 

原文链接:

https://docs.opencv.org/3.4.3/d4/d86/group__imgproc__filter.html#gae84c92d248183bd92fa713ce51cc3599

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2015-09-20 11:45:25 u013162930 阅读数 7954
  • 学习OpenCV3.2+QT5+ffmpeg实战开发视频编辑视频教程

    OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现),双线性插值,图像金字塔)、颜色格式(灰度图,二值化(阈值)),旋转镜像,视频裁剪(ROI),视频水印(ROI+weight),导出处理后的视频(包含音频,使用ffmpeg工具对音频进行抽取、剪切和终于opencv处理的视频合并)。

    19573 人正在学习 去看看 夏曹俊

平滑空间滤波器是低频增强的空间滤波技术。它的目的有两类:一是模糊处理,二是降低噪声。本文介绍的平滑空间滤波器也分为两类,一类是线性滤波器,比如最简单的简单平均法;另一类是统计排序滤波器。

平滑处理也常称为模糊处理。是因为对于线性滤波器来说,一般高通是锐化,低通是模糊。


下面我们先来说说平滑线性滤波器

平滑线性空间滤波器的输出(响应)是包含在滤波器模板邻域内的像素的简单平均值。这些滤波器有时也称为均值滤波器。也可以把它们归入低通滤波器。

这种处理的结果降低了图像灰度的尖锐变化。由于典型的随机噪声由灰度级的急剧变化组成,因此常见的平滑处理的应用就是降噪。

然而,由于图像边缘(几乎总是一幅图像希望有的特性)也是由图像灰度尖锐变化带来的特性,所以均值滤波器处理还是存在着不希望有的边缘模糊的负面效应。

下面这幅图中的是最为常见的简单平均的滤波器模板

所有系数都相等的空间均值滤波器,有时也被称为盒状滤波器。

 

这个滤波器模板相比于上一个更加重要。这个滤波器模板产生所谓的加权平均,使用这一术语是指,用不同的系数去乘以像素。即一些像素的重要性(权重)比另外一些像素的重要性更大。

在这个例子所示的模板中,中心位置的系数最大,因此在均值计算中可以为该像素提供更大的权重。其他像素离中心越近就赋予越大的权重。

这种加权重的策略的目的是,在平滑处理中,试图降低模糊。

我们也可以选择其他权重来达到相同的目的。

但是,这个例子中所有系数的和等于16,这对于计算机来说是一个很有吸引力的特性,因为它是2的整数次幂。


在实践中,由于这些模板在一幅图像中的任何一个位置所跨越的区域很小,通常很难看出这两个模板或者类似方式进行平滑处理后的图像之间的区别。


一幅M * N的图像进过一个m*n的加权均值滤波器,滤波的过程可由下式给出:

当图像的细节与滤波器模板近似相同时,图像中的一些细节受到的影响比较大。

邻域越大平滑的效果越好。但是邻域过大,平滑会使边缘信息损失的越大,从而使输出的图像变得模糊,因此需要合理的选择邻域的大小。

模板的大小由那些即将融入背景中的物体R的尺寸来决定。

滤波后的图像中可能会有黑边。这是由于我们用0(黑色)填充原图像的边界,经滤波后,再去除填充区域的结果,某些黑的混入了滤波后的图像。对于使用较大滤波器平滑的图像,这就成了问题。


统计排序(非线性)滤波器

统计排序滤波器是一种非线性空间滤波器,这种滤波器的响应以滤波器包围的图像的像素的排序为基础,然后使用统计排序结果决定的值代替中心像素的值。

这一类中最知名的就要数中值滤波器了~它是将像素邻域内的灰度值的中值代替该像素的值。

中值滤波器的使用非常的普遍,它对于一定类型的随机噪声提供了一种优秀的去噪能力。而且比同尺寸的线性平滑滤波器的模糊程度明显要低。不足之处就是中值滤波花费的时间是均值滤波的5倍以上。

中值滤波器对于处理脉冲噪声非常有效,这种噪声称为椒盐噪声,因为这种噪声是以黑白点的形式叠加在图像上的。

中值滤波器的主要功能是使拥有不同灰度的点看起来更接近于他们的相邻点。

我们使用m*m中值滤波器来去除那些相对于其邻域像素更亮或更暗并且其区域小于(m^2)/2(滤波器区域一半)的孤立像素族。



以下是openCV的均值滤波、中值滤波

using namespace cv;
Mat srcImage = imread("M:/图像处理实验/平滑空间滤波器/椒盐噪声.jpg");
//均值滤波
Mat dstImage;
blur(srcImage,dstImage,Size(5,5));
imwrite("M:/图像处理实验/平滑空间滤波器/椒盐噪声result.jpg", dstImage);

using namespace cv;
Mat srcImage = imread("M:/图像处理实验/平滑空间滤波器/椒盐噪声.jpg");
//中值滤波
Mat dstImage;
medianBlur(srcImage,dstImage,5);
imwrite("M:/图像处理实验/平滑空间滤波器/中值滤波.jpg", dstImage);

添加了椒盐噪声的图像

均值滤波后的结果


中值滤波后的结果




很明显,中值滤波的效果要比均值滤波好的多~




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