I am testing some code with Visual Studio's built in Unit test framework for C++. The test just call the following routine and then does an Assert::AreEqual(returned_value, (float)1)however, all other tests run and this just hangs. I can't see why the loops would be infinite loops, but I am likely missing something. Thanks.
vector< vector<float> > history;
vector< vector<float> > graph;
float calculateDeviation(int period) {
int x1 = history.front()[0];
int x2 = x1 + period;
int i = 0, minimum, maximum, SSres = 0, SStot = 0, j=0, R2 =0;
float average = 0;
while (x2 <= history.back()[0]) {
average += averageGradient(x1, x2);
x1 = x2;
x2 = + period;
}
x1 = history.front()[0];
x2 = x1 + period;
i++;
while (j < i) {
SSres += pow((graph[i][0]-((graph[i][2]*graph[i][0])+graph[i][3])), 2);
SStot += pow(graph[i][0] - average, 2);
x1 = x2;
x2 = + period;
j++;
}
R2 = 1 - (SSres / SStot);
return R2;
}
The following values are measured & returned in the unit test.
history.size() = 15
history[5].size() = 14
graph.size() = 14
graph[1].size() = 4
Related
The function f(x) and the series need to end up with the same answer
This is my attempt on this task, but it gives me different results and I don't fully understand the concept of series in C++
#include <iostream>
#include <math.h>
#include <cstdlib>
using namespace std;
int main()
{
float x, y1, y2, a;
int n;
cout<<"Enter x: ";
cin>>x;
cout<<"Enter n: ";
cin>>n;
if (x == 0) x = 3.0;
y1 = 1.0/(2.0*x+5.0);
a = 1.0/11;
y2 = a;
cout<<"f(x) = "<<y1<<endl;
if(x > -5.0/2.0 && x < 17.0/2.0){
for (int k = 0; k <= n; k++){
a = (a*(-1)*pow(2.0/11.0,k))/pow(11.0,k);
y2 = y2 + a;
}
}
else{
return 1;
}
cout<<"Sum = "<<y2<<endl;
system("pause");
return 0;
}
I used any x from -2,5 to 8,5 and n up to 100
the results are always different...
the function and sum of the series are supposed to have very close, if not equal answers, but it's not in my case..
How am I supposed to do it? would be happy for an explanation)
You should probably just use the correct term for your sum:
a = pow(-2.0 / 11.0 * (x - 3), k) / 11.0;
Note that I combined the terms in the power. The division by 11 may also be moved to the end, saving some operations. But then you would need a different initialization. However, this would also allow you to calculate a incrementally. Something like this:
//Initialization
a = 1.0;
y2 = a;
double factor = -2.0 / 11.0 * (x - 3);
//...
for (int k = 1; k <= n; k++)
{
a *= factor;
y2 += a;
}
//Finally
cout << "Sum = " << y2 / 11.0f << endl;
I am struggling since a couple of months to re-write Matlab code into C++
The bigger part of the work as been already done (fft, ifft, xcorr and binFreq functions have been already written in c++), now I am stuck to one function. the function is supposed to estimate delay between two signals S1 and S2. The function relies on FFT-based cross-correlation.
I am stuck in this line " e = [e, eIter];" where e is a vector with variable length ( e was declared earlier as : "e =[]";)
original function in Matlab:
% ****************************************************************
% estimates delay and scaling factor
% ****************************************************************
function [delay_samples, coeff] = iterDelayEst(s1, s2)
n = numel(s1);
halfN = floor(n/2);
assert(numel(s2) == n, 'signals must have same length');
% ****************************************************************
% constants
% ****************************************************************
% exit if uncertainty below threshold
thr_samples = 1e-7;
% exit after fixed number of iterations
nIter = 25;
% frequency domain representation of signals
fd1 = fft(s1);
fd2 = fft(s2);
% first round: No delay was applied
tau = []; %(1,0) ;
fd2Tau = fd2; % delayed s2 in freq. domain
% frequency corresponding to each FFT bin -0.5..0.5
f = binFreq(n);
% uncertainty plot data
e = [];
% normalization factor
nf = sqrt((fd1 * fd1') * (fd2 * fd2')) / n; % normalizes to 1
%nf = sqrt((fd1 .* conj(fd1)) * (fd2 .* conj(fd2))') / n;
% search window:
% known maximum and two surrounding points
x1 = -1;
x2 = -1;
x3 = -1;
y1 = -1;
y2 = -1;
y3 = -1;
% ****************************************************************
% iteration loop
% ****************************************************************
for count = 1:nIter
% ****************************************************************
% crosscorrelation with time-shifted signal
% ****************************************************************
xcorr = abs(ifft(fd2Tau .* conj(fd1)))/ nf;
% ****************************************************************
% detect peak
% ****************************************************************
if isempty(tau)
% ****************************************************************
% startup
% initialize with three adjacent bins around peak
% ****************************************************************
ix = find(xcorr == max(xcorr));
ix = ix(1); % use any, if multiple bitwise identical peaks
% indices of three bins around peak
ixLow = mod(ix-1-1, n) + 1; % one below
ixMid = ix;
ixHigh = mod(ix-1+1, n) + 1; % one above
% delay corresponding to the three bins
tauLow = mod(ixLow -1 + halfN, n) - halfN;
tauMid = mod(ixMid -1 + halfN, n) - halfN;
tauHigh = mod(ixHigh -1 + halfN, n) - halfN;
% crosscorrelation value for the three bins
xcLow = xcorr(ixLow);
xcMid = xcorr(ixMid);
xcHigh = xcorr(ixHigh);
x1 = tauLow;
x2 = tauMid;
x3 = tauHigh;
y1 = xcLow;
y2 = xcMid;
y3 = xcHigh;
else
% ****************************************************************
% only main peak at first bin is of interest
% ****************************************************************
tauMid = tau;
xcMid = xcorr(1);
if xcMid > y2
% ****************************************************************
% improve midpoint
% ****************************************************************
if tauMid > x2
% midpoint becomes lower point
x1 = x2;
y1 = y2;
else
% midpoint becomes upper point
x3 = x2;
y3 = y2;
end
x2 = tauMid;
y2 = xcMid;
elseif tauMid < x2
% ****************************************************************
% improve low point
% ****************************************************************
assert(tauMid >= x1); % bitwise identical is OK
assert(tauMid > x1 || xcMid > y1); % expect improvement
x1 = tauMid;
y1 = xcMid;
elseif tauMid > x2
% ****************************************************************
% improve high point
% ****************************************************************
assert(tauMid <= x3); % bitwise identical is OK
assert((tauMid < x3) || (xcMid > y3)); % expect improvement
x3 = tauMid;
y3 = xcMid;
else
assert(false, '?? evaluated for existing tau ??');
end
end
% ****************************************************************
% calculate uncertainty (window width)
% ****************************************************************
eIter = abs(x3 - x1);
e = [e, eIter];
if eIter < thr_samples
% disp('threshold reached, exiting');
break;
end
if y1 == y2 || y2 == y3
% reached limit of numerical accuracy on one side
usePoly = 0;
else
% ****************************************************************
% fit 2nd order polynomial and find maximum
% ****************************************************************
num = (x2^2-x1^2)*y3+(x1^2-x3^2)*y2+(x3^2-x2^2)*y1;
denom = (2*x2-2*x1)*y3+(2*x1-2*x3)*y2+(2*x3-2*x2)*y1;
if denom ~= 0
tau = (num / denom);
% is the point within [x1, x3]?
usePoly = ((tau > x1) && (tau < x3));
else
usePoly = 0;
end
end
if ~usePoly
% revert to linear interpolation on the side with the
% less-accurate outer sample
% Note: There is no guarantee that the side with the more accurate
% outer sample is the right one, as the samples aren't
% placed on a regular grid!
% Therefore, iterate to improve the "worse" side, which will
% eventually become the "better side", and iteration converges.
tauLow = (x1 + x2) / 2;
tauHigh = (x2 + x3) / 2;
if y1 < y3
o = [tauLow, tauHigh];
else
o = [tauHigh, tauLow];
end
% don't choose point that is identical to one that is already known
tau = o(1);
if tau == x1 || tau == x2 || tau == x3
tau = o(2);
if tau == x1 || tau == x2 || tau == x3
break;
end
end
end
% ****************************************************************
% advance 2nd signal according to location of maximum
% phase shift in frequency domain - delay in time domain
% ****************************************************************
fd2Tau = fd2 .* exp(2i * pi * f * tau);
end % for
% ****************************************************************
% the delay estimate is the final location of the delay that
% maximized crosscorrelation (center of window).
% ****************************************************************
delay_samples = x2;
% ****************************************************************
% Coefficient: Turn signal 1 into signal 2
% ****************************************************************
coeff = fd2Tau * fd1' ./ (fd1 * fd1');
end
C++ equivalent code I have written so far :
//iterDelayEst.cpp
#include <cstddef>
#include <utility>
#include <numeric>
#include <vector>
std::vector<std::size_t> max_indices(CArray const& y) {
struct acc_t {
std::vector<std::size_t> max_idcs;
double max_value;
std::size_t current_idx;
acc_t&& next() {
++current_idx;
return std::move(*this);
}
acc_t&& next_with_current() {
max_idcs.push_back(current_idx++);
return std::move(*this);
}
acc_t&& next_with(Complex const& c) {
max_value = c.real();
max_idcs.clear();
return next_with_current();
}
};
return std::accumulate(
std::begin(y), std::end(y), acc_t{},
[](acc_t acc, Complex const& c) {
return c.real() < acc.max_value ? acc.next()
: c.real() > acc.max_value ? acc.next_with(c)
: acc.next_with_current();
}
).max_idcs;
}
/****************************************************************************/
void tet(CArray const& y) {
auto const max_idcs = max_indices(y);
std::cout << "The max is " << y[max_idcs.front()] << " at indices [";
auto first = true;
for (auto const idx : max_idcs) {
if (!first) {
std::cout << ", ";
} else {
first = false;
}
std::cout << idx;
}
std::cout << "]\n";
}
/****************xcorr function**************************************************************/
void xcorr( CArray & x){
int i;
int n=32;
fft(x);
x *=x.apply(std::conj);
ifft(x);
for ( i = 0 ; i < n ; i++ ){
cout << "x[" << i <<"] =" << x[i] << endl;
}
}
double iterDelayEst(int n,CArray& x, CArray& y)
{
/***************************constants************************************************
/************************************************************************************/
//exit if uncertainty below threshold
int halfN=std::floor(n/2);
double thr_samples = 1e-7;
Complex eIter;
Complex e;
//exit after fixed number of iterations
double nIter = 25;
fft(x);
fft(y);
//frequency domain representation of signals
typedef std::vector < std::complex < double > > tau;
auto f = binFreq(n);
std::vector<double> e;
Complex nf3(0.0,0.0);
int j;
for ( j = 0 ; j < n ; j++ )
{
auto nf1 = ((x * x.apply(std::conj)) * (y * y.apply(std::conj)));
nf3 += nf1[j];
}
auto nf2 =std::sqrt(nf3);
auto nf =nf2/(double)n;
cout << "nf3" << nf3 <<endl;
cout << "nf2" << nf2 <<endl;
cout << "nf" << nf <<endl;
Complex x1(-1,0);
Complex x2(-1,0);
Complex x3(-1,0);
Complex y1(-1,0);
Complex y2(-1,0);
Complex y3(-1,0);
int i;
/***************************************iteration loop**********************************************
**************************************************************************************************/
//for(i=0; i<nIter; i++)
x = x.apply(std::conj);
y *= x;
ifft(y);
y =std::abs(y);
y=y/nf;
for ( i = 0 ; i < n ; i++ ){
cout << "y[" << i <<"] =" << y[i] << endl;
}
if (tau.empty())
{
tet(y);
Complex ix=y[0]; //use any, if multiple bitwise identical peaks
/***********indices of three bins around peak***********/
Complex ixLow= std::fmod(ix-1-1, n) +1 //one below
Complex ixMid=ix;
Complex ixHigh= std::fmod(ix-1+1, n) +1 //one above
/**********delay corresponding to the three bins*********/
Complex tauLow = std::fmod(ixLow -1 + halfN, n) - halfN;
Complex tauMid = std::fmod(ixMid -1 + halfN, n) - halfN;
Complex tauHigh = std::fmod(ixHigh -1 + halfN, n) - halfN;
/**********crosscorrelation value for the three bins******/
Complex xcLow = xcorr(ixLow);
Complex xcMid = xcorr(ixMid);
Complex xcHigh = xcorr(ixHigh);
x1 = tauLow;
x2 = tauMid;
x3 = tauHigh;
y1 = xcLow;
y2 = xcMid;
y3 = xcHigh;
}
else
{
/**********only main peak at first bin is of interest****/
tauMid =tau;
xcMid = xcorr(1);
if (xcMid > y2){
/**********improve midpoint***************************/
if(tauMid > x2){
//midpoint becomes lower point
x1 = x2;
y1 = y2;
}
else{
//midpoint becomes upper point
x3 = x2;
y3 = y2;
}
x2 = tauMid;
y2 = xcMid;
else if (tauMid < x2){
//improve high point
assert(tauMid >= x1); // bitwise identical is OK
assert(tauMid > x1 || xcMid > y1); //expect improvement
x1 = tauMid;
y1 = xcMid;
}
else if (tauMid > x2){
//improve high point
assert(tauMid <= x3); // bitwise identical is OK
assert((tauMid < x3) || (xcMid > y3)); // expect improvement
x3 = tauMid;
y3 = xcMid;
}
else{
assert(("?? evaluated for existing tau ??", false));
}
}
/*************Calculate uncertainty (Window Width)********************/
eIter =abs(x3-x1);
}
The entire Matlab program can be found here :
https://www.dsprelated.com/showcode/288.php
I will be very grateful for any help
Well, my Matlab training is really far away in time, but assuming that e = [e eIter] means that you append a value to e, then you need use a vector
define your e vector somewhere like this: you already done that in your code. Maybe you copied/pasted some code, I don't know, it looks rather neat.
std::vector<double> e;
However I doubt that will compile since you also have a Complex e declaration in the same scope...
// then in your loop populate it like this
eIter = abs(x3 - x1); // (this is your code)
e.push_back(eIter); // push_back was the method you need
Then you can access elements of e just like a standard C-array:
e[i]
To perform a loop, I use an old-style C++ iteration. I know there is better but my C++ is a bit rusty since 2006. Comments/edits are welcome to improve this:
// replace const_iterator by iterator to be able to modify the values
std::vector<double>::const_iterator it;
for (it = e.begin(); it != e.end(); it++)
{
const double &value = *it; // (remove const to be able to change the value)
...
I am unit testing the following C++ code using Visual Studio 2015's built in test framework. When I run the test below, no error is thrown (and the code compiles), but the test just hangs. It only does it when the line I have commented out which calls averageGradient is run. Why is this?
float averageGradient(int x1, int x2) {
int i = 0, y1 = 0, y2 = 0;
while (i < graph.size() && (y1 == 0 || y2 == 0)) { //if both y values haven't been solved then keep trying
if (x1 >= graph[i][0] && x1 < graph[i][1]) { // if x1 lies in the first straight line segment
y1 = (graph[i][2] * x1) + graph[i][2]; // then calculate it's y value (y1)
}
else if (x2 >= graph[i][0] && x2 < graph[i][1]) { //try the same thing for x2
y2 = (graph[i][2] * x2) + graph[i][3]; //calculate its y value (y2)
}
else { i++; } //otherwise incriment i to check the next straight line segment
}
float m = (y2 - y1) / (x2 - x1);
return m;
};
Unit Testing:
TEST_METHOD(Average_Gradient) {
int x1 = 683675;
int x2 = x1 + 86400;
//float gradient = averageGradient(x1, x2);
float answer = 0.0000895684639;
//Assert::AreEqual(answer, gradient);
}
There is an infinite loop in your code. This is not related to unit test.
float averageGradient(int x1, int x2) {
int i = 0, y1 = 0, y2 = 0;
while (i < graph.size() && (y1 == 0 || y2 == 0)) // 1
{
if (x1 >= graph[i][0] && x1 < graph[i][1]) // 2
{
y1 = (graph[i][2] * x1) + graph[i][2]; // 3
}
else if (x2 >= graph[i][0] && x2 < graph[i][1]) // 4
{
y2 = (graph[i][2] * x2) + graph[i][3];
}
else { i++; }
}
float m = (y2 - y1) / (x2 - x1);
return m;
};
In the first iteration of your loop, let's assume that condition in line marked with // 2 is true.
You enter line // 3, and change y1. i and y2 are not modified.
Now you go to next iteration.
i hasn't changed so i < graph.size() is still true.
y2 hasn't changed so (y1 == 0 || y2 == 0) is still true.
Thus, you go to line // 2: the condition is true again, as neither x1 nor graph[] values have changed.
Execution enters // 3, y1 is not modified
Execution continues at 3. (infinite loop)
If your first iteration enters // 4 instead of // 2, the same thing happens.
You should be able to easily analyze this just by running your code under debugger.
i'm trying to implement a custom anti-aliasing routine by summing nearest pixels for downsizing an image.
I tried to sum and mean up to 3 pixels-wide but the result is not good, it's as much antialised (edit i mean aliased) as before.
here is the code i used:
h is height
w is width
buf is a buffer containing the values.
out is the output buffer
for (int x = 0; x < w; x++)
for (int y = 0; y < h; y++)
{
int n = 3;
int x1 = x - n;
int x2 = x + n;
if (x1 < 0) x1 = 0;
if (x2 > w -1) x2 = w - 1;
int y1 = y - n;
int y2 = y + n;
if (y1 < 0) y1 = 0;
if (y2 > h - 1) y2 = h - 1;
double sum = 0;
for (int i = x1; i <= x2; i++)
for (int j = y1; j <= y2; j++)
sum += buf[i][j];
sum = sum / double((x2 - x1 +1) * (y2 - y1 +1));
out[x][y] = sum;
}
What quick routine could i use to do a simple basic anti-aliasing?
I am trying to make a program in OpenCV to convert an image into matrix form, with each value representing an image's pixel. I have converted the image into binary form and now I want to convert it's pixel values into a matrix.
If You need to use CvMat object, You may want to try to use cvCopy function. It takes CvArr* as its arguments, so both IPLImage and CvMat will fit. If You would leave the C API and go to something more modern, You can use cv::Mat object to load image into and use C++ threshold.
The question is why do You want to convert the format of matrix that you already have (IPLImage as well as all others are matrices already). If You want to have a matrix of bool type, use Matx or Mat_ template class for this.
First glance at your question raises more questions... try to specify a bit (I don't seem to be able to see your code example, I'm new to stackoverflow)
Such as, your open cv version and IDE (like codeblocks or Microsoft Visual Studio). But include it in your question. What I would also like to know, is what is the purpose of this? Why do you need a matrix and so forth :)
attempted answer
from what I can gather
"but I have installed OpenCV version 2.3.1 on Visual C++ 2010 – Ayesha Khan"
OpenCV uses the class called Mat, which you should have encountered a lot. This class is essentially a matrix already. If I remember correctly it is very similar to vectors, which I won't cover here.
so if you need to access any pixel value in, lets say.
Mat Img;
you would use a function in this instance of the class, as such
cout << Img.at<uchar>(x,y);
This will access and print the value of the pixel with the coordinates of x,y, to console. In this example I use uchar inside the pointy brackets <>. uchar is used for 8bit picures. You will have to change this if you work with images of more detail (more bits).
When using a binary picture, OpenCV will most likely will allocate the memory of 8bit, which means you need the example above.
I'd like to give more details, but not before you've specified what exactly it is that you are attempting to do.
Regards Scrub # Stackoverflow
Your code uses OpenCV version 1. I'll let someone else answer, since it's not my forte. In my opinion, the 2.0 template-based interface is much more intuitive, and it's my recommendation to use it for all new endeavors.
Have a look at the way I use imread() in this program...
Please inspect the type of value returned from imread()...
Also, search in the code for originalColor = imageArg(/*row*/chosenX, /*column*/chosenY); It's a way to index into the matrix returned from imread
// HW1 Intro to Digital Image Processing
// used OpenCV 2.3.1 and VS2010 SP1 to develop this solution
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <cassert>
using namespace cv;
Mat_<Vec3b> image;
int discreteAngles = 512;
void on_mouse(int eventCode, int centerX, int centerY, int flags, void* params);
int str2int(const std::string &str);
int main(int argc, char* argv[])
{
// command itself is one element of argument array...
if(argc != 1 && argc != 3)
{
std::cout << "Expecting two arguments to the application: angular granularity as a whole number and a file name." << std::endl;
exit(0);
}
std::string discreteAnglesStr, fileName;
if(argc == 3)
{
discreteAnglesStr = argv[1];
fileName = argv[2];
}
else
{
discreteAnglesStr = "64";
fileName = "boats.tif";
}
try
{
discreteAngles = str2int(discreteAnglesStr);
auto image_ = imread(fileName);
int channels = image_.channels();
assert(channels == 3);
image = image_;
if(image.rows == 0)
throw new std::exception();
auto originalImageStr = "Original Image";
namedWindow(originalImageStr);
setMouseCallback(originalImageStr, on_mouse);
imshow(originalImageStr, image);
}
catch(std::exception e)
{
std::cout << "could not load image." << std::endl;
}
waitKey(0);
return -1;
}
// borrowed from http://stackoverflow.com/q/194465/90475, courtesy of Luka Marinko
int str2int(const std::string &str)
{
std::stringstream ss(str);
int num;
if((ss >> num).fail())
{
throw new std::exception("could not parse user input!");
}
return num;
}
double compute_max_madius(int imageRows, int imageCols, int centerX, int centerY)
{
auto otherX = imageCols - centerX;
auto otherY = imageRows - centerY;
auto a = sqrt((double)centerX * centerX + centerY * centerY);
auto b = sqrt((double)otherX * otherX + centerY * centerY);
auto c = sqrt((double)centerX * centerX + otherY * otherY);
auto d = sqrt((double)otherX * otherX + otherY * otherY);
return max(max(a,b), max(c,d));
}
Vec3b interpolate_with_nearest(const Mat_<Vec3b>& imageArg, double x, double y)
{
auto x0 = static_cast<int>(floor(x)); auto y0 = static_cast<int>(floor(y));
auto x1 = static_cast<int>(ceil(x)); auto y1 = static_cast<int>(ceil(y));
// Rolls over to the other side, esp. for angles
if(x0 < 0) x0 = imageArg.rows - 1;
if(y0 < 0) y0 = imageArg.cols - 1;
if (x1 == imageArg.rows) x1 = 0;
if (y1 == imageArg.cols) y1 = 0;
int chosenX, chosenY;
if (x - x0 < 0.5) chosenX = x0; else chosenX = x1;
if (y - y0 < 0.5) chosenY = y0; else chosenY = y1;
Vec3b originalColor = Vec3b(0, 0, 0);
if (chosenX >= 0 && chosenX < imageArg.rows &&
chosenY >= 0 && chosenY < imageArg.cols)
{
originalColor = imageArg(/*row*/chosenX, /*column*/chosenY);
}
return originalColor;
}
Vec3b interpolate_with_bilinear(const Mat_<Vec3b>& imageArg, double x, double y)
{
auto x0 = static_cast<int>(floor(x)); auto y0 = static_cast<int>(floor(y));
auto x1 = static_cast<int>(ceil(x)); auto y1 = static_cast<int>(ceil(y));
// Rolls over to the other side, esp. for angles
if(x0 < 0) x0 = imageArg.rows - 1;
if(y0 < 0) y0 = imageArg.cols - 1;
if (x1 == imageArg.rows) x1 = 0;
if (y1 == imageArg.cols) y1 = 0;
if (!(
x0 >= 0 && x0 < imageArg.rows &&
x1 >= 0 && x1 < imageArg.rows &&
y0 >= 0 && y0 < imageArg.cols &&
y1 >= 0 && y1 < imageArg.cols))
return Vec3b(0, 0, 0);
auto f00 = imageArg(x0, y0);
auto f01 = imageArg(x0, y1);
auto f10 = imageArg(x1, y0);
auto f11 = imageArg(x1, y1);
auto b1 = f00;
auto b2 = f10 - f00;
auto b3 = f01 - f00;
auto b4 = f00 + f11 - f01 - f10;
x = x - x0;
y = y - y0;
return b1 + b2 * x + b3 * y + b4 * x * y;
}
void on_mouse(int eventCode, int centerX, int centerY, int flags, void* params)
{
if(eventCode == 0)
return;
switch( eventCode )
{
case CV_EVENT_LBUTTONDOWN:
{
std::cout << "Center was (" << centerX << ", " << centerY << ")" << std::endl;
auto maxRadiusXY = compute_max_madius(image.rows, image.cols, centerX, centerY);
int discreteRadii = static_cast<int>(floor(maxRadiusXY));
Mat_<Vec3b> polarImg1;
polarImg1.create(/*rows*/discreteRadii, /*cols*/discreteAngles);
Mat_<Vec3b> polarImg2;
polarImg2.create(/*rows*/discreteRadii, /*cols*/discreteAngles);
for (int radius = 0; radius < discreteRadii; radius++) // radii
{
for (int discreteAngle = 0; discreteAngle < discreteAngles; discreteAngle++) // discreteAngles
{
// 3
auto angleRad = discreteAngle * 2.0 * CV_PI / discreteAngles;
// 2
auto xTranslated = cos(angleRad) * radius;
auto yTranslated = sin(angleRad) * radius;
// 1
auto x = centerX + xTranslated;
auto y = centerY - yTranslated;
polarImg1(/*row*/ radius, /*column*/ discreteAngle) = interpolate_with_nearest(image, /*row*/y, /*column*/x);
polarImg2(/*row*/ radius, /*column*/ discreteAngle) = interpolate_with_bilinear(image, /*row*/y, /*column*/x);
}
}
auto polarImage1Str = "Polar (nearest)";
namedWindow(polarImage1Str);
imshow(polarImage1Str, polarImg1);
auto polarImage2Str = "Polar (bilinear)";
namedWindow(polarImage2Str);
imshow(polarImage2Str, polarImg2);
Mat_<Vec3b> reprocessedImg1;
reprocessedImg1.create(Size(image.rows, image.cols));
Mat_<Vec3b> reprocessedImg2;
reprocessedImg2.create(Size(image.rows, image.cols));
for(int y = 0; y < image.rows; y++)
{
for(int x = 0; x < image.cols; x++)
{
// 1
auto xTranslated = x - centerX;
auto yTranslated = -(y - centerY);
// 2
auto radius = sqrt((double)xTranslated * xTranslated + yTranslated * yTranslated);
double angleRad;
if(xTranslated != 0)
{
angleRad = atan((double)abs(yTranslated) / abs(xTranslated));
// I Quadrant
if (xTranslated > 0 && yTranslated > 0)
angleRad = angleRad;
// II Quadrant
if (xTranslated < 0 && yTranslated > 0)
angleRad = CV_PI - angleRad;
// III Quadrant
if (xTranslated < 0 && yTranslated < 0)
angleRad = CV_PI + angleRad;
/// IV Quadrant
if (xTranslated > 0 && yTranslated < 0)
angleRad = 2 * CV_PI - angleRad;
if (yTranslated == 0)
if (xTranslated > 0) angleRad = 0;
else angleRad = CV_PI;
}
else
{
if (yTranslated > 0) angleRad = CV_PI / 2;
else angleRad = 3 * CV_PI / 2;
}
// 3
auto discreteAngle = angleRad * discreteAngles / (2.0 * CV_PI);
reprocessedImg1(/*row*/ y, /*column*/ x) = interpolate_with_nearest(polarImg1, /*row*/radius, /*column*/discreteAngle);
reprocessedImg2(/*row*/ y, /*column*/ x) = interpolate_with_bilinear(polarImg2, /*row*/radius, /*column*/discreteAngle);
}
}
auto reprocessedImg1Str = "Re-processed (nearest)";
namedWindow(reprocessedImg1Str);
imshow(reprocessedImg1Str, reprocessedImg1);
auto reprocessedImg2Str = "Re-processed (bilinear)";
namedWindow(reprocessedImg2Str);
imshow(reprocessedImg2Str, reprocessedImg2);
} break;
}
}