图像滤波:包括图像平滑,锐化,以及图像金字塔
形态学运算的应用:膨胀、腐蚀、开运算、闭运算
几何变换:仿射和透视变换
修复:用于重构图像的受损部分
去噪:用于降低图像拍摄设备所产生的图像噪声
图像滤波
图像滤波是增强或者修改图像的过程
滤波是增强或者修改图像的过程。增强图像中的某些特征,或者消除其他特征
滤波是一种领域运算,领域是选定区域周围像素几何,通过利用在该像素周围一定领域内像素集合的值执行的某些运算
平滑:又称为模糊。将位于(xi,yj)位置及周围的输入像素值进行加权的值作为该处的输出像素值
线性运算中,像素的权值通常存储在一个称为kernel的矩阵中
因此一个滤波可以表示为为一个滑动窗口
最常用的平滑滤波方法
中值滤波 适合去除椒盐噪声 & 斑点噪声
高斯滤波 适合边缘检测的预处理阶段
双边滤波 适合处理平滑强边缘的图像
常用滤波函数
void boxFilter( 输入,输出,输出图像深度,核大小,核中心(默认(-1,-1)及定位像素是核中心),=true时 输出像素值是核领域的均值,边界类型)
void GaussianBlur
@param src input image; the image can have any number of channels, which are processed
independently, but the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
@param dst output image of the same size and type as src.
@param ksize Gaussian kernel size. ksize.width and ksize.height can differ but they both must be
positive and odd. Or, they can be zero's and then they are computed from sigma.
@param sigmaX Gaussian kernel standard deviation in X direction.
@param sigmaY Gaussian kernel standard deviation in Y direction; if sigmaY is zero, it is set to be
equal to sigmaX, if both sigmas are zeros, they are computed from ksize.width and ksize.height,
respectively (see cv::getGaussianKernel for details); to fully control the result regardless of
possible future modifications of all this semantics, it is recommended to specify all of ksize,
sigmaX, and sigmaY.
@param borderType pixel extrapolation method, see cv::BorderTypes
@sa sepFilter2D, filter2D, blur, boxFilter, bilateralFilter, medianBlur
*/
CV_EXPORTS_Wvoid GaussianBlur( InputArraysrc,OutputArray dst, Size ksize,
double sigmaX , double sigmaY= 0,
int borderType = BORDER_DEFAULT );
void medianBlur 顾名思义:输出图像的像素值是领域的中值
void bilateralBlur
This filter does not work inplace.
@param src Source 8-bit or floating-point, 1-channel or 3-channel image.
@param dst Destination image of the same size and type as src .
@param d Diameter of each pixel neighborhood that is used during filtering. If it is non-positive,
it is computed from sigmaSpace.
@param sigmaColor Filter sigma in the color space. A larger value of the parameter means that
farther colors within the pixel neighborhood (see sigmaSpace) will be mixed together, resulting
in larger areas of semi-equal color.
@param sigmaSpace Filter sigma in the coordinate space. A larger value of the parameter means that
farther pixels will influence each other as long as their colors are close enough (see sigmaColor
). When d\>0, it specifies the neighborhood size regardless of sigmaSpace. Otherwise, d is
proportional to sigmaSpace.
@param borderType border mode used to extrapolate pixels outside of the image, see cv::BorderTypes
*/
CV_EXPORTS_Wvoid bilateralFilter( InputArray src,OutputArray dst, int d,
double sigmaColor , double sigmaSpace,
int borderType = BORDER_DEFAULT );
void blur 使用归一化的盒式滤波来平滑图像
#include"opencv2/opencv.hpp"
#include"opencv.hpp"
#include<iostream>
usingnamespacestd;
usingnamespacecv;
intmain(intargc,char**argv)
{
//read the src image
Matsrc;
src=imread("math.png");
//open the fliter
Matdst, dst2;
GaussianBlur(src, dst,Size(9, 9), 0, 0);
medianBlur(src, dst2, 9);
//show
namedWindow("Original image",WINDOW_AUTOSIZE);
imshow("Original image", src);
namedWindow("Gussian blur",WINDOW_AUTOSIZE);
imshow("Gussian blur", dst);
namedWindow("Median blur",WINDOW_AUTOSIZE);
imshow("Median blur", dst2);
//wait
waitKey();
return0;
}
锐化
锐化用于突出显示图像的边界和其他精细部分
锐化是基于一阶导数和二阶导数的,一幅数字图像的离散量即梯度,其的一阶导数计算图像强度梯度的逼近,而二阶导数定义为该梯度的散度
一阶导数可以产生粗的图像边缘,广泛用于边缘提取
二阶导数对于细节的响应更好,常被用于图像增强
用于获取导数的两种常用算子是Sobel和Laplacian
Sobel算子计算一幅图像I的一阶导数,公式如下
通过整合两个方向上的梯度逼近值,可以获得如下的Soble梯度幅值
一幅图像的Laplacian值,可以使用下述核的卷积给出
常用的锐化函数
void
Sobel(
InputArray
src
,
OutputArray
dst
,
int
ddepth
,
int
dx
,
int
dy
,
int
ksize
= 3,
double
scale
= 1,
double
delta
= 0,
int
borderType
=
BORDER_DEFAULT
);
使用Soble算子计算src的一幅图像的一阶导数、二阶导数、三阶导数或混合导数
参数解释:
@param src input image.
@param dst output image of the same size and the same number of channels as src .
@param ddepth output image depth, see @ref filter_depths "combinations"; in the case of
8-bit input images it will result in truncated derivatives.
当值为-1时,输出与输入图像的深度相同
@param dx order of the derivative x.
@param dy order of the derivative y. 表示希望求导的阶
@param ksize size of the extended Sobel kernel; it must be 1, 3, 5, or 7.
@param scale optional scale factor for the computed derivative values; by default, no scaling is
applied (see cv::getDerivKernels for details). 建立计算导数值得尺度因子
@param delta optional delta value that is added to the results prior to storing them in dst.
@param borderType pixel extrapolation method, see cv::BorderTypes
@sa Scharr, Laplacian, sepFilter2D, filter2D, GaussianBlur, cartToPolar
void Scharr 用于计算一个3*3大小的核更精确的导数
@param src input image.
@param dst output image of the same size and the same number of channels as src.
@param ddepth output image depth, see @ref filter_depths "combinations"
@param dx order of the derivative x.
@param dy order of the derivative y.
@param scale optional scale factor for the computed derivative values; by default, no scaling is
applied (see getDerivKernels for details).
@param delta optional delta value that is added to the results prior to storing them in dst.
@param borderType pixel extrapolation method, see cv::BorderTypes
@sa cartToPolar
*/
CV_EXPORTS_Wvoid Scharr( InputArraysrc,OutputArray dst, int ddepth,
int dx , int dy,double scale = 1, double delta= 0,
int borderType = BORDER_DEFAULT );
void Laplacian 用于计算一幅图像的Laplacian值
除了ksize之外所有的参数和sobel &scharr 中的相同
ksize==1 使用3*3的核(中心值为-4,四个角的值为0,其余值为1)对图像进行滤波
ksize>1 使用Sobel算子通过累加x的二阶导数和y的二阶导数来计算源图像的Laplacian
@param src Source image.
@param dst Destination image of the same size and the same number of channels as src .
@param ddepth Desired depth of the destination image.
@param ksize Aperture size used to compute the second-derivative filters. See getDerivKernels for
details. The size must be positive and odd.
@param scale Optional scale factor for the computed Laplacian values. By default, no scaling is
applied. See getDerivKernels for details.
@param delta Optional delta value that is added to the results prior to storing them in dst .
@param borderType Pixel extrapolation method, see cv::BorderTypes
@sa Sobel, Scharr
*/
CV_EXPORTS_Wvoid Laplacian( InputArraysrc,OutputArray dst, int ddepth,
int ksize = 1, double scale= 1, double delta= 0,
int borderType = BORDER_DEFAULT );
#include"opencv2/opencv.hpp"
#include"opencv.hpp"
#include<iostream>
usingnamespacestd;
usingnamespacecv;
intmain(intargc,char**argv)
{
//read the src image
Matsrc;
src=imread("go.png");
//sharpen
Matdst, dst2;
Sobel(src, dst, -1, 0, 0);
Laplacian(src, dst2, -1);
//show
namedWindow("Original image",WINDOW_AUTOSIZE);
imshow("Original image", src);
namedWindow("Sobel",WINDOW_AUTOSIZE);
imshow("Soble", dst);
namedWindow("Laplacian",WINDOW_AUTOSIZE);
imshow("Laplacian", dst2);
//wait
waitKey();
return0;
}
图像金字塔
在某些情况下使用固定的图像工作是不可能的,可能需要不同分辨率的原始图像
例如,检测图像,从较小分辨率的图像进行搜索更为有效
这种类型的图像集合按照从下到上,从大到小堆起来,被形象地称为金字塔或者多级纹理(mipmap)
越到上面层数越高,图像的面积越小
有两类图像金字塔:高斯金字塔,拉普拉斯金字塔
1 高斯金字塔
在低一层通过交替隔行和隔列删除像素,然后对底层领域进行高斯滤波来获得更高一层的像素值
这样每执行一次,图像的宽和高变为原来的一半,面积减少为原来的1/4
2 拉普拉斯金字塔
可以看作是其大部分元素为0的一些边界图像,其第i层是高斯金字塔的第i层和第i+1层的膨胀般的差
OpenCV中没有专门提供拉普拉斯金字塔的函数
计算高斯金字塔的函数
void pyrDown 采样并模糊源图像,将结果传递给目标图像,当没有设置输出图像的大小时,使用Size((src.cols+1)/2,(src.rows+1)/2)来计算
void pyrUp 计算与函数pyrDown相反的过程
#include"opencv2/opencv.hpp"
#include"opencv.hpp"
#include<iostream>
usingnamespacestd;
usingnamespacecv;
intmain(intargc,char**argv)
{
//read the src image
Matsrc;
src=imread("cat2.png");
//pyrDown*2
Matdst, dst2;
pyrDown(src, dst);
pyrDown(dst, dst2);
//show
namedWindow("Original image",WINDOW_AUTOSIZE);
imshow("Original image", src);
namedWindow("1st pyrDown",WINDOW_AUTOSIZE);
imshow("1st pyrDown", dst);
namedWindow("2st pyrDown",WINDOW_AUTOSIZE);
imshow("2st pyrDown", dst2);
//pyrUp
pyrUp(dst2, dst);
pyrUp(dst, src);
//show
namedWindow("New",WINDOW_AUTOSIZE);
imshow("New", dst2);
namedWindow("1st pyrUp",WINDOW_AUTOSIZE);
imshow("1st pyrUp", dst);
namedWindow("2st pyrUp",WINDOW_AUTOSIZE);
imshow("2st pyrUp", src);
//wait
waitKey();
return0;
}
void buildPyramid 该函数为源图像建立一个有参数maxlevel张图像的高斯金字塔,并将金字塔储存在目标图像的数组中,原始图像是该数组的第一个元素dst[0]
基于均值漂移分割算法第一步的均值漂移金字塔建立函数
void pyrMeanShiftFiltering 实现均值漂移分割的第一步,滤波。获取一幅具有颜色梯度和细粒度纹理平滑的目标图像dst。有参数sp代表空间窗口半径,sr代表颜色窗口半径
形态学计算(morphological operation)
即根据图像的形态处理图像
从而使得对某些特定的形状更加敏感或者相反
两个基本的形态学运算:膨胀(dilation)&腐蚀(erosion)
膨胀是指从对象的背景到边界添加像素
腐蚀则是清除像素
定义形态结构,来表示要添加或者删除的元素,通过比较(xi,yj)处的输入像素值和领域的像素值来计算(xi,yj)处的像素得到一幅新的图像
膨胀运算中,输出像素的值是其领域所有像素的最大值
腐蚀运算中,输出像素的值是其领域所有像素的最小值
开运算:先腐蚀,后膨胀 清除小对象,保留大对象
闭运算:先膨胀,后腐蚀 清除小洞,保留更大的对象
形态学梯度:一幅图像膨胀运算和腐蚀运算的差值
top-hat:原图像与其开运算的差值
black-hat:闭运算与原图像的差值
可以推出:[闭运算图]>[原图]>[开运算图]
void dilate 对源图像进行膨胀运算,结果储存在目标图像中
The function supports the in-place mode. Dilation can be applied several ( iterations ) times. In
case of multi-channel images, each channel is processed independently.
@param src input image; the number of channels can be arbitrary, but the depth should be one of
CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
@param dst output image of the same size and type as src\`.
@param kernel structuring element used for dilation; if elemenat=Mat(), a 3 x 3 rectangular
structuring element is used. Kernel can be created using getStructuringElement
@param anchor position of the anchor within the element; default value (-1, -1) means that the
anchor is at the element center.
@param iterations number of times dilation is applied. 迭代的次数,可以多次执行该运算
@param borderType pixel extrapolation method, see cv::BorderTypes
@param borderValue border value in case of a constant border
@sa erode, morphologyEx, getStructuringElement
*/
CV_EXPORTS_Wvoid dilate( InputArraysrc,OutputArray dst, InputArray kernel,
Point anchor = Point(-1,-1), int iterations= 1,
int borderType = BORDER_CONSTANT,
const Scalar & borderValue = morphologyDefaultBorderValue() );
void erode 对源图像进行腐蚀运算,结果储存在目标图像中
The function supports the in-place mode. Erosion can be applied several ( iterations ) times. In
case of multi-channel images, each channel is processed independently.
@param src input image; the number of channels can be arbitrary, but the depth should be one of
CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
@param dst output image of the same size and type as src.
@param kernel structuring element used for erosion; if `element=Mat()`, a `3 x 3` rectangular
structuring element is used. Kernel can be created using getStructuringElement.
@param anchor position of the anchor within the element; default value (-1, -1) means that the
anchor is at the element center.
@param iterations number of times erosion is applied.
@param borderType pixel extrapolation method, see cv::BorderTypes
@param borderValue border value in case of a constant border
@sa dilate, morphologyEx, getStructuringElement
*/
CV_EXPORTS_Wvoid erode( InputArraysrc,OutputArray dst, InputArray kernel,
Point anchor = Point(-1,-1), int iterations= 1,
int borderType = BORDER_CONSTANT,
const Scalar & borderValue = morphologyDefaultBorderValue() );
void morphologyEx 执行使用参数op定义的形态学运算
The function can perform advanced morphological transformations using an erosion and dilation as
basic operations.
Any of the operations can be done in-place. In case of multi-channel images, each channel is
processed independently.
@param src Source image. The number of channels can be arbitrary. The depth should be one of
CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
@param dst Destination image of the same size and type as src\` .
@param kernel Structuring element. It can be created using getStructuringElement.
@param anchor Anchor position with the kernel. Negative values mean that the anchor is at the
kernel center.
@param op Type of a morphological operation, see cv::MorphTypes
@param iterations Number of times erosion and dilation are applied.
@param borderType Pixel extrapolation method, see cv::BorderTypes
@param borderValue Border value in case of a constant border. The default value has a special
meaning.
@sa dilate, erode, getStructuringElement
*/
CV_EXPORTS_Wvoid morphologyEx( InputArraysrc,OutputArray dst,
int op , InputArray kernel,
Point anchor = Point(-1,-1), int iterations= 1,
int borderType = BORDER_CONSTANT,
const Scalar & borderValue = morphologyDefaultBorderValue() );
Mat getStructuringElement 返回一个指定大小和形状的结构元素
The function constructs and returns the structuring element that can be further passed to cv::erode,
cv::dilate or cv::morphologyEx. But you can also construct an arbitrary binary mask yourself and use it as
the structuring element.
@param shape Element shape that could be one of cv::MorphShapes
@param ksize Size of the structuring element.
@param anchor Anchor position within the element. The default value \f$(-1, -1)\f$ means that the
anchor is at the center. Note that only the shape of a cross-shaped element depends on the anchor
position. In other cases the anchor just regulates how much the result of the morphological
operation is shifted.
*/
CV_EXPORTS_WMat getStructuringElement(intshape,Size ksize , Point anchor= Point(-1,-1));
#include"opencv2/opencv.hpp"
#include"opencv.hpp"
#include<iostream>
usingnamespacestd;
usingnamespacecv;
intmain(intargc,char**argv)
{
//read the src image
Matsrc;
src=imread("go.png");
//blur
Matdst, dst2,dst3,dst4,dst5;
inRange(src,Scalar(210, 210, 210),Scalar(255,255, 255), dst);//二值化阀值
Matelement = getStructuringElement(MORPH_ELLIPSE,Size(15, 15));
//closed operation
dilate(dst, dst2, element);
erode(dst2, dst3, element);
//open operation
erode(dst, dst4, element);
dilate(dst4, dst5, element);
//show
namedWindow("Original image",WINDOW_AUTOSIZE);
imshow("Original image", src);
namedWindow("Segmented",WINDOW_AUTOSIZE);
imshow("Segmented", dst);
/* namedWindow("Dilation", WINDOW_AUTOSIZE);
imshow("Dilation", dst2);
namedWindow("Dilation->Erision", WINDOW_AUTOSIZE);
imshow("Dilation->Erision", dst3);*/
//open operation
namedWindow("Dilation",WINDOW_AUTOSIZE);
imshow("Dilation", dst4);
namedWindow("Erision->Dilation",WINDOW_AUTOSIZE);
imshow("Erision->Dilation", dst5);
//wait
waitKey();
return0;
}
//闭运算
//开运算
查找表LUT(Look up table)
一个LUT变换,根据表中的值为输入图像的每个像素分配一个新的像素值
在该表中,其索引代表输入的亮度值,而相应索引单元的内容代表对应的输出值
该转化实际上是对每个可能的亮度值计算
#include
"opencv2/opencv.hpp"
#include
"opencv.hpp"
#include
<iostream>
using
namespace
std;
using
namespace
cv;
int
main(
int
argc
,
char
**
argv
)
{
//read the src image
Mat
src;
src
=
imread(
"color.png"
);
//creat the table and init
uchar
*M = (
uchar
*)malloc(256 *
sizeof
(
uchar
));
for
(
int
i = 0; i < 256; i++)
{
M[i] = i*0.5;
}
Mat
lut(1, 256,
CV_8UC1
, M);
//LUT
Mat
dst;
LUT(src, lut, dst);
//show
namedWindow(
"Orginal"
,
WINDOW_AUTOSIZE
);
imshow(
"Orginal"
, src);
namedWindow(
"LUT"
,
WINDOW_AUTOSIZE
);
imshow(
"LUT"
, dst);
//wait
waitKey();
return
0;
}