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离散余弦变换
相当于低通滤波器,主要的信息(低频部分)主要集中在左上角,因此可以用来平滑影像;另外保存左上角的主要信息,可以用来影像压缩处理。 (保留影像的大小和左上角的信息)
源影像 DCT变换之后的结果
说明2
DFT变换(傅里叶变换)
源影像1 源影像2
DFT变换的结果1 DFT变换的结果2
DFT变换之后,二值化的影像1 DFT变换之后,二值化的影像2
进行傅里叶变换,中心化之后,低频部分在中心部分(主要的纹理信息),高频部分分布在四周(边缘,噪声等)。
从上述影像的傅里叶变换的结果可以看出影像有明显的旋转,可以通过houghline提取线,进行影像的校正
3.IDFT变换(傅里叶逆变换)
源影像 DFT变换之后的结果
从上图可以看出
由于高频部分的丢失,会造成振铃效应