OpenCV 常用函数使用例子和说明

1,操作例子目录

操作 描述
cv::abs() 返回所有元素的绝对值
cv::absdiff() 返回两个元素数组差的绝对值
cv::add() 最元素相加
cv::addWeighted() 添加两个每个元素的权值
cv::bitwise_and() 两个数组逐元素求与操作
cv::bitwise_not() 数组逐元素求非
cv::bitwise_or() 两个数组逐元素求或运算
cv::bitwise_xor() 两个数组逐元素求异或运算
cv::calcCovarMatrix() 计算n维数组的协方差
cv::cartToPolar() 将二维向量转换为极坐标
cv::checkRange() 检查数组是否是有效值
cv::compare() 比较两个数组是否相同
cv::completeSymm() 对称矩阵,复制一半元素到另一半
cv::convertScaleAbs() 缩放,采取绝对值,然后转换为8bit无符号数值
cv::countNonZero() 计算数组中非零元素的个数
cv::arrtoMat() 转换旧版本的数组
cv::dct() 计算离散余弦函数
cv::dft() 计算傅里叶转换矩阵

 

cv::idct() 计算逆离散余弦矩阵
cv::idft()

计算逆傅里叶矩阵

2,代码例子

//包含OpenCV的头文件
#include 
#include 
#include 
#include 
using namespace  std;
//使用OpenCV的命名空间
using namespace cv;
//cv::abs()
//数据结果
/*
//原始数据
[0.060565587, -0.60148162, -0.19788112;
0.62877017, -0.12573405, -0.5024206;
0.54621011, 0.52418745, -0.38441104]
//abs后的结果数据
[0.060565587, 0.60148162, 0.19788112;
0.62877017, 0.12573405, 0.5024206;
0.54621011, 0.52418745, 0.38441104]
*/
void test_abs()
{
	const int iRows = 3;
	const int iCols = 3;
	Mat m(iRows, iCols, CV_32FC1);
	randu(m, -1, 1);
	cout << m << endl;
	Mat m1 = abs(m);
	cout << m1 << endl;
	return;
}

//测试absdiff()
/*
m0 is:
[0.060565587, -0.60148162, -0.19788112;
0.62877017, -0.12573405, -0.5024206;
0.54621011, 0.52418745, -0.38441104]

m1 is:
[1, 1, 1;
1, 1, 1;
1, 1, 1]

m2 is:
[0.93943441, 1.6014817, 1.1978811;
0.37122983, 1.1257341, 1.5024207;
0.45378989, 0.47581255, 1.3844111]
*/
void test_absdiff()
{
	const int iRows = 3;
	const int iCols = 3;
	Mat m0(iRows, iCols, CV_32FC1);
	//m1的元素为1.0f
	Mat m1(iRows, iCols, CV_32FC1, Scalar(1.0f));
	//m0的元素为[-1,1)的随机数
	randu(m0, -1, 1);
	cout << "m0 is:\n" << m0 << endl << endl;
	cout << "m1 is:\n" << m1 << endl << endl;
	Mat m2;
	absdiff(m0, m1, m2);
	cout << "m2 is:\n" << m2 << endl << endl;
	return;
}

//测试add()
/*
m0 is:
[0.060565587, -0.60148162, -0.19788112;
0.62877017, -0.12573405, -0.5024206;
0.54621011, 0.52418745, -0.38441104]

m1 is:
[1, 1, 1;
1, 1, 1;
1, 1, 1]

m2 is:
[1.0605656, 0.39851838, 0.8021189;
1.6287701, 0.87426597, 0.4975794;
1.5462101, 1.5241874, 0.61558896]
*/
void test_add()
{
	const int iRows = 3;
	const int iCols = 3;
	Mat m0(iRows, iCols, CV_32FC1);
	//m1的元素为1.0f
	Mat m1(iRows, iCols, CV_32FC1, Scalar(1.0f));	
	
	//m0的元素为[-1,1)的随机数
	randu(m0, -1, 1);
	cout << "m0 is:\n" << m0 << endl << endl;
	cout << "m1 is:\n" << m1 << endl << endl;
	Mat m2;
	add(m0, m1, m2);
	cout << "m2 is:\n" << m2 << endl << endl;
	return;
}

//测试addWeight()
/*
m0 is:
[0.060565587, -0.60148162, -0.19788112;
0.62877017, -0.12573405, -0.5024206;
0.54621011, 0.52418745, -0.38441104]

m1 is:
[1, 1, 1;
1, 1, 1;
1, 1, 1]

m2 is:
[0.5302828, 0.19925919, 0.40105945;
0.81438506, 0.43713298, 0.2487897;
0.77310503, 0.76209372, 0.30779448]
*/
void test_addWeight()
{
	const int iRows = 3;
	const int iCols = 3;
	Mat m0(iRows, iCols, CV_32FC1);
	//m1的元素为1.0f
	Mat m1(iRows, iCols, CV_32FC1, Scalar(1.0f));

	//m0的元素为[-1,1)的随机数
	randu(m0, -1, 1);
	cout << "m0 is:\n" << m0 << endl << endl;
	cout << "m1 is:\n" << m1 << endl << endl;
	Mat m2;
	addWeighted(m0, 0.5, m1, 0.5, 0, m2);
	cout << "m2 is:\n" << m2 << endl << endl;
	return;
}

//测试bitwise_and()
//结果和 src1&src2 是相同的
/*
m0 is:
[246, 156, 192;
7, 165, 166;
2, 179, 231]

m1 is:
[  1,   1,   1;
1,   1,   1;
1,   1,   1]

m2 is:
[  0,   0,   0;
1,   1,   0;
0,   1,   1]
*/
void test_bitwise_and()
{
	const int iRows = 3;
	const int iCols = 3;
	Mat m0(iRows, iCols, CV_8UC1);
	Mat m1(iRows, iCols, CV_8UC1, Scalar(1));
	randu(m0, 0, 256);
	cout << "m0 is:\n" << m0 << endl << endl;
	cout << "m1 is:\n" << m1 << endl << endl;
	Mat m2;
	bitwise_and(m0, m1, m2);
	cout << "m2 is:\n" << m2 << endl << endl;
	return;
}

//测试bitwise_not
//结果求反
/*
m0 is:
[246, 156, 192;
7, 165, 166;
2, 179, 231]

m2 is:
[  9,  99,  63;
248,  90,  89;
253,  76,  24]
*/
void test_bitwise_not()
{
	const int iRows = 3;
	const int iCols = 3;
	Mat m0(iRows, iCols, CV_8UC1);
	randu(m0, 0, 256);
	cout << "m0 is:\n" << m0 << endl << endl;
	Mat m2;
	bitwise_not(m0, m2);
	cout << "m2 is:\n" << m2 << endl << endl;
	return;
}

//测试bitwise_or()
/*
m0 is:
[246, 156, 192;
7, 165, 166;
2, 179, 231]

m1 is:
[  1,   1,   1;
1,   1,   1;
1,   1,   1]

m2 is:
[247, 157, 193;
7, 165, 167;
3, 179, 231]

*/
void test_bitwise_or()
{
	const int iRows = 3;
	const int iCols = 3;
	Mat m0(iRows, iCols, CV_8UC1);
	Mat m1(iRows, iCols, CV_8UC1, Scalar(1));
	randu(m0, 0, 256);
	cout << "m0 is:\n" << m0 << endl << endl;
	cout << "m1 is:\n" << m1 << endl << endl;
	Mat m2;
	bitwise_or(m0, m1, m2);
	cout << "m2 is:\n" << m2 << endl << endl;
	return;
}

//测试 bitwise_xor()
/*
m0 is:
[246, 156, 192;
7, 165, 166;
2, 179, 231]

m1 is:
[  1,   1,   1;
1,   1,   1;
1,   1,   1]

m2 is:
[247, 157, 193;
6, 164, 167;
3, 178, 230]
*/
void test_bitwise_xor()
{
	const int iRows = 3;
	const int iCols = 3;
	Mat m0(iRows, iCols, CV_8UC1);
	Mat m1(iRows, iCols, CV_8UC1, Scalar(1));
	randu(m0, 0, 256);
	cout << "m0 is:\n" << m0 << endl << endl;
	cout << "m1 is:\n" << m1 << endl << endl;
	Mat m2;
	bitwise_xor(m0, m1, m2);
	cout << "m2 is:\n" << m2 << endl << endl;
	return;
}

//测试calcCovarMatrix 计算协方差矩阵
//协方差计算的例子:https://blog.csdn.net/mr_hhh/article/details/78490576
//一个需要注意的地方:
//如果不使用COVAR_SCALE的话,那么计算出来的协方差是没有除以(样本数-1)的
//如果使用COVAR_SCALE的话,那么计算出来的协方差是除以(样本数)
//所以在使用的使用,应该注意一下,需要使用的是除以(样本数)还是(样本数-1)
/*
m matrix is:
[1, 8, 4;
2, 9, 3;
1, 9, 4;
6, 8, 5]
mean matrix is:
[2.5, 8.5, 4]
covar matrix is:
[17, -2, 4;
-2, 1, -1;
4, -1, 2]
*/
void test_calcCovarMatrix()
{
	const int iRows = 4;
	const int iCols = 3;
	Mat m(iRows, iCols, CV_32FC1);

	m.at(0, 0) = 1;
	m.at(0, 1) = 8;
	m.at(0, 2) = 4;

	m.at(1, 0) = 2;
	m.at(1, 1) = 9;
	m.at(1, 2) = 3;

	m.at(2, 0) = 1;
	m.at(2, 1) = 9;
	m.at(2, 2) = 4;

	m.at(3, 0) = 6;
	m.at(3, 1) = 8;
	m.at(3, 2) = 5;

	Mat covar, mean;
	calcCovarMatrix(m, covar, mean, COVAR_NORMAL | COVAR_ROWS);
	cout << "m matrix is:\n" << m << endl;
	cout << "mean matrix is:\n" << mean << endl;
	cout << "covar matrix is:\n" << covar << endl;
	return;
}

//测试test_cartToPolar()
//将笛卡尔坐标转换为极坐标
/*
x coordinate is:
[1, 1, 0, -1, -1, -1, 0, 1]
y coordinate is:
[0, 1, 1, 1, 0, -1, -1, -1]
magnitude is:
[1, 1.4142135, 1, 1.4142135, 1, 1.4142135, 1, 1.4142135]
angle is:
[0, 44.990456, 90, 135.00955, 180, 224.99045, 270, 315.00955]
*/
void test_cartToPolar()
{
	const int iCols = 8;
	Mat x(1, iCols, CV_32FC1);
	Mat y(1, iCols, CV_32FC1);
	
	x.at(0, 0) = 1;
	y.at(0, 0) = 0;

	x.at(0, 1) = 1;
	y.at(0, 1) = 1;

	x.at(0, 2) = 0;
	y.at(0, 2) = 1;

	x.at(0, 3) = -1;
	y.at(0, 3) = 1;

	x.at(0, 4) = -1;
	y.at(0, 4) = 0;

	x.at(0, 5) = -1;
	y.at(0, 5) = -1;

	x.at(0, 6) = 0;
	y.at(0, 6) = -1;

	x.at(0, 7) = 1;
	y.at(0, 7) = -1;

	Mat mag, angle;
	//使用角度值进行表示
	//如果希望使用弧度制表示的话,那么将最后的flag设置为false即可
	cartToPolar(x, y, mag, angle, true);
	cout << "x coordinate is:\n" << x << endl;
	cout << "y coordinate is:\n" << y << endl;
	cout << "magnitude is:\n" << mag << endl;
	cout << "angle is:\n" << angle << endl;
	return;
}

//测试checkRange()
//bool checkRange(InputArray _src, bool quiet, Point* pt, double minVal, double maxVal)
//_src 输入的影像矩阵
//quiet 如果设置为false,那么超过范围的话,直接抛出异常;如果设置为true,那么函数结果返回false
//pt 如果不为NULL,那么返回第一个超过范围值的位置
//minVal 需要测试的最小值
//maxVal 需要测试的最大值
/*
m matrix is:
[1, 10, 100, 200, 150]
the matrix is [0,170)?: false
the first out of range location is:[3, 0]
*/
void test_checkRange()
{
	int iCols = 5;
	Mat m(1, iCols, CV_32FC1);
	m.at(0) = 1;
	m.at(1) = 10;
	m.at(2) = 100;
	m.at(3) = 200; 
	m.at(4) = 150;
	cv::Point pos;
	//检测是够在[0,170)之间
	bool bRet = checkRange(m, true, &pos, 0, 170);
	cout << "m matrix is:\n" << m << endl;
	cout << "the matrix is [0,170)?:\t";
	if (bRet)
	{
		cout << "true" << endl;
	}
	else
	{
		cout << "false" << endl;
	}
	cout << "the first out of range location is:" << pos << endl;
	return;
}

//测试compare()
//void compare(InputArray src1, InputArray src2, OutputArray dst, int cmpop);
//src1 输入需要比较第一个源影像
//src2 输入需要比较第二个源影像
//dst 输出的比较影像 如果true的话,输出是255;不然的话,输出是0
//cmpop 比较标志 
//CMP_EQ ==
//CMP_GT >
//CMP_GE >=
//CMP_LT <
//CMP_LE <=
//CMP_NE !=
/*
src1 matrix is:
[0, 1, 2;
1, 2, 3;
2, 3, 4]
src2 matrix is:
[0, 1, 2;
1, 2, 3;
2, 2, 1]
compare equal is:
[255, 255, 255;
255, 255, 255;
255,   0,   0]
*/
void test_compare()
{
	const int iRows = 3;
	const int iCols = 3;
	Mat src1(iRows, iCols, CV_32FC1);
	Mat src2(iRows, iCols, CV_32FC1);
	Mat dst;
	for (int i=0;i(i, j) = i + j;
			src2.at(i, j) = i + j;
		}
	}
	//稍微变更一下src2中的值
	src2.at(2, 2) = 1;
	src2.at(2, 1) = 2;
	compare(src1, src2, dst, CMP_EQ);
	cout << "src1 matrix is:\n" << src1 << endl;
	cout << "src2 matrix is:\n" << src2 << endl;
	cout << "compare equal is:\n" << dst << endl;
	return;
}

//测试completeSymm()
//完成对称矩阵
//CV_EXPORTS_W void completeSymm(InputOutputArray mtx, bool lowerToUpper = false);
//mtx 输入输出矩阵
//lowerToUpper 如果为false的话,那么将上三角矩阵赋值到下三角矩阵
//如果为true的话, 那么需要将下三角矩阵赋值到上三角矩阵
/*
src matrix is:
[  0,   1,   2,   3;
0,   2,   3,   4;
0,   0,   4,   5;
0,   0,   0,   6]
dst matrix is:
[  0,   1,   2,   3;
1,   2,   3,   4;
2,   3,   4,   5;
3,   4,   5,   6]
*/
void test_completeSymm()
{
	const int iRows = 4;
	const int iCols = 4;
	Mat m(iRows, iCols, CV_8UC1,Scalar(0));
	for (int  i=0;i(i, j) = i + j;
		}
	}
	cout << "src matrix is:\n" << m << endl;
	completeSymm(m,false);
	cout << "dst matrix is:\n" << m << endl;
	return;
}

//测试convertScaleAbs()
//void convertScaleAbs(InputArray src, OutputArray dst,double alpha = 1, double beta = 0);
//公式为|alpha*src+beta|
//src 源影像
//dst 目标影像
/*
src matrix is:
[0, -1, -2, -3;
-1, -2, -3, -4;
-2, -3, -4, -5;
-3, -4, -5, -6]
dst matrix is:
[ 10,  12,  14,  16;
12,  14,  16,  18;
14,  16,  18,  20;
16,  18,  20,  22]
*/
void test_convertScaleAbs()
{
	const int iRows = 4;
	const int iCols = 4;
	Mat m(iRows, iCols, CV_32FC1);
	for (int i = 0; i < iRows; ++i)
	{
		for (int j = 0; j < iCols; ++j)
		{
			m.at(i, j) = -(i + j);
		}
	}
	cout << "src matrix is:\n" << m << endl;
	Mat dst;
	//公式为
	//|m*2-10|
	convertScaleAbs(m, dst, 2, -10);
	cout << "dst matrix is:\n" << dst << endl;
	return;
}

//测试countNonZero()
//统计非0元素的个数
/*
src matrix is:
[0, 1, 2, 3;
0, 2, 3, 4;
0, 0, 4, 5;
0, 0, 0, 6]
matrix non zero is:
9
*/
void test_countNonZero()
{
	const int iRows = 4;
	const int iCols = 4;
	//建立一个上三角矩阵
	Mat m(iRows, iCols, CV_32FC1,Scalar(0));
	for (int i = 0; i < iRows; ++i)
	{
		for (int j = i; j < iCols; ++j)
		{
			m.at(i, j) = i+j;
		}
	}
	cout << "src matrix is:\n" << m << endl;
	int nCount = countNonZero(m);
	cout << "matrix non zero is:\n" << nCount << endl;
	return;
}

//测试 dct
//CV_EXPORTS_W void dct(InputArray src, OutputArray dst, int flags = 0);
//src 输入的影像
//dst 输出影像
//由于影像必须是偶数,所以需要先优化影像的尺寸
size_t getOptimalDCTSize(size_t N) { return 2 * getOptimalDFTSize((N + 1) / 2); }
void test_dct()
{
	Mat src = imread("C:/Users/GuSheng/Desktop/标准测试图片/三国杀/58d379286a8da.jpg");
	//如果影像为NULL的话,直接返回
	if (src.empty())
	{
		return;
	}
	//将彩色影像转换为灰度影像
	cvtColor(src, src, CV_BGR2GRAY);
	//优化后的影像宽度
	int nOptWidth = getOptimalDCTSize(src.cols);
	int nOptHeight = getOptimalDCTSize(src.rows);
	int nExtWidth = (nOptWidth - src.cols) / 2;
	int nExtHeight = (nOptHeight - src.rows) / 2;
	//优化边界
	copyMakeBorder(src, src, nExtHeight, nExtHeight, nExtWidth, nExtWidth, BORDER_CONSTANT, Scalar(0));
	//显示源影像
	namedWindow("src", WINDOW_AUTOSIZE);
	imshow("src", src);
	
	//将类型转换为float类型,将其归一化到[0,1]之间的数据
	src.convertTo(src, CV_32F,1/255.0);
	Mat dst;
	//进行dft变换
	dct(src, dst);
	namedWindow("dct", WINDOW_AUTOSIZE);
	imshow("dct", dst);
	waitKey(0);
	return;
}

//测试 idct
//离散余弦反变换
void test_idct()
{
	Mat src = imread("C:/Users/GuSheng/Desktop/标准测试图片/三国杀/58d379286a8da.jpg");
	//如果影像为NULL的话,直接返回
	if (src.empty())
	{
		return;
	}
	//将彩色影像转换为灰度影像
	cvtColor(src, src, CV_BGR2GRAY);
	//优化后的影像宽度
	int nOptWidth = getOptimalDCTSize(src.cols);
	int nOptHeight = getOptimalDCTSize(src.rows);
	int nExtWidth = (nOptWidth - src.cols) / 2;
	int nExtHeight = (nOptHeight - src.rows) / 2;
	//优化边界
	copyMakeBorder(src, src, nExtHeight, nExtHeight, nExtWidth, nExtWidth, BORDER_CONSTANT, Scalar(0));
	//显示源影像
	namedWindow("src", WINDOW_AUTOSIZE);
	imshow("src", src);

	//将类型转换为float类型,将其归一化到[0,1]之间的数据
	src.convertTo(src, CV_32F, 1 / 255.0);
	Mat dst;
	//进行dft变换
	dct(src, dst);
	namedWindow("dct", WINDOW_AUTOSIZE);
	imshow("dct", dst);

	//低通滤波处理,将100行和100列之后的值设置为0,以达到平滑影像的目的
	for (int i=100;i(i, j) = 0.0;
		}
	}
	//然后进行离散余弦函数的反变换
	Mat dst1;
	idct(dst, dst1);
	//将影像转换为8bits格式,缩放为255,设置范围为(0,255)之间,和之前对应的1/255.0相对应
	dst1.convertTo(dst1, CV_8U,255);
	namedWindow("dst1", WINDOW_AUTOSIZE);
	imshow("dst1", dst1);
	waitKey(0);
	return;
}

//测试dft 傅里叶变换
void test_dft()
{
	Mat src = imread("C:/Users/GuSheng/Desktop/标准测试图片/test1.jpg");
	if (src.empty())
	{
		//如果影像读取失败的话,直接返回
		return;
	}
	//转换为灰度影像
	cvtColor(src, src, CV_BGR2GRAY);
	//获取优化的傅里叶变换
	int iWidth = getOptimalDFTSize(src.cols);
	int iHeight = getOptimalDFTSize(src.rows);
	//重新组织影像
	copyMakeBorder(src, src, 0, 0, iHeight - src.rows, iWidth - src.cols, BORDER_CONSTANT, Scalar(0));
	//显示源影像
	namedWindow("src", WINDOW_AUTOSIZE);
	imshow("src", src);
	//组织傅里叶变换
	Mat plane[2] = { Mat_(src),Mat::zeros(src.size(),CV_32FC1) };
	//合并影像--合并为复数影像
	Mat ComplexImg;
	merge(plane, 2, ComplexImg);
	//进行傅里叶变换
	dft(ComplexImg, ComplexImg);
	//分离通道
	split(ComplexImg, plane);
	magnitude(plane[0], plane[1], plane[0]);
	Mat mag=plane[0];//幅度值
	mag += Scalar::all(1);
	log(mag, mag);
	mag = mag(Rect(0, 0, mag.cols&-2, mag.rows&-2));
	//中心化处理
	int cx = mag.cols / 2;
	int cy = mag.rows / 2;
	Mat temp;
	Mat q0(mag, Rect(0, 0, cx, cy));
	Mat q1(mag, Rect(cx, 0, cx, cy));
	Mat q2(mag, Rect(0, cy, cx, cy));
	Mat q3(mag, Rect(cx, cy, cx, cy));

	q0.copyTo(temp);
	q3.copyTo(q0);
	temp.copyTo(q3);

	q1.copyTo(temp);
	q2.copyTo(q1);
	temp.copyTo(q2);
	//归一化为0-1
	normalize(mag, mag, 0, 1, NORM_MINMAX);
	//转换为8bits影像,乘以255 是为了归一化到[0,255]之间
	mag.convertTo(mag, CV_8U, 255);
	threshold(mag,mag,175,255,THRESH_BINARY);
	namedWindow("dft", WINDOW_AUTOSIZE);
	imshow("dft", mag);
	waitKey(0);
	return;
}

//测试idft
void test_idft()
{
	//读取源影像
	Mat src = imread("C:/Users/GuSheng/Desktop/标准测试图片/lena.jpg");
	if (src.empty())
	{
		//如果影像读取失败的话,直接返回
		return;
	}
	//转换为灰度影像
	cvtColor(src, src, CV_BGR2GRAY);
	//计算优化后的影像宽度和高度
	int iWidth = getOptimalDFTSize(src.cols);
	int iHeight = getOptimalDFTSize(src.rows);
	//重新整合影像
	copyMakeBorder(src, src, 0, 0, iWidth - src.cols, iHeight - src.rows, BORDER_CONSTANT, Scalar(0));
	//显示源影像
	namedWindow("src", WINDOW_AUTOSIZE);
	imshow("src", src);
	//组合影像
	Mat planes[] = { Mat_(src),Mat::zeros(src.size(),CV_32FC1) };
	Mat magImage;
	merge(planes,2, magImage);
	//进行傅里叶比变换
	dft(magImage, magImage);
	//分割为实部和虚部部分
	split(magImage, planes);
	//对planes进行中心化处理
	planes[0] = planes[0](Rect(0, 0, planes[0].cols&-2, planes[0].rows&-2));
	planes[1] = planes[1](Rect(0, 0, planes[1].cols&-2, planes[1].rows&-2));
	//因为planes[0]影像储存和planes[1]的尺寸一定相同的,所以这里选择planes[0]
	int cx = planes[0].cols / 2;
	int cy = planes[0].rows / 2;
	//中心化 实数和虚数部分
	for (int i=0;i<2;++i)
	{
		Mat tmp;
		Mat q0 = planes[i](Rect(0, 0, cx, cy));
		Mat q1 = planes[i](Rect(cx, 0, cx, cy));
		Mat q2 = planes[i](Rect(0, cy, cx, cy));
		Mat q3 = planes[i](Rect(cx, cy, cx, cy));
		//中心化处理
		q0.copyTo(tmp);
		q3.copyTo(q0);
		tmp.copyTo(q3);

		q1.copyTo(tmp);
		q2.copyTo(q1);
		tmp.copyTo(q2);
	}
	//对数变换,为了显示
	Mat ShowImage;//为了显示而创建的影像,暂时先不动planes,因为后面我们要进行傅里叶的逆变换处理
	magnitude(planes[0], planes[1], ShowImage);
	ShowImage += Scalar::all(1);
	log(ShowImage, ShowImage);
	//归一化处理
	normalize(ShowImage, ShowImage, 0, 1, NORM_MINMAX);
	namedWindow("dft", WINDOW_AUTOSIZE);
	imshow("dft", ShowImage);

	//对频率域进行滤波处理
	//这里将频率域影像中心100*100的处理设置为0,也就是说低频部分过滤掉,高频部分进行保留,结果就是保留边缘部分
	//如果进行相反操作的话,那么效果就是平滑影像
// 	for (int i=0;i<2;++i)
// 	{
// 		//提取中心部分,设置为0
// 		Mat RImg = planes[i](Rect(cx - 50, cy - 50, 100, 100));
// 		RImg.setTo(Scalar(0));
// 	}
	//如果希望平滑的话
	for (int k=0;k<2;++k)
	{
		for (int i = 0; i < iHeight; ++i)
		{
			for (int j = 0; j < iWidth; ++j)
			{
				if (!((i > cx - 50) && (i < cx + 50) && (j > cy - 50) && j < cy + 50))
				{
					planes[k].at(i, j) = 0;
				}
			}
		}
	}
	
	//反中心化处理
	for (int i = 0; i < 2; ++i)
	{
		Mat tmp;
		Mat q0 = planes[i](Rect(0, 0, cx, cy));
		Mat q1 = planes[i](Rect(cx, 0, cx, cy));
		Mat q2 = planes[i](Rect(0, cy, cx, cy));
		Mat q3 = planes[i](Rect(cx, cy, cx, cy));
		//中心化处理
		q0.copyTo(tmp);
		q3.copyTo(q0);
		tmp.copyTo(q3);

		q1.copyTo(tmp);
		q2.copyTo(q1);
		tmp.copyTo(q2);
	}
	//合并操作
	Mat ResultImg;
	merge(planes, 2, ResultImg);
	idft(ResultImg, ResultImg);
	//分割为实部通道和虚部通道
	split(ResultImg, planes);
	magnitude(planes[0], planes[1], planes[0]);
	//归一化处理
	normalize(planes[0], planes[0], 0, 1, NORM_MINMAX);
	planes[0].convertTo(planes[0], CV_8U, 255);
	namedWindow("idft", WINDOW_AUTOSIZE);
	imshow("idft", planes[0]);
	waitKey(0);
	return;
}

int main()
{
	//修改默认的随机数
	//RNG rng(time(NULL));
	//theRNG() = rng;
	test_dft();
	return 0;
}	

 说明1

DCT离散余弦变换

相当于低通滤波器,主要的信息(低频部分)主要集中在左上角,因此可以用来平滑影像;另外保存左上角的主要信息,可以用来影像压缩处理。 (保留影像的大小和左上角的信息)

OpenCV 常用函数使用例子和说明_第1张图片 源影像 OpenCV 常用函数使用例子和说明_第2张图片 DCT变换之后的结果

 

 

 

 

 

 

 

 

 

 

 

 

 

 

OpenCV 常用函数使用例子和说明_第3张图片 使用test_idct()例子,低通滤波之后的结果

 说明2

DFT变换(傅里叶变换)

OpenCV 常用函数使用例子和说明_第4张图片 源影像1 OpenCV 常用函数使用例子和说明_第5张图片 源影像2

 

 

 

 

 

 

 

 

 

 

 

OpenCV 常用函数使用例子和说明_第6张图片 DFT变换的结果1 OpenCV 常用函数使用例子和说明_第7张图片 DFT变换的结果2

 

 

 

 

 

 

 

 

 

 

 

OpenCV 常用函数使用例子和说明_第8张图片 DFT变换之后,二值化的影像1 OpenCV 常用函数使用例子和说明_第9张图片 DFT变换之后,二值化的影像2

 

 

 

 

 

 

 

 

 

 

 

进行傅里叶变换,中心化之后,低频部分在中心部分(主要的纹理信息),高频部分分布在四周(边缘,噪声等)。

从上述影像的傅里叶变换的结果可以看出影像有明显的旋转,可以通过houghline提取线,进行影像的校正

 3.IDFT变换(傅里叶逆变换)

OpenCV 常用函数使用例子和说明_第10张图片 源影像 OpenCV 常用函数使用例子和说明_第11张图片 DFT变换之后的结果

 

OpenCV 常用函数使用例子和说明_第12张图片 IDFT变换之后的结果

 从上图可以看出

由于高频部分的丢失,会造成振铃效应

你可能感兴趣的:(OpenCV学习)