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

离散傅里叶变换

 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 }

 

上一篇:mean = np.array([0.485,0.456,0.406]) std = np.array([0.229,0.224,0.225])


下一篇:kafka在zookeeper中存储结构