-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
113 lines (94 loc) · 3 KB
/
main.cpp
File metadata and controls
113 lines (94 loc) · 3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include "opencv2/core.hpp"
#include "opencv2/core/base.hpp"
#include "opencv2/core/hal/interface.h"
#include "opencv2/core/mat.hpp"
#include "opencv2/highgui.hpp"
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <string>
#include <vector>
// Add Gaussian Noise
cv::Mat addGaussianNoise(const cv::Mat &image, double mean, double stddev) {
// only supports grayscale uchar for now
CV_Assert(image.type() == CV_8U);
cv::Mat floatImg;
image.convertTo(floatImg, CV_32F);
cv::Mat noise(floatImg.size(), CV_32F);
cv::randn(noise, mean, stddev);
return floatImg + noise;
}
struct Options {
std::string imagePath;
int sampleSize = 5;
bool showRandom = false;
};
Options parseArgs(int argc, char *argv[]) {
Options opts;
for (int i = 0; i < argc; i++) {
std::string arg = argv[i];
if ((arg == "-i" || arg == "--image") && i + 1 < argc) {
opts.imagePath = argv[++i];
} else if (arg == "--sample-size" && i + 1 < argc) {
opts.sampleSize = std::stoi(argv[++i]);
} else if (arg == "--show-random-noisy-image") {
opts.showRandom = true;
}
}
return opts;
}
int main(int argc, char *argv[]) {
auto opts = parseArgs(argc, argv);
if (opts.imagePath.empty()) {
std::cerr << "Usage: " << argv[0]
<< " -i <image_path> [--samples-size N] [--show-random-noisy-image]\n";
return 1;
}
cv::Mat img = cv::imread(opts.imagePath, cv::IMREAD_COLOR);
if (img.empty()) {
std::cerr << "Error: No image found.\n";
return -1;
}
// Convert image to grayscale
cv::Mat grayImage;
cv::cvtColor(img, grayImage, cv::COLOR_BGR2GRAY);
// Resize (400x300)
cv::Mat resized_img;
cv::Size new_size(800, 600);
resize(grayImage, resized_img, new_size, 0, 0, cv::INTER_LINEAR);
// generate noisy samples
std::vector<cv::Mat> noisySamples;
noisySamples.reserve(opts.sampleSize);
for (int i = 0; i < opts.sampleSize; ++i)
noisySamples.push_back(addGaussianNoise(resized_img, 0, 20));
/*
* Noise Reduction
*
* Uses Central Limit Theorem to reduce noise in the image
*/
cv::Mat result(resized_img.size(), CV_32F, cv::Scalar(0));
for (int i = 0; i < opts.sampleSize; ++i) {
result += noisySamples[i];
}
result /= opts.sampleSize;
result.convertTo(result, CV_8U);
// --show-ramdom-noisy-image: true
// show random noisy sample
if (opts.showRandom && !noisySamples.empty()) {
std::srand(static_cast<unsigned>(std::time(nullptr)));
int idx = std::rand() % noisySamples.size();
cv::Mat random_sample;
noisySamples[idx].convertTo(random_sample, CV_8U);
cv::imshow("Random Noisy Sample", random_sample);
}
cv::imshow("Denoised Result", result);
int key;
for (;;) {
key = cv::waitKey(20);
if (key == 27 || key == 'q') {
break;
}
}
return 0;
}