Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "stdafx.h"
- #define _USE_MATH_DEFINES
- #include <iostream>
- #include <cmath>
- #include <string>
- #include <vector>
- #include <complex>
- #include "CImg.h"
- using namespace std;
- using namespace cimg_library;
- void DFT(const CImg<float>&image, vector<vector<complex<double>>>&factors)
- {
- double width = image.width();
- double height = image.height();
- double angle;
- for (int i = 0; i < width; i++)
- {
- for (int j = 0; j < height; j++)
- {
- complex<double> sum(0, 0);
- complex<double> Wn(0, 0);
- complex<double> Wm(0, 0);
- for (int x = 0; x < width; x++)
- {
- for (int y = 0; y < height; y++)
- {
- Wn.real(cos(2 * M_PI * x * i / width));
- Wn.imag(-sin(2 * M_PI * x * i / width));
- Wm.real(cos(2 * M_PI * y * j / height));
- Wm.imag(-sin(2 * M_PI * y * j / height));
- complex<double> valuePix(double(image(x, y, 0)));
- sum += (valuePix * Wn * Wm);
- }
- }
- factors[i][j] = sum / (sqrt(width*height)); //normalization
- }
- }
- }
- void IDFT(CImg<float> &image, const vector<vector<complex<double>>>&factors)
- {
- double width = image.width();
- double height = image.height();
- for (int j = 0; j < height; j++)
- {
- for (int i = 0; i < width; i++)
- {
- complex<double> suma(0, 0);
- complex<double> Wn(0, 0);
- complex<double> Wm(0, 0);
- for (int y = 0; y < height; y++)
- {
- for (int x = 0; x < width; x++)
- {
- Wn.real(cos(2 * M_PI * i * x / width));
- Wn.imag(sin(2 * M_PI * i * x / width));
- Wm.real(cos(2 * M_PI * j * y / height));
- Wm.imag(sin(2 * M_PI * j * y / height));
- suma += (factors[x][y] * Wn * Wm);
- }
- }
- image(i, j) = suma.real() / sqrt(width*height); //normalization!
- }
- }
- }
- void changePosition(CImg<unsigned char> &image)
- {
- const int width = image.width();
- const int height = image.height();
- CImg<unsigned char> temp(width, height, 1, 3, 0);
- for (int j = height / 2; j < height; j++)
- for (int i = 0; i < width / 2; i++)
- {
- temp((width / 2) + i, j - (height / 2)) = image(i, j);
- }
- for (int j = 0; j < height / 2; j++)
- for (int i = 0; i < width / 2; i++)
- {
- temp((width / 2) + i, (height / 2) + j) = image(i, j);
- }
- for (int j = 0; j < height / 2; j++)
- for (int i = width / 2; i < width; i++)
- {
- temp(i - (width / 2), (height / 2) + j) = image(i, j);
- }
- for (int j = height / 2; j < height; j++)
- for (int i = width / 2; i < width; i++)
- {
- temp(i - (width / 2), j - (width / 2)) = image(i, j);
- }
- image = temp;
- }
- CImg<unsigned char> getMagnitude(vector<vector<complex<double>>> &factors)
- {
- const int width = factors.size();
- const int height = factors[0].size();
- int magnitudeMax = 0;
- int presentMag = 0;
- CImg<unsigned char> magnitude(width, height, 1, 3, 0);
- for (int x = 0; x < width; x++)
- for (int y = 0; y < height; y++)
- {
- float re = factors[x][y].real();
- float im = factors[x][y].imag();
- presentMag = sqrt((re * re) + (im * im));
- if (presentMag > magnitudeMax) magnitudeMax = presentMag; //seting max
- }
- for (int x = 0; x < width; x++)
- for (int y = 0; y < height; y++)
- {
- float re = factors[x][y].real();
- float im = factors[x][y].imag();
- magnitude(x, y) = (255 / log(1.0 + magnitudeMax)) * log(1.0 + presentMag);
- }
- changePosition(magnitude);
- return magnitude;
- }
- CImg<unsigned char> getPhase(vector<vector<complex<double>>> &factors)
- {
- const int width = factors.size();
- const int height = factors[0].size();
- CImg<unsigned char> phase(width, height, 1, 3, 0);
- for (int i = 0; i<width; i++)
- for (int j = 0; j<height; j++)
- {
- float re = factors[i][j].real();
- float im = factors[i][j].imag();
- phase(i, j) = atan(im / re);
- phase(i, j) = (phase(i, j)) * (255 / (2 * M_PI));
- }
- changePosition(phase);
- return phase;
- }
- vector< complex<double> > fft1d(vector< complex<double> > input)
- {
- const int N = input.size();
- const complex<double> I = (0.0, 1.0);
- if (N == 1) return input;
- else {
- vector< complex<double> > left, right, temp1, temp2, temp3, temp4, temp5;
- 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]);
- }
- //fourierShift(temp2, inverse);
- complex<double> alfa;
- complex<double> t;
- for (int k = 0; k < N / 2; ++k)
- {
- alfa = ((2 * M_PI * k) / N);
- t = (cos(alfa) - I*sin(alfa))* temp2[k];
- temp3.push_back(t);
- }
- temp4 = fft1d(temp1);
- temp5 = fft1d(temp3);
- int j = 0;
- for (int k = 0; k<N / 2; ++k)
- {
- input[j] = temp4[k];
- input[j + 1] = temp5[k];
- j += 2;
- }
- return input;
- }
- }
- void normalization(vector< complex<double> > &c)
- {
- for (auto i = c.begin(); i < c.end(); ++i)
- {
- (*i) /= sqrt(c.size());
- }
- }
- vector<vector<complex<double>>> FFT(vector<vector<complex<double>>> image)
- {
- for (size_t i = 0; i < image[0].size(); i++)
- fft1d(image[i]);
- //swap(input);
- for (size_t j = 0; j < image.size(); j++)
- fft1d(image[j]);
- //swap(input);
- return image;
- }
- void IFFT(CImg<unsigned char> &image, vector<vector<complex<double>>>&factors)
- {
- const int width = image.width();
- const int height = image.height();
- //unsigned int *reverse1 = new unsigned int[width];
- //for (int i = 0; i<width; i++) reverse1[i] = i;
- //reverseBinary(width, reverse1);
- //const double PI = acos(-1.0);
- //bool *swapped = new bool[width];
- //for (int i = 0; i<width; i++)
- // swapped[i] = false;
- //for (int i = 0; i<width; i++)
- //{
- // for (int j = 0; j<height; j++)
- // if (!(swapped[i] || swapped[reverse1[i]]))
- // swap(factors[i][j], factors[reverse1[i]][j]);
- // if (i != reverse1[i])
- // {
- // swapped[i] = true;
- // swapped[reverse1[i]] = true;
- // }
- //}
- //delete[] swapped;
- //swapped = new bool[height];
- //for (int i = 0; i<width; i++)
- // swapped[i] = false;
- //for (int j = 0; j<height; j++)
- //{
- // for (int i = 0; i<width; i++)
- // if (!(swapped[j] || swapped[reverse1[j]]))
- // swap(factors[i][j], factors[i][reverse1[j]]);
- // if (j != reverse1[j])
- // {
- // swapped[j] = true;
- // swapped[reverse1[j]] = true;
- // }
- //}
- //delete[] swapped;
- //for (int j = 0; j<height; j++)
- //{
- // complex<double> *W = new complex<double>[width / 2];
- // for (int n = 0; n<width / 2; n++)
- // {
- // W[n].real(cos(2 * PI*n / width));
- // W[n].imag(sin(2 * PI*n / width));
- // }
- // const int levelMax = log2(width);
- // for (int level = 0; level < levelMax; level++)
- // {
- // const int blockMax = width / pow(2.0, level + 1);
- // for (int block = 0; block < blockMax; block++)
- // {
- // const int operationMax = pow(2.0, level);
- // for (int operation = 0; operation < operationMax; operation++)
- // {
- // const int i = operation + (block * 2 * pow(2.0, level));
- // const complex<double> a = factors[i][j];
- // complex<double> b = factors[i + operationMax][j];
- // b *= W[operation*(int)pow(2.0, levelMax - level - 1)];
- // factors[i][j] = a + b;
- // factors[i + operationMax][j] = a - b;
- // }
- // }
- // }
- // delete[] W;
- //}
- //for (int i = 0; i<width; i++)
- //{ //tweedle factor
- // complex<double> *W = new complex<double>[height / 2];
- // for (int m = 0; m<height / 2; m++)
- // {
- // W[m].real(cos(2 * PI*m / height));
- // W[m].imag(sin(2 * PI*m / height));
- // }
- // const int levelMax = log2(height);
- // for (int level = 0; level < levelMax; level++)
- // {
- // const int blockMax = height / pow(2.0, level + 1);
- // for (int block = 0; block < blockMax; block++)
- // {
- // const int operationMax = pow(2.0, level);
- // for (int operation = 0; operation < operationMax; operation++)
- // {
- // const int j = operation + (block * 2 * pow(2.0, level));
- // const complex<double> a = factors[i][j];
- // complex<double> b = factors[i][j + operationMax];
- // b *= W[operation*(int)pow(2.0, levelMax - level - 1)];
- // factors[i][j] = a + b;
- // factors[i][j + operationMax] = a - b;
- // }
- // }
- // }
- // delete[] W;
- //}
- //for (int j = 0; j<height; j++)
- // for (int i = 0; i<width; i++)
- // for (int k = 0; k<3; k++)
- // {
- // factors[i][j] /= sqrt(width*height + 0.0);
- // image(i, j) = trunc(factors[i][j].real());
- // }
- //delete[] reverse1;
- }
- void lowpass(CImg<float> &image, int range)
- {
- vector<vector<complex<double>>> factors;
- int width = image.width();
- int height = image.height();
- CImg<unsigned char> magnitude(width, height, 1, 3, 0);
- CImg<unsigned char> phase(width, height, 1, 3, 0);
- double distance;
- CImg<unsigned char> mask(width, height, 1, 3, 0);
- CImg<unsigned char> outputimage(width, height, 1, 3, 0);
- factors.resize(width);
- for (int i = 0; i<width; i++)
- {
- factors[i].resize(height);
- for (int j = 0; j<height; j++)
- {
- factors[i][j]= 0;
- }
- }
- for (int i = 0; i < width; i++)
- {
- for (int j = 0; j < height; j++)
- {
- distance = sqrt((float)((i - width / 2)*(i - width / 2)) + ((j - height / 2)*(j - height / 2)));
- if (distance < range)
- {
- mask(i, j) = 1;
- }
- else
- {
- mask(i, j) = 0;
- }
- }
- }
- changePosition(mask);
- //FFT(image);
- for (int i = 0; i < width; i++)
- {
- for (int j = 0; j < height; j++)
- {
- factors[i][j].real(factors[i][j].real() * mask(i, j));
- factors[i][j].imag(factors[i][j].imag() * mask(i, j));
- }
- }
- magnitude = getMagnitude(factors);
- phase = getPhase(factors);
- IFFT(outputimage, factors);
- outputimage.save("lowpass.bmp");
- magnitude.save("magnitude_low.bmp");
- phase.save("phase_low.bmp");
- }
- void highpass(CImg<float> &image, double range)
- {
- vector<vector<complex<double>>>factors;
- CImg<unsigned char> magnitude(image.width(), image.height(), 1, 3, 0);
- CImg<unsigned char> phase(image.width(), image.height(), 1, 3, 0);
- factors.resize(image.width());
- for (int x = 0; x<image.width(); x++)
- {
- factors[x].resize(image.height());
- for (int y = 0; y<image.height(); y++)
- {
- factors[x][y] = 0;
- }
- }
- int width = image.width();
- int height = image.height();
- double distance;
- CImg<unsigned char> mask(width, height, 1, 3, 0);
- CImg<unsigned char> image_output(width, height, 1, 3, 0);
- for (int x = 0; x < width; x++)
- {
- for (int y = 0; y < height; y++)
- {
- distance = sqrt((float)((x - width / 2)*(x - width / 2)) + ((y - height / 2)*(y - height / 2)));
- if (distance > range)
- mask(x, y) = 1;
- else
- mask(x, y) = 0;
- }
- }
- changePosition(mask);
- mask(0, 0, 0) = 1;
- mask(0, 0, 1) = 1;
- mask(0, 0, 2) = 1;
- //FFT(image, factors);
- for (int x = 0; x < width; x++)
- {
- for (int y = 0; y < height; y++)
- {
- factors[x][y].real(factors[x][y].real() * mask(x, y));
- factors[x][y].imag(factors[x][y].imag() * mask(x, y));
- }
- }
- magnitude = getMagnitude(factors);
- phase = getPhase(factors);
- IFFT(image_output, factors);
- image_output.save("highpass.bmp");
- magnitude.save("magnitude_high.bmp");
- phase.save("phase_high.bmp");
- }
- void bandpass(CImg<float> &image, int range, int thickness)
- {
- vector<vector<complex<double>>> factors;
- int width = image.width();
- int height = image.height();
- CImg<unsigned char> magnitude(width, height, 1, 3, 0);
- CImg<unsigned char> phase(width, height, 1, 3, 0);
- double distance;
- CImg<unsigned char> mask(width, height, 1, 3, 0);
- CImg<unsigned char> outputimage(width, height, 1, 3, 0);
- factors.resize(width);
- for (int i = 0; i<width; i++)
- {
- factors[i].resize(height);
- for (int j = 0; j<height; j++)
- {
- factors[i][j] = 0;
- }
- }
- for (int i = 0; i < width; i++)
- {
- for (int j = 0; j < height; j++)
- {
- distance = sqrt((float)((i - width / 2)*(i - width / 2)) + ((j - height / 2)*(j - height / 2)));
- if ((distance > range - (thickness / 2)) && (distance < range + (thickness / 2)))
- {
- mask(i, j) = 1;
- }
- else
- {
- mask(i, j) = 0;
- }
- }
- }
- changePosition(mask);
- mask(0, 0, 0) = 1;
- mask(0, 0, 1) = 1;
- mask(0, 0, 2) = 1;
- //FFT(image, factors);
- for (int i = 0; i < width; i++)
- {
- for (int j = 0; j < height; j++)
- {
- factors[i][j].real(factors[i][j].real() * mask(i, j));
- factors[i][j].imag(factors[i][j].imag() * mask(i, j));
- }
- }
- magnitude = getMagnitude(factors);
- phase = getPhase(factors);
- IFFT(outputimage, factors);
- outputimage.save("bandpass.bmp");
- magnitude.save("magnitude_bpass.bmp");
- phase.save("phase_bpass.bmp");
- }
- void bandcut(CImg<float> &image, int range, int thickness)
- {
- vector<vector<complex<double>>>factors;
- int width = image.width();
- int height = image.height();
- CImg<unsigned char> magnitude(width, height, 1, 3, 0);
- CImg<unsigned char> phase(width, height, 1, 3, 0);
- double distance;
- CImg<unsigned char> mask(width, height, 1, 3, 0);
- CImg<unsigned char> outputimage(width, height, 1, 3, 0);
- factors.resize(width);
- for (int i = 0; i<width; i++)
- {
- factors[i].resize(height);
- for (int j = 0; j<height; j++)
- {
- factors[i][j] = 0;
- }
- }
- for (int i = 0; i < width; i++)
- {
- for (int j = 0; j < height; j++)
- {
- distance = sqrt((float)((i - width / 2)*(i - width / 2)) + ((j - height / 2)*(j - height / 2)));
- if ((distance < range - (thickness / 2)) || (distance > range + (thickness / 2)))
- {
- mask(i, j) = 1;
- }
- else
- {
- mask(i, j) = 0;
- }
- }
- }
- changePosition(mask);
- //FFT(image, factors);
- for (int i = 0; i < width; i++)
- {
- for (int j = 0; j < height; j++)
- {
- factors[i][j].real(factors[i][j].real() * mask(i, j));
- factors[i][j].imag(factors[i][j].imag() * mask(i, j));
- }
- }
- magnitude = getMagnitude(factors);
- phase = getPhase(factors);
- IFFT(outputimage, factors);
- outputimage.save("bandcut.bmp");
- magnitude.save("magnitude_bcut.bmp");
- phase.save("phase_bcut.bmp");
- }
- CImg<unsigned char>& resize2(CImg<unsigned char>& image, double value)
- {
- int width_after = static_cast<int>(image.width() * value);
- int height_after = static_cast<int>(image.height() * value);
- CImg<float> temp(width_after, height_after, 1, 3, 0); // (width, height, depth, channels, default vale)
- for (int i = 0; i < width_after; i++)
- {
- for (int j = 0; j < height_after; j++)
- {
- temp(i, j) = image(i / value, j / value);
- }
- }
- image = temp;
- return image;
- }
- vector<vector<complex<double>>> Vec2Img(CImg<double>image)
- {
- vector<vector<complex<double>>> result;
- for (int x = 0; x < image.width(); x++)
- {
- vector<complex<double>>temp;
- for (int y = 0; y < image.height(); y++)
- {
- temp.push_back(complex<double>(image(x, y), 0.0));
- }
- result.push_back(temp);
- }
- return result;
- }
- void high_edge(CImg<float> &image, int number, int rotate_indx)
- {
- int width = image.width();
- int height = image.height();
- CImg<unsigned char> outputimage(image.width(), image.height(), 1, 3, 0);
- CImg<unsigned char> mask;
- vector<vector<complex<double>>> factors;
- CImg<unsigned char> magnitude(width, height, 1, 3, 0);
- CImg<unsigned char> phase(width, height, 1, 3, 0);
- if (number == 0)
- {
- mask.load("F5mask1.bmp");
- }
- else if (number == 1)
- {
- mask.load("F5mask2.bmp");
- }
- double scale = width / mask.width();
- resize2(mask, scale);
- mask.save("maskF5.bmp");
- changePosition(mask);
- mask(0, 0) = 255;
- factors.resize(width);
- for (int i = 0; i<width; i++)
- {
- factors[i].resize(height);
- for (int j = 0; j<height; j++)
- {
- factors[i][j] = 0;
- }
- }
- //FFT(image, factors);
- for (int i = 0; i < width; i++)
- {
- for (int j = 0; j < height; j++)
- {
- factors[i][j].real(factors[i][j].real() * (mask(i, j) / 255));
- factors[i][j].imag(factors[i][j].imag() * (mask(i, j) / 255));
- }
- }
- magnitude = getMagnitude(factors);
- phase = getPhase(factors);
- IFFT(outputimage, factors);
- outputimage.save("high_edge.bmp");
- magnitude.save("magnitude_highedge.bmp");
- phase.save("phase_highedge.bmp");
- }
- void phase(CImg<float> &image, int q, int w)
- {
- int width = image.width();
- int height = image.height();
- CImg<unsigned char> outputimage(width, height, 1, 3, 0);
- vector<vector<complex<double>>> mask;
- vector<vector<complex<double>>> factors;
- CImg<unsigned char> magnitude(width, height, 1, 3, 0);
- CImg<unsigned char> phase(width, height, 1, 3, 0);
- const double PI = acos(-1.0);
- mask.resize(width);
- for (int i = 0; i<width; i++)
- {
- mask[i].resize(height);
- for (int j = 0; j<height; j++)
- {
- mask[i][j].real(cos(((-i*q * 2 * PI) / width) + ((-j*w * 2 * PI) / height) + (q + w)*PI));
- mask[i][j].imag(sin(((-i*q * 2 * PI) / width) + ((-j*w * 2 * PI) / height) + (q + w)*PI));
- }
- }
- factors.resize(width);
- for (int i = 0; i<width; i++)
- {
- factors[i].resize(height);
- for (int j = 0; j<height; j++)
- {
- factors[i][j] = 0;
- }
- }
- //FFT(image, factors);
- for (int i = 0; i < width; i++)
- {
- for (int j = 0; j < height; j++)
- {
- factors[i][j] *= mask[i][j];
- }
- }
- magnitude = getMagnitude(factors);
- phase = getPhase(factors);
- IFFT(outputimage, factors);
- outputimage.save("phase_filter.bmp");
- magnitude.save("magnitude_phasefilter.bmp");
- phase.save("phase_phasefilter.bmp");
- }
- int main(int argc, char *argv[])
- {
- const double PI = acos(-1.0);
- vector<vector<complex<double>>> factors;
- try
- {
- if (argc < 2) throw "Too few arguments! See --help";
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- if ((string)argv[1] == "--DFT")
- {
- if (argc != 3)
- throw "Incorrect/missing arguments! See --help";
- CImg<float> img;
- img.assign(argv[2]);
- //--------------------------------------------------------------------
- // making 3-dimensional table to store DFT values
- factors.resize(img.width());
- for (int x = 0; x<img.width(); x++)
- {
- factors[x].resize(img.height());
- for (int y = 0; y<img.height(); y++)
- {
- factors[x][y] = 0;
- }
- }
- //--------------------------------------------------------------------
- DFT(img, factors); // calculate factors
- //--------------------------------------------------------------------
- // save calculated magnitudes and phases to corresponding images
- CImg<unsigned char> magnitude(img.width(), img.height(), 1, 3, 0);
- CImg<unsigned char> phase(img.width(), img.height(), 1, 3, 0);
- magnitude = getMagnitude(factors);
- phase = getPhase(factors);
- //--------------------------------------------------------------------
- IDFT(img, factors);
- //--------------------------------------------------------------------
- magnitude.save("magnitude.bmp");
- phase.save("phase.bmp");
- img.save("inverse.bmp");
- return 0;
- }
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- if ((string)argv[1] == "--FFT")
- {
- if (argc != 3)
- throw "Incorrect/missing arguments! See --help";
- CImg<unsigned char> img;
- vector<vector<complex<double>>>res;
- img.assign(argv[2]);
- //--------------------------------------------------------------------
- // making 3-dimensional table to store DFT values
- factors.resize(img.width());
- for (int x = 0; x<img.width(); x++)
- {
- factors[x].resize(img.height());
- for (int y = 0; y<img.height(); y++)
- {
- factors[x][y] = 0;
- }
- }
- res = Vec2Img(img);
- //--------------------------------------------------------------------
- FFT(res); // calculate factors
- //--------------------------------------------------------------------
- // save calculated magnitudes and phases to corresponding images
- CImg<unsigned char> magnitude(img.width(), img.height(), 1, 3, 0);
- CImg<unsigned char> phase(img.width(), img.height(), 1, 3, 0);
- magnitude = getMagnitude(res);
- phase = getPhase(res);
- //--------------------------------------------------------------------
- //IFFT(img, factors);
- //--------------------------------------------------------------------
- magnitude.save("magnitude.bmp");
- phase.save("phase.bmp");
- //img.save("inverse.bmp");
- return 0;
- }
- if (argc == 4)
- {
- CImg<float> foto;
- std::string par = reinterpret_cast<char*>(argv[1]);
- foto.load(argv[2]);
- int par2 = atoi(argv[3]);
- if (par == "--highpass")
- {
- highpass(foto, par2);
- return 0;
- }
- if (par == "--lowpass")
- {
- lowpass(foto, par2);
- return 0;
- }
- }
- if (argc == 5)
- {
- CImg<float> foto;
- std::string par = reinterpret_cast<char*>(argv[1]);
- foto.load(argv[2]);
- int par2 = atoi(argv[3]);
- int par3 = atoi(argv[4]);
- if (par == "--bandpass")
- {
- bandpass(foto, par2, par3);
- return 0;
- }
- if (par == "--bandcut")
- {
- bandcut(foto, par2, par3);
- return 0;
- }
- if (par == "--highedge")
- {
- high_edge(foto, par2, par3);
- return 0;
- }
- if (par == "--phase")
- {
- phase(foto, par2, par3);
- return 0;
- }
- } throw "Incorrect argument!";
- }
- catch (char const *e)
- {
- cout << e;
- return 1;
- }
- catch (CImgException &e)
- {
- cout << e.what();
- return 2;
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement