ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

OpenCV学习(5)--离散傅里叶变换、滤波、侵蚀、扩张

2020-10-05 19:03:33  阅读:160  来源: 互联网

标签:src return Mat -- 滤波 magI OpenCV int cv


离散傅里叶变换

 1 // 离散傅里叶变换
 2 /*
 3 离散傅里叶变换(DFT),是傅里叶变换在时域和频域上都呈现离散的形式,将时域信号
 4 的采样变换为在离散时间傅里叶变换(DTFT)频域的采样。在形式上,变换两端(时域和
 5 频域上)的序列是有限长的,而实际上这两组序列都应当被认为是离散周期信号的主值序
 6 列。即使对有限长的离散信号作DFT,也应当将其看作经过周期延拓成为周期信号再作变
 7 换。在实际应用中通常采用快速傅里叶变换以高效计算DFT。
 8 */
 9 int dftExample(void) {
10     cv::Mat image = cv::imread("sky.jpg", cv::IMREAD_COLOR);
11     //assert(!image.empty(), "Failed read!");
12     cv::Mat padded;
13     // getOptimalDFTSize函数返回给定向量尺寸的傅里叶最优尺寸大小。
14     // 此函数的唯一一个参数为int类型的vecsize,向量尺寸,即图片的rows、cols
15     int m = cv::getOptimalDFTSize(image.rows);
16     int n = cv::getOptimalDFTSize(image.cols);
17     // 扩展输入图像image尺寸,在边缘加0值
18     // 滤波 https://blog.csdn.net/qianqing13579/article/details/42323397
19     cv::copyMakeBorder(image, padded, 0, m - image.rows, 0, n - image.cols, cv::BORDER_CONSTANT, cv::Scalar::all(0));
20 
21     cv::Mat planes[] = { cv::Mat_<float>(padded), cv::Mat::zeros(padded.size(), CV_32F) };
22     cv::Mat complexImage;
23     cv::merge(planes, 2, complexImage);  // 图像通道的合并
24 
25     cv::dft(complexImage, complexImage); // 对一维或者二维浮点数数组进行正向或反向离散傅里叶变换
26     // 运行到此处 抛出异常 程序终止了
27 
28 
29 
30     cv::split(complexImage, planes);
31     // 计算二维矢量的幅值:magnitude()函数
32     // https://blog.csdn.net/qq_31935691/article/details/71699582
33     cv::magnitude(planes[0], planes[1], planes[0]);
34     cv::Mat magI = planes[0];
35     magI += cv::Scalar::all(1);
36     cv::log(magI, magI);
37 
38     magI = magI(cv::Rect(0, 0, magI.cols & -2, magI.rows & -2));
39     int cx = magI.cols / 2;
40     int cy = magI.rows / 2;
41 
42     // 将magI从横竖中间线切开 分为四部分
43     cv::Mat q0(magI, cv::Rect(0, 0, cx, cy));     // 左上
44     cv::Mat q1(magI, cv::Rect(cx, 0, cx, cy));    // 右上
45     cv::Mat q2(magI, cv::Rect(0, cy, cx, cy));    // 左下
46     cv::Mat q3(magI, cv::Rect(cx, cy, cx, cy));   // 右下
47 
48     cv::Mat tmp;
49     // 交换q0 q3
50     q0.copyTo(tmp);
51     q3.copyTo(q0);
52     tmp.copyTo(q3);
53     // 交换q1 q2
54     q1.copyTo(tmp);
55     q2.copyTo(q1);
56     tmp.copyTo(q2);
57 
58     // 归一化数据。该函数分为范围归一化与数据值归一化。
59     // https://blog.csdn.net/cosmispower/article/details/64457406
60     cv::normalize(magI, magI, 0, 1, cv::NORM_MINMAX);
61 
62     cv::imshow("Input Image", image);
63     cv::imshow("Spectrum Magnitude", magI);
64 
65     cv::waitKey(0);
66     return 0;
67 }
// OpenCV中的英特尔IPP异步C/C++库
void ippasyncExample() {

}

// 使用OpenCV parallel_for 来并行化代码
void parallelForExample() {

}

滤波操作

 1 class SmoothingDemo {
 2     // OpenCV平滑图像
 3     // 平滑 也称为模糊 是一种常用的图像处理操作 使用平滑的原因有很多 此处是为了减少噪音
 4     // 要执行平滑操作 需要对图像应用滤波器
 5     // 有多种类型的滤波器 最常见的是线性滤波器 除此之外还有
 6     // 归一化框滤波器 
 7     // 高斯滤波器
 8     // 中值滤波器
 9     // 双边滤波器
10 public:
11     SmoothingDemo() {
12         windowName = "Smoothing Demo";
13         cv::namedWindow(windowName, cv::WINDOW_AUTOSIZE);
14     }
15 
16     int showDifferentSmoothing() {
17         src = cv::imread("angel.jpg", cv::IMREAD_COLOR);
18         // show original image
19         if (displayCaption("Original Image") != 0)
20             return 0;
21 
22         dst = src.clone();
23         if (displayDst(DELAY_CAPTION) != 0)  // 展示clone后的目标图片
24             return 0;
25 
26         // // 归一化滤波
27         if (displayCaption("Homogeneous Blur") != 0)
28             return 0;
29         for (int i = 1; i < MAX_KERNEL_LENGTH; i += 2) {
30             cv::blur(src, dst, cv::Size(i, i), cv::Point(-1, -1)); // https://blog.csdn.net/duwangthefirst/article/details/79971322
31             if (displayDst(DELAY_BLUR) != 0)
32                 return 0;
33         }
34 
35         // 高斯滤波
36         if (displayCaption("Gaussian Blur") != 0)
37             return 0;
38         for (int i = 1; i < MAX_KERNEL_LENGTH; i += 2) {
39             cv::GaussianBlur(src, dst, cv::Size(i, i), 0, 0);  // https://blog.csdn.net/cindywry/article/details/102837184
40             if (displayDst(DELAY_BLUR) != 0)
41                 return 0;
42         }
43 
44         // 中值滤波
45         if (displayCaption("Median Blur") != 0)
46             return 0;
47         for (int i = 1; i < MAX_KERNEL_LENGTH; i += 2) {
48             cv::medianBlur(src, dst, i);  // https://blog.csdn.net/charce_you/article/details/100177628
49             if (displayDst(DELAY_BLUR) != 0)
50                 return 0;
51         }
52 
53         // 双边滤波
54         if (displayCaption("Bilateral Blur") != 0)
55             return 0;
56         for (int i = 1; i < MAX_KERNEL_LENGTH; i += 2) {
57             cv::bilateralFilter(src, dst, i, i * 2, i / 2);  // https://blog.csdn.net/keith_bb/article/details/54427779
58             if (displayDst(DELAY_BLUR) != 0)
59                 return 0;
60         }
61 
62         // 随着上述各个for循环的进行 i 的增大 图片越来越模糊
63 
64         displayCaption("End: Press a key!");
65         cv::waitKey(0);
66         return 0;
67     }
68 
69 private:
70     int displayCaption(const char* caption) {
71         dst = cv::Mat::zeros(src.size(), src.type());
72         cv::putText(dst, caption, cv::Point(src.cols / 4, src.rows / 2), cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255));
73         cv::imshow(windowName, dst);
74         int c = cv::waitKey(DELAY_CAPTION);
75 
76         if (c >= 0)
77             return -1;
78         return 0;
79     }
80 
81     int displayDst(int delay) {
82         cv::imshow(windowName, dst);
83         int c = cv::waitKey(delay);
84 
85         if (c >= 0)
86             return -1;
87         return 0;
88     }
89 
90     static const int DELAY_CAPTION = 1500;
91     static const int DELAY_BLUR = 100;
92     static const int MAX_KERNEL_LENGTH = 31;
93     string windowName;
94     cv::Mat src;
95     cv::Mat dst;
96 };

侵蚀、扩张

 1 // 侵蚀 使图像中暗去增长
 2 // 扩张 使图像中亮区增长
 3 cv::Mat src;
 4 cv::Mat erosionDst;
 5 cv::Mat dilationDst;
 6 int erosionElem = 0;
 7 int erosionSize = 0;
 8 int dilationElem = 0;
 9 int dilationSize = 0;
10 const int maxElem = 2;
11 const int maxKernelSize = 21;
12 
13 static void Erosion(int, void*) {
14     int erosionType = 0;
15     if (erosionElem == 0)
16         erosionType = cv::MORPH_RECT;
17     else if (erosionElem == 1)
18         erosionType = cv::MORPH_CROSS;
19     else if (erosionElem == 2)
20         erosionType = cv::MORPH_ELLIPSE;
21     else {}
22 
23     // cv::getStructuringElement()返回指定形状和尺寸的结构元素
24     // https://blog.csdn.net/kksc1099054857/article/details/76569718
25     cv::Mat element = cv::getStructuringElement(erosionType, cv::Size(2 * erosionSize + 1, 2 * erosionSize + 1), cv::Point(erosionSize, erosionSize));
26     // erode()函数可以对输入图像用特定结构元素进行腐蚀操作,该结构元素确定腐蚀操作过程中的邻域的形状,各点像素值将被替换为对应邻域上的最小值
27     // https://blog.csdn.net/duwangthefirst/article/details/79999856
28     cv::erode(src, erosionDst, element);
29     cv::imshow("Erosion Demo", erosionDst);
30 }
31 
32 static void Dilation(int, void*) {
33     int dilationType = 0;
34     if (dilationElem == 0)
35         dilationType = cv::MORPH_RECT;
36     else if (dilationElem == 1)
37         dilationType = cv::MORPH_CROSS;
38     else if (dilationElem == 2)
39         dilationType = cv::MORPH_ELLIPSE;
40     else {}
41 
42     cv::Mat element = cv::getStructuringElement(dilationType, cv::Size(2 * dilationSize + 1, 2 * dilationSize + 1), cv::Point(dilationSize, dilationSize));
43     // dilate()函数可以对输入图像用特定结构元素进行膨胀操作,该结构元素确定膨胀操作过程中的邻域的形状,各点像素值将被替换为对应邻域上的最大值:
44     // https://blog.csdn.net/duwangthefirst/article/details/80001106
45     cv::dilate(src, dilationDst, element);
46     cv::imshow("Dilation Demo", dilationDst);
47 }
48 
49 int ErosionAndDilationExample(void) {
50     src = cv::imread("blackWord.png", cv::IMREAD_COLOR);
51     if (src.empty()) {
52         std::cout << "Failed Read!" << std::endl;
53         return -1;
54     }
55 
56     cv::namedWindow("Erosion Demo", cv::WINDOW_AUTOSIZE);
57     cv::namedWindow("Dilation Demo", cv::WINDOW_AUTOSIZE);
58 
59     // 此处最后一个参数不匹配?
60     // 但是这个是void Fun(int, void*);类型的
61     cv::createTrackbar("Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Erosion Demo", &erosionElem, maxElem, Erosion);
62     cv::createTrackbar("Kernel size:\n 2n + 1", "Erosion Demo", &erosionSize, maxKernelSize, Erosion);
63 
64     cv::createTrackbar("Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Dilation Demo", &dilationElem, maxElem, Dilation);
65     cv::createTrackbar("Kernel size:\n 2n + 1", "Dilation Demo", &dilationSize, maxKernelSize, Dilation);
66 
67     Erosion(0, 0);
68     Dilation(0, 0);
69     cv::waitKey(0);
70     return 0;
71 }

 

标签:src,return,Mat,--,滤波,magI,OpenCV,int,cv
来源: https://www.cnblogs.com/lnlin/p/13771001.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有