《数字图像处理》实验报告院系:XXXXX学号:XXXXXXX姓名:XXX指导老师:XX XX完成时间:2020.02.02题目一:(1)将宽为2n的正方形图像,用FFT算法从空域变换到频域,并用频域图像的模来进行显示;(2)使图像能量中心,对应到几何中心,并用频域图像的模来进行显示;(3)将频域图象,通过FFT逆变换到空域,并显示。
该题实现环境为操作系统:Windows 10 操作系统;编程环境:VS2013;内部核心处理算法库:OpenCV。
此题目的具体实现过程及其展示如下所示:}imshow("原始图像", srcImage);//将输入图像延扩到最佳的尺寸,边界用0补充int m = getOptimalDFTSize(srcImage.rows);int n = getOptimalDFTSize(srcImage.cols);//将添加的像素初始化为0.Mat padded;copyMakeBorder(srcImage, padded,0, m - srcImage.rows,0, n -srcImage.cols, BORDER_CONSTANT, Scalar::all(0));//为傅立叶变换的结果(实部和虚部)分配存储空间。
//将planes数组组合合并成一个多通道的数组complexIMat planes[]={ Mat_<float>(padded), Mat::zeros(padded.size(),CV_32F)};Mat complexI;merge(planes,2, complexI);//进行就地离散傅里叶变换dft(complexI, complexI);//将复数转换为幅值,即=> log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2)) split(complexI, planes);// 将多通道数组complexI分离成几个单通道数组,planes[0] = Re(DFT(I),//planes[1] = Im(DFT(I))magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitude Mat magnitudeImage = planes[0];//进行对数尺度(logarithmic scale)缩放magnitudeImage += Scalar::all(1);log(magnitudeImage, magnitudeImage);//求自然对数//剪切和重分布幅度图象限//若有奇数行或奇数列,进行频谱裁剪magnitudeImage = magnitudeImage(Rect(0,0, magnitudeImage.cols &-2, magnitudeImage.rows &-2));//重新排列傅立叶图像中的象限,使得原点位于图像中心int cx = magnitudeImage.cols /2;int cy = magnitudeImage.rows /2;Mat q0(magnitudeImage, Rect(0,0, cx, cy));// ROI区域的左上Mat q1(magnitudeImage, Rect(cx,0, cx, cy));// ROI区域的右上Mat q2(magnitudeImage, Rect(0, cy, cx, cy));// ROI区域的左下Mat q3(magnitudeImage, Rect(cx, cy, cx, cy));// ROI区域的右下//交换象限(左上与右下进行交换)Mat tmp;q0.copyTo(tmp);q3.copyTo(q0);tmp.copyTo(q3);//交换象限(右上与左下进行交换)q1.copyTo(tmp);q2.copyTo(q1);tmp.copyTo(q2);//归一化,用0到1之间的浮点值将矩阵变换为可视的图像格式normalize(magnitudeImage, magnitudeImage,0,1, CV_MINMAX);//显示效果图imshow("频域", magnitudeImage);//(3)频域-->空域Mat inversed;dft(complexI, inversed, DFT_INVERSE | DFT_REAL_OUTPUT);normalize(inversed, inversed,0,1, CV_MINMAX);imshow("空域", inversed);waitKey();return0;}其转换的原始图像及其效果图频域图像、空域图像分别如下图所示:(1)题目四:对MNIST手写数字数据库(可在网上搜索下载),编程实现来提取其链码。
该题实现的具体思路过程为:(1)将Mnist字库读取到以OpenCV里的Mat为储存单元的vector中;(2)使用findContours将链码保存在vector中;(3)输出链码。
ch3 =(i >>16)&255;ch4 =(i >>24)&255;return((int)ch1 <<24)+((int)ch2 <<16)+((int)ch3 <<8)+ ch4; }/*** 将Mnist数据库读取到OpenCV::Mat格式中* 格式:* magic number* number of images* rows* cols* a very very long vector contains all digits*/void read_Mnist(string filename, vector<Mat>&vec){ifstream file(filename, ios::binary);if(file.is_open()){int magic_number =0;int number_of_images =0;int n_rows =0;int n_cols =0;file.read((char*)&magic_number,sizeof(magic_number));magic_number = ReverseInt(magic_number);file.read((char*)&number_of_images,sizeof(number_of_images)); number_of_images = ReverseInt(number_of_images);file.read((char*)&n_rows,sizeof(n_rows));n_rows = ReverseInt(n_rows);file.read((char*)&n_cols,sizeof(n_cols));n_cols = ReverseInt(n_cols);for(int i =0; i < number_of_images;++i){cv::Mat tp = Mat::zeros(n_rows, n_cols, CV_8UC1);for(int r =0; r < n_rows;++r){for(int c =0; c < n_cols;++c){unsigned char temp =0;file.read((char*)&temp,sizeof(temp));tp.at<uchar>(r, c)=(int)temp;}}vec.push_back(tp);}}//if}int main(int argc,char**argv){int count =1;//存储Mnist字库vector<Mat> vec;//将Mnist字库读取到vector中read_Mnist("t10k-images.idx3-ubyte", vec);cout <<"共含有:"<< vec.size()<<"幅图片"<< endl;for(auto iter = vec.begin(); iter != vec.end(); iter++){cout <<"第"<< count++<<"幅图片..."<< endl;//显示Mnist字库imshow("Mnist",*iter);vector<vector<Point>> contours;//读取轮廓findContours(*iter, contours, CV_RETR_EXTERNAL, CV_CHAIN_CODE);//输出链码for(int i =0; i < contours.size(); i++){for(int j =0; j < contours[i].size(); j++)实现的效果图如下截图所示:根据输出结果,所得到的链码并不是所熟悉的4方向和8方向链码,由于时间仓促,进一步的完善会在接下来的学习过程中继续进行。