Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "stdafx.h"
- #define _USE_MATH_DEFINES
- #include <vector>
- #include <complex>
- #include <iostream>
- #include "CImg.h"
- #include <cmath>
- using namespace std;
- using namespace cimg_library;
- CImg<double> horizontalFlip(CImg<double> image) {
- for (int i = 0; i < image.width() / 2; i++) {
- for (int j = 0; j < image.height(); j++) {
- for (int z = 0; z < image.spectrum(); z++) {
- double temp = image(i, j, z);
- image(i, j, z) = image(image.width() - 1 - i, j, z);
- image(image.width() - 1 - i, j, z) = temp;
- }
- }
- }
- return image;
- }
- CImg<double> verticalFlip(CImg<double> image) {
- for (int i = 0; i < image.width(); i++) {
- for (int j = 0; j < image.height() / 2; j++) {
- for (int z = 0; z < image.spectrum(); z++) {
- double temp = image(i, j, z);
- image(i, j, z) = image(i, image.height() - j - 1, z);
- image(i, image.height() - j - 1, z) = temp;
- }
- }
- }
- return image;
- }
- CImg<double> diagonalFlip(CImg<double> image) {
- image = horizontalFlip(image);
- image = verticalFlip(image);
- return image;
- }
- // ----------------------------------------------------------------------------------------------------
- // task 4
- // ==============================================================================================================================
- // fast
- void fft1d(vector< complex<double> > &input, bool inverse)
- {
- const int N = input.size();
- const complex<double> I = (0.0, 1.0);
- if (N == 1) return;
- else {
- vector< complex<double> > left, right, temp1, temp2;
- for (int i = 0; i < (N / 2); ++i)
- {
- left.push_back(input[i]);
- right.push_back((input[N / 2 + i]));
- }
- for (int n = 0; n < N / 2; ++n)
- {
- temp1.push_back(left[n] + right[n]);
- temp2.push_back(left[n] - right[n]);
- }
- for (int n = 0; n < N / 2; n++) {
- //double angle = 0;
- //angle = -2 * M_PI*n / N;
- double angle = (inverse ? 2 * M_PI * n * 1 / N : -2 * M_PI * n * 1 / N);
- double real = cos(angle);
- double imaginary = sin(angle);
- complex<double> W(real, imaginary);
- temp2[n] *= W;
- }
- fft1d(temp1, inverse);
- fft1d(temp2, inverse);
- int j = 0;
- for (int k = 0; k<N / 2; ++k)
- {
- input[j] = temp1[k];
- input[j + 1] = temp2[k];
- j += 2;
- }
- }
- }
- // ==============================================================================================================================
- // slow
- vector< complex<double> > dft(vector< complex<double> > input, bool inverse) {
- vector< complex<double> > result;
- const int N = input.size();
- for (int n = 0; n < N; n++) {
- complex<double> sum(0.0, 0.0);
- for (int k = 0; k < N; k++) {
- double angle = 0;
- if (inverse == false) {
- angle = -2 * M_PI*k*n / N;
- }
- else {
- angle = 2 * M_PI*k*n / N;
- }
- double tempReal = cos(angle);
- double tempImaginary = sin(angle);
- complex<double> factor(tempReal, tempImaginary);
- sum += input[k] * factor;
- }
- result.push_back(sum);
- }
- return result;
- }
- // ==============================================================================================================================
- vector<vector<complex<double> > > fourierTransformTwoDimensional(vector<vector<complex<double> > > input, CImg<double>&image, bool useFastAlgorithm, bool inverse)
- {
- vector<vector<complex<double> > > matrix1, matrix2;
- for (int j = 0; j < image.height(); j++)
- {
- vector<complex<double> > row;
- for (int i = 0; i < image.width(); i++)
- {
- row.push_back(input[i][j]);
- }
- fft1d(row, inverse);
- matrix1.push_back(row);
- }
- for (int j = 0; j < image.width(); j++)
- {
- vector<complex<double> > column;
- for (int i = 0; i < image.height(); i++)
- {
- column.push_back(matrix1[i][j]);
- }
- fft1d(column, inverse);
- matrix2.push_back(column);
- }
- return matrix2;
- }
- // ==============================================================================================================================
- // FUNKCJE DO RYSOWANIA I OBLICZANIA
- void calculateMagnitude(vector<vector<complex<double> > >* input, CImg<double>&image) {
- double realPart, imaginaryPart;
- complex<double> temp;
- for (int j = 0; j < image.width(); j++) {
- for (int i = 0; i < image.height(); i++) {
- temp = input->at(j).at(i);
- realPart = temp.real();
- imaginaryPart = temp.imag();
- input->at(j).at(i) = complex<double>(sqrt(realPart*realPart + imaginaryPart*imaginaryPart), imaginaryPart);
- }
- }
- }
- void swap_quarters(vector<vector<complex<double> > >* input) {
- const int N = input->size();
- complex<double> temp;
- for (int i = 0; i < N / 2; i++) {
- for (int j = 0; j < N / 2; j++) {
- temp = input->at(i).at(j);
- input->at(i).at(j) = input->at(i + N / 2).at(j + N / 2);
- input->at(i + N / 2).at(j + N / 2) = temp;
- temp = input->at(i + N / 2).at(j);
- input->at(i + N / 2).at(j) = input->at(i).at(j + N / 2);
- input->at(i).at(j + N / 2) = temp;
- }
- }
- }
- void logVector(vector<vector<complex<double> > >* input) {
- const int N = input->size();
- double logReal, logImag;
- for (int j = 0; j < N; j++) {
- for (int i = 0; i < N; i++) {
- logReal = abs(input->at(j).at(i).real());
- logImag = abs(input->at(j).at(i).imag());
- if (logReal != 0) logReal = log(logReal);
- if (logImag != 0) logImag = log(logImag);
- input->at(j).at(i) = complex<double>(logReal, logImag);
- }
- }
- }
- void scaleAndDraw(vector<vector<complex<double> > >* input, CImg<double>&image, CImg<double>* newWindow) {
- double real = 0, imaginary = 0, scaleReal = 1, scaleImag = 0, maxReal = 0, maxImag = 0;
- const int N = input->size();
- for (int j = 0; j < N; j++) {
- for (int i = 0; i < N; i++) {
- real = input->at(j).at(i).real();
- imaginary = input->at(j).at(i).imag();
- if (real > maxReal) {
- maxReal = real;
- }
- if (imaginary > maxImag) {
- maxImag = imaginary;
- }
- }
- }
- scaleReal = 255 / maxReal;
- scaleImag = 255 / maxImag;
- double value = 0;
- complex<double> temp;
- for (int j = 0; j < image.width(); j++) {
- for (int i = 0; i < image.height(); i++) {
- temp = input->at(j).at(i);
- real = scaleReal*temp.real();
- imaginary = scaleImag*temp.imag();
- if (real > 255) {
- real = 255;
- }
- else if (real < 0) {
- real = 0;
- }
- newWindow->atXYZC(j, i, 0, 0) = newWindow->atXYZC(j, i, 0, 1) = newWindow->atXYZC(j, i, 0, 2) = real;
- }
- }
- }
- void CImgToVector(CImg<double> &image, vector<vector<complex<double> > >* imageVector) {
- vector<complex<double> > row;
- for (int i = 0; i < image.height(); i++) {
- for (int j = 0; j < image.width(); j++) {
- row.push_back(complex<double>(image._atXYZC(i, j, 0, 0)*1.0, 0.0));
- }
- imageVector->push_back(row);
- row.clear();
- }
- }
- // ==============================================================================================================================
- // FOURIER
- CImg<double> fourier(CImg<double> &image, bool useFastAlgorithm) {
- CImg<double> image_output(image.width(), image.height(), image.depth(), image.spectrum());
- CImg<double> spectrum(image.width(), image.height(), image.depth(), image.spectrum());
- vector<vector<complex<double> > > img, imageSpectrum;
- CImgToVector(image, &img);
- imageSpectrum = fourierTransformTwoDimensional(img, image, useFastAlgorithm, false);
- swap_quarters(&imageSpectrum);
- calculateMagnitude(&imageSpectrum, image);
- logVector(&imageSpectrum);
- scaleAndDraw(&imageSpectrum, image, &spectrum);
- return spectrum;
- }
- // ==============================================================================================================================
- // LOW PASS FILTER - HIGH CUT FILTER
- CImg<double> lowPass(CImg<double> &image, int radius) {
- CImg<double> image_output(image.width(), image.height(), image.depth(), image.spectrum(), 255);
- CImg<double> spectrum(image.width(), image.height(), image.depth(), image.spectrum(), 255);
- vector<vector<complex<double> > > img;
- vector<vector<complex<double> > > imageSpectrum;
- CImgToVector(image, &img);
- imageSpectrum = fourierTransformTwoDimensional(img, image, true, false);
- swap_quarters(&imageSpectrum);
- double distance;
- for (int j = 0; j<image.width(); j++) {
- for (int i = 0; i<image.height(); i++) {
- for (int k = 0; k<image.spectrum(); k++) {
- double temp1 = (j - image.width() / 2)*(j - image.width() / 2);
- double temp2 = (i - image.height() / 2)*(i - image.height() / 2);
- distance = sqrt(temp1 + temp2);
- if (distance <= radius) {}
- else
- imageSpectrum[j][i] = 0.0;
- }
- }
- }
- swap_quarters(&imageSpectrum);
- img = fourierTransformTwoDimensional(imageSpectrum, image, true, true);
- scaleAndDraw(&img, image, &image_output);
- return image_output;
- }
- // ==============================================================================================================================
- // HIGH PASS FILTER - LOW CUT FILTER
- CImg<double> highPass(CImg<double> &image, int radius) {
- CImg<double> image_output(image.width(), image.height(), image.depth(), image.spectrum(), 255);
- CImg<double> spectrum(image.width(), image.height(), image.depth(), image.spectrum(), 255);
- vector<vector<complex<double> > > img;
- vector<vector<complex<double> > > imageSpectrum;
- CImgToVector(image, &img);
- imageSpectrum = fourierTransformTwoDimensional(img, image, true, false);
- swap_quarters(&imageSpectrum);
- complex<double> dcComponent = imageSpectrum[image.height() / 2][image.width() / 2];
- double distance;
- for (int j = 0; j<image.width(); j++) {
- for (int i = 0; i<image.height(); i++) {
- for (int k = 0; k<image.spectrum(); k++) {
- double temp1 = (j - image.width() / 2)*(j - image.width() / 2);
- double temp2 = (i - image.height() / 2)*(i - image.height() / 2);
- distance = sqrt(temp1 + temp2);
- if (distance <= radius) {
- imageSpectrum[j][i] = 0.0;
- }
- }
- }
- }
- imageSpectrum[image.height() / 2][image.width() / 2] = dcComponent;
- swap_quarters(&imageSpectrum);
- img = fourierTransformTwoDimensional(imageSpectrum, image, true, true);
- scaleAndDraw(&img, image, &image_output);
- return image_output;
- }
- // ==============================================================================================================================
- // BAND PASS FILTER
- CImg<double> bandPass(CImg<double>&image, int min, int max) {
- CImg<double> image_output(image.width(), image.height(), image.depth(), image.spectrum(), 255);
- CImg<double> spectrum(image.width(), image.height(), image.depth(), image.spectrum(), 255);
- vector<vector<complex<double> > > img;
- vector<vector<complex<double> > > imageSpectrum;
- CImgToVector(image, &img);
- imageSpectrum = fourierTransformTwoDimensional(img, image, true, false);
- swap_quarters(&imageSpectrum);
- // dc component
- complex<double> dcComponent = imageSpectrum[image.height() / 2][image.width() / 2];
- double distance;
- for (int j = 0; j<image.width(); j++) {
- for (int i = 0; i<image.height(); i++) {
- for (int k = 0; k<image.spectrum(); k++) {
- double temp1 = (j - image.width() / 2)*(j - image.width() / 2);
- double temp2 = (i - image.height() / 2)*(i - image.height() / 2);
- distance = sqrt(temp1 + temp2);
- if ((distance < min) || (distance > max))
- imageSpectrum[j][i] = 0;
- }
- }
- }
- imageSpectrum[image.height() / 2][image.width() / 2] = dcComponent;
- swap_quarters(&imageSpectrum);
- img = fourierTransformTwoDimensional(imageSpectrum, image, true, true);
- scaleAndDraw(&img, image, &image_output);
- return image_output;
- }
- // ==============================================================================================================================
- // BAND CUT FILTER
- CImg<double> bandCut(CImg<double>&image, int min, int max) {
- CImg<double> image_output(image.width(), image.height(), image.depth(), image.spectrum(), 255);
- CImg<double> spectrum(image.width(), image.height(), image.depth(), image.spectrum(), 255);
- vector<vector<complex<double> > > img, imageSpectrum;
- CImgToVector(image, &img);
- imageSpectrum = fourierTransformTwoDimensional(img, image, true, false);
- swap_quarters(&imageSpectrum);
- complex<double> dcComponent = imageSpectrum[image.height() / 2][image.width() / 2];
- double distance;
- for (int j = 0; j<image.width(); j++) {
- for (int i = 0; i<image.height(); i++) {
- for (int k = 0; k<image.spectrum(); k++) {
- double temp1 = (j - image.width() / 2)*(j - image.width() / 2);
- double temp2 = (i - image.height() / 2)*(i - image.height() / 2);
- distance = sqrt(temp1 + temp2);
- if ((distance > min) && (distance < max))
- imageSpectrum[j][i] = 0;
- }
- }
- }
- imageSpectrum[image.height() / 2][image.width() / 2] = dcComponent;
- swap_quarters(&imageSpectrum);
- img = fourierTransformTwoDimensional(imageSpectrum, image, true, true);
- scaleAndDraw(&img, image, &image_output);
- return image_output;
- }
- // ==============================================================================================================================
- // HIGH PASS FILTER WITH DETECTION OF EDGE DIRECTIONS
- CImg<double> highPassWithEdgeDetection(CImg<double> &image, CImg<double>&mask) {
- CImg<double> image_output(image.width(), image.height(), image.depth(), image.spectrum(), 255);
- CImg<double>hpfmask(image.width(), image.height(), 1, 3, 1);
- CImg<double> spectrum(image.width(), image.height(), image.depth(), image.spectrum(), 255);
- vector<vector<complex<double> > > img;
- vector<vector<complex<double> > > imageSpectrum;
- CImgToVector(image, &img);
- imageSpectrum = fourierTransformTwoDimensional(img, image, true, false);
- swap_quarters(&imageSpectrum);
- complex<double> dcComponent = imageSpectrum[image.height() / 2][image.width() / 2];
- for (int i = 0; i<image.width(); i++) {
- for (int j = 0; j<image.height(); j++) {
- for (int k = 0; k<image.spectrum(); k++) {
- if (mask(i,j,k) == 0)
- imageSpectrum[i][j] = 0;
- }
- }
- }
- imageSpectrum[image.height() / 2][image.width() / 2] = dcComponent;
- swap_quarters(&imageSpectrum);
- img = fourierTransformTwoDimensional(imageSpectrum, image, true, true);
- scaleAndDraw(&img, image, &image_output);
- return image_output;
- }
- // ==============================================================================================================================
- // PHASE MODYFING FILTER
- vector<vector<complex<double> > > phase(vector<vector<complex<double> > > input, CImg<double> &image, int x, int y) {
- for (int j = 0; j<image.width(); j++) {
- for (int i = 0; i<image.height(); i++) {
- input[i][j] = complex<double>(cos(((-i*x * 2 * M_PI) / (image.height())) + ((-j*y * 2 * M_PI) / (image.width())) + ((x + y)*M_PI)),
- sin(((-i*x * 2 * M_PI) / (image.height())) + ((-j*y * 2 * M_PI) / (image.width())) + ((x + y)*M_PI)));
- }
- }
- return input;
- }
- CImg<double> phaseFilter(CImg<double> &image, int x, int y) {
- CImg<double> image_output(image.width(), image.height(), image.depth(), image.spectrum(), 255);
- CImg<double> spectrum(image.width(), image.height(), image.depth(), image.spectrum(), 255);
- vector<vector<complex<double> > > img, imageSpectrum, mask;
- complex<double> number1, number2;
- double number1X, number2X, number1Y, number2Y;
- double realSum, imaginarySum;
- CImgToVector(image, &img);
- imageSpectrum = fourierTransformTwoDimensional(img, image, true, false);
- mask = phase(img, image, x, y);
- for (int j = 0; j<image.width(); j++) {
- for (int i = 0; i<image.height(); i++) {
- number1 = imageSpectrum[i][j];
- number2 = mask[i][j];
- number1X = number1.real();
- number1Y = number1.imag();
- number2X = number2.real();
- number2Y = number2.imag();
- realSum = (number1X*number2X) - (number1Y*number2Y);
- imaginarySum = (number1Y*number2X) + (number1X*number2Y);
- imageSpectrum[i][j] = complex<double>(realSum, imaginarySum);
- }
- }
- img = fourierTransformTwoDimensional(imageSpectrum, image, true, true);
- scaleAndDraw(&img, image, &image_output);
- return image_output;
- }
- // ==============================================================================================================================
- void save_img(CImg<double> image) {
- string nameOfSavedFile;
- cout << "Input the name of the saved image: ";
- cin >> nameOfSavedFile;
- image.save_bmp(nameOfSavedFile.c_str());
- return;
- }
- void help() {
- cout << "-fft" << endl;
- cout << "-lowpass parameter" << endl;
- cout << "-hightpass parameter" << endl;
- cout << "-bandpass parameter1 parameter2" << endl;
- cout << "-bandcut parameter1 parameter2" << endl;
- cout << "-edgedet mask" << endl;
- cout << "-phase parameter1 parameter2" << endl;
- }
- // ==============================================================================================================================
- // MENU
- int main(int argc, char**argv) {
- if (argc < 2) {
- cout << "Too few argumnets!!" << endl;
- cout << "Check -help" << endl;
- }
- else if (argc == 2) {
- string decision = argv[1];
- if (decision == "-help") help();
- else { help(); }
- }
- else if (argc > 2) {
- CImg<double> image(argv[1]);
- string decision = argv[2];
- if (decision == "-fft") {
- CImg<double> newimage = fourier(image, true);
- save_img(newimage);
- }
- // -------------------------------------------------
- // FILTERS
- if (decision == "-lowpass") {
- int parameter = atoi(argv[3]);
- CImg<double> newimage = lowPass(image, parameter);
- save_img(newimage);
- }
- else if (decision == "-highpass") {
- int parameter = atoi(argv[3]);
- CImg<double> newimage = highPass(image, parameter);
- save_img(newimage);
- }
- else if (decision == "-bandpass") {
- int parameter1 = atoi(argv[3]);
- int parameter2 = atoi(argv[4]);
- CImg<double> newimage = bandPass(image, parameter1, parameter2);
- save_img(newimage);
- }
- else if (decision == "-bandcut") {
- int parameter1 = atoi(argv[3]);
- int parameter2 = atoi(argv[4]);
- CImg<double> newimage = bandCut(image, parameter1, parameter2);
- save_img(newimage);
- }
- else if (decision == "-hpfedge") {
- CImg<double> image2(argv[3]);
- CImg<double> newimage = highPassWithEdgeDetection(image, image2);
- save_img(newimage);
- }
- else if (decision == "-phase") {
- int parameter1 = atoi(argv[3]);
- int parameter2 = atoi(argv[4]);
- CImg<double> newimage = phaseFilter(image, parameter1, parameter2);
- save_img(newimage);
- }
- // -------------------------------------------------
- else {
- cout << endl;
- }
- return 0;
- }
- else {
- cout << "Sorry,something went wrong,check -help" << endl;
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement