本文共 6717 字,大约阅读时间需要 22 分钟。
1) 将宽为2n的正方形图像,用FFT算法从空域变换到频域,并用频域图像的模来进行显示。
2) 使图像能量中心,对应到几何中心,并用频域图像的模来进行显示。
3)将频域图象,通过FFT逆变换到空域,并显示。
#include#include #include using namespace cv;using namespace std;int main(){ //以灰度模式读取原始图像并显示 Mat srcImage = imread("lena.png", 0); if (srcImage.empty()) { cout << "打开图像失败!" << endl; return -1; } 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数组组合合并成一个多通道的数组complexI Mat planes[] = { Mat_ (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); //频域-->空域 Mat inversed; dft(complexI, inversed, DFT_INVERSE | DFT_REAL_OUTPUT); normalize(inversed, inversed, 0, 1, CV_MINMAX); imshow("空域", inversed); waitKey(); return 0;}
#include#include #include #include using namespace std;using namespace cv;int ContrastValue; //对比度值int BrightValue; //亮度值Mat src, dst;//改变图像对比度和亮度值的回调函数static void ContrastAndBright(int, void *){ //创建窗口 namedWindow("【原始图窗口】", WINDOW_AUTOSIZE); for (int y = 0; y < src.rows; y++) { for (int x = 0; x < src.cols; x++) { for (int c = 0; c < 3; c++) { dst.at (y, x)[c] = saturate_cast ((ContrastValue * 0.01)*(src.at (y, x)[c]) + BrightValue); } } } //显示图像 imshow("【原始图窗口】", src); imshow("【效果图窗口】", dst);}int main(int argc, char *argv[]){ //打开图像 src = imread("two.png"); if (src.empty()) { cout << "打开图像失败!" << endl; return -1; } //中值滤波去噪 medianBlur(src, src, 3); dst = Mat::zeros(src.size(), src.type()); //设定对比度和亮度的初值 ContrastValue = 80; BrightValue = 80; //创建窗口 namedWindow("【效果图窗口】", WINDOW_AUTOSIZE); //创建轨迹条 createTrackbar("对比度:", "【效果图窗口】", &ContrastValue, 300, ContrastAndBright); createTrackbar("亮 度:", "【效果图窗口】", &BrightValue, 200, ContrastAndBright); //调用回调函数 ContrastAndBright(ContrastValue, 0); ContrastAndBright(BrightValue, 0); //等待用户按键,起到暂停的作用 waitKey(); return 0;}
对于下面这幅图像,编程实现染色体计数,并附简要处理流程说明。
#include#include #include #include #include using namespace std;using namespace cv;int main(int argc, char **argv){ Mat gray, src, dst; //打开图像 src = imread("image.png"); if (src.empty()) { cout << "打开图像失败!" << endl; return -1; } cout << "rows = " << src.rows << endl; cout << "cols = " << src.cols << endl; //转换为灰度图 cvtColor(src, gray, CV_BGR2GRAY); //中值滤波 medianBlur(gray, gray, 7); //图像二值化 threshold(gray, dst, 170, 255, THRESH_BINARY); //腐蚀,默认内核3*3 erode(dst, dst, Mat()); //erode(dst, dst, Mat()); Mat canny_output; vector > contours; vector hierarchy; //画轮廓线 Canny(dst, canny_output, 100, 100 * 2, 3); imwrite("data.png", dst); //检测轮廓 findContours(dst, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); cout << "一共检测到染色体数目:" << contours.size() - 1 << endl; /* for (int i = 0; i < contours.size(); i++) { for (int j = 0; j < contours[i].size(); j++) { cout << contours[i][j] << " "; } cout << ";" << endl; } */ //显示图片 imshow("src", src); imshow("canny_output", canny_output); //将图片保存到文件 imwrite("dst.png", canny_output); //等待用户输入 waitKey(); return 0;}//高斯滤波//GaussianBlur(gray, gray, Size(5, 5), 0, 0);//双边滤波//bilateralFilter(gray, gray, 5, 10.0, 2.0);//中值滤波//medianBlur(gray, gray, 3);
#include详细说明:#include #include #include #include #include #include using namespace std;using namespace cv;//格式转换int ReverseInt(int i){ unsigned char ch1, ch2, ch3, ch4; ch1 = i & 255; ch2 = (i >> 8) & 255; 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 &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 (r, c) = (int)temp; } } vec.push_back(tp); } }//if}int main(int argc, char **argv){ int count = 1; //存储Mnist字库 vector 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 > 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++) { cout << contours[i][j]; } cout << endl; } contours.clear(); waitKey(1000); } waitKey(); return 0;}