I'm trying to do a normalization of data for a polinomial interpolation with perceptron, I'm using the following formula:
Where:
xi is a data point (x1, x2…xn).
x̄ is the sample mean.
s is the sample standard deviation.
and Z is my new value of input for the perceptron.
I'm programming in C ++, and plotting graph with freeglut.
My function for normalize:
vector<double> Perceptron::normalizar(double x) {
vector<double> aux;
aux.push_back(1.0);
for (unsigned i = 1; i < pesos.size(); i++) {
double t = (pow(x,i) - means[i]) / devianation[i];
aux.push_back(t);
}
return aux;
}
The problem is: before I did the normalization, the polynomial was converging to the points.
But after normalization, the polynomial is converging to other points, and I do not know where it is converging.
The formula for the polynomial would be as follows (with W being the weights of the perceptron):
So I used a mean formula for each value of x.
See the code:
void Perceptron::mean(Points P) { //P is a struct with all x and y values of the points.
means.clear(); //vector that stores the means
for (unsigned i = 0; i < weights.size(); i++) {
double m = 0;
for (unsigned j = 0; j < P.size(); j++) {
m += pow(P[i].x, i);
}
means.push_back(m / P.size());
}
}
void Perceptron::deviation(Points P) {
deviations.clear(); //vector that stores the deviations
for (unsigned i = 0; i < weights.size(); i++) {
double sd = 0;
for (unsigned j = 0; j < P.size(); j++) {
sd += pow(pow(P[j].x, i) - means[i], 2);
}
deviations.push_back(sqrt(sd / P.size()));
}
}
Related
I'm working on a program that requires calculating the inverse of an 8x8 matrix as fast as possible. Here's the code I wrote:
class matrix
{
public:
int w, h;
std::vector<std::vector<float>> cell;
matrix(int width, int height)
{
w = width;
h = height;
cell.resize(width);
for (int i = 0; i < cell.size(); i++)
{
cell[i].resize(height);
}
}
};
matrix transponseMatrix(matrix M)
{
matrix A(M.h, M.w);
for (int i = 0; i < M.h; i++)
{
for (int j = 0; j < M.w; j++)
{
A.cell[i][j] = M.cell[j][i];
}
}
return A;
}
float getMatrixDeterminant(matrix M)
{
if (M.w != M.h)
{
std::cout << "ERROR! Matrix isn't of nXn type.\n";
return NULL;
}
float determinante = 0;
if (M.w == 1)
{
determinante = M.cell[0][0];
}
if (M.w == 2)
{
determinante = M.cell[0][0] * M.cell[1][1] - M.cell[1][0] * M.cell[0][1];
}
else
{
for (int i = 0; i < M.w; i++)
{
matrix A(M.w - 1, M.h - 1);
int cy = 0;
for (int y = 1; y < M.h; y++)
{
int cx = 0;
for (int x = 0; x < M.w; x++)
{
if (x != i)
{
A.cell[cx][cy] = M.cell[x][y];
cx++;
}
}
cy++;
}
determinante += M.cell[i][0] * pow(-1, i + 0) * getMatrixDeterminant(A);
}
}
return determinante;
}
float getComplementOf(matrix M, int X, int Y)
{
float det;
if (M.w != M.h)
{
std::cout << "ERROR! Matrix isn't of nXn type.\n";
return NULL;
}
if (M.w == 2)
{
det = M.cell[1 - X][1 - Y];
}
else
{
matrix A(M.w - 1, M.h - 1);
int cy = 0;
for (int y = 0; y < M.h; y++)
{
if (y != Y)
{
int cx = 0;
for (int x = 0; x < M.w; x++)
{
if (x != X)
{
A.cell[cx][cy] = M.cell[x][y];
cx++;
}
}
cy++;
}
}
det = getMatrixDeterminant(A);
}
return (pow(-1, X + Y) * det);
}
matrix invertMatrix(matrix M)
{
matrix A(M.w, M.h);
float det = getMatrixDeterminant(M);
if (det == 0)
{
std::cout << "ERROR! Matrix inversion impossible (determinant is equal to 0).\n";
return A;
}
for (int i = 0; i < M.h; i++)
{
for (int j = 0; j < M.w; j++)
{
A.cell[j][i] = getComplementOf(M, j, i) / det;
}
}
A = transponseMatrix(A);
return A;
}
While it does work, it does so way too slowly for my purposes, managing to calculate an 8x8 matrix's inverse about 6 times per second.
I've tried searching for more efficient ways to invert a matrix but was unsuccessfull in finding solutions for matrices of these dimensions.
However I did find conversations in which people claimed that for matrices below 50x50 or even 1000x1000 time shouldn't be a problem, so I was wondering if I have missed something, either a faster method or some unnecessary calculations in my code.
Does anyone have experience regarding this and/or advice?
Sorry for broken english.
Your implementation have problems as others commented on the question. The largest bottleneck is the algorithm itself, calculating tons of determinants.(It's O(n!)!)
If you want a simple implementation, just implement Gaussian elimination. See finding the inverse of a matrix and the pseudo code at Wikipedia. It'll perform fast enough for small sizes such as 8x8.
If you want a complex but more efficient implementation, use a library that is optimized for LU decomposition(Gaussian elimination), QR decomposition, etc.(Such as LAPACK or OpenCV.)
I am attempting to write a naive implementation of the Short-Time Fourier Transform using consecutive FFT frames in time, calculated using the FFTW library, but I am getting a Segmentation fault and cannot work out why.
My code is as below:
// load in audio
AudioFile<double> audioFile;
audioFile.load ("assets/example-audio/file_example_WAV_1MG.wav");
int N = audioFile.getNumSamplesPerChannel();
// make stereo audio mono
double fileDataMono[N];
if (audioFile.isStereo())
for (int i = 0; i < N; i++)
fileDataMono[i] = ( audioFile.samples[0][i] + audioFile.samples[1][i] ) / 2;
// setup stft
// (test transform, presently unoptimized)
int stepSize = 512;
int M = 2048; // fft size
int noOfFrames = (N-(M-stepSize))/stepSize;
// create Hamming window vector
double w[M];
for (int m = 0; m < M; m++) {
w[m] = 0.53836 - 0.46164 * cos( 2*M_PI*m / M );
}
double* input;
// (pads input array if necessary)
if ( (N-(M-stepSize))%stepSize != 0) {
noOfFrames += 1;
int amountOfZeroPadding = stepSize - (N-(M-stepSize))%stepSize;
double ipt[N + amountOfZeroPadding];
for (int i = 0; i < N; i++) // copy values from fileDataMono into input
ipt[i] = fileDataMono[i];
for (int i = 0; i < amountOfZeroPadding; i++)
ipt[N + i] = 0;
input = ipt;
} else {
input = fileDataMono;
}
// compute stft
fftw_complex* stft[noOfFrames];
double frames[noOfFrames][M];
fftw_plan fftPlan;
for (int i = 0; i < noOfFrames; i++) {
stft[i] = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * M);
for (int m = 0; m < M; m++)
frames[i][m] = input[i*stepSize + m] * w[m];
fftPlan = fftw_plan_dft_r2c_1d(M, frames[i], stft[i], FFTW_ESTIMATE);
fftw_execute(fftPlan);
}
// compute istft
double* outputFrames[noOfFrames];
double output[N];
for (int i = 0; i < noOfFrames; i++) {
outputFrames[i] = (double*)fftw_malloc(sizeof(double) * M);
fftPlan = fftw_plan_dft_c2r_1d(M, stft[i], outputFrames[i], FFTW_ESTIMATE);
fftw_execute(fftPlan);
for (int m = 0; i < M; m++) {
output[i*stepSize + m] += outputFrames[i][m];
}
}
fftw_destroy_plan(fftPlan);
for (int i = 0; i < noOfFrames; i++) {
fftw_free(stft[i]);
fftw_free(outputFrames[i]);
}
// output audio
AudioFile<double>::AudioBuffer outputBuffer;
outputBuffer.resize (1);
outputBuffer[0].resize(N);
outputBuffer[0].assign(output, output+N);
bool ok = audioFile.setAudioBuffer(outputBuffer);
audioFile.setAudioBufferSize (1, N);
audioFile.setBitDepth (16);
audioFile.setSampleRate (8000);
audioFile.save ("out/audioOutput.wav");
The segfault seems to be being raised by the first fftw_malloc when computing the forward STFT.
Thanks in advance!
The relevant bit of code is:
double* input;
if ( (N-(M-stepSize))%stepSize != 0) {
double ipt[N + amountOfZeroPadding];
//...
input = ipt;
}
//...
input[i*stepSize + m];
Your input pointer points at memory that exists only inside the if statement. The closing brace denotes the end of the lifetime of the ipt array. When dereferencing the pointer later, you are addressing memory that no longer exists.
For example, in Visual Studio there is tChart and its Series property, which is responsible for drawing lines of the graph. Here is an example of this code
for (int j = 1; j < Nt - 1; j++)
{
for (int i = 1; i < Nt - 1; i++)
{
chart2->Series["" + (j + 1).ToString()]->Points->AddXY(i, wht[j][i]);
}
}
And draw this graph with a lot of lines.
But my task is transfering in Qt Creator(because in Qt Creator may making a lot of opportunities)
This code
void MainWindow::drawdifnet(int Nt)
{
int N=Nt;
int N1=pow(N,2);
QVector<double> x22(N), y22(N1);
int ii=0,jj=0;
for (int j = 0; j < Nt ; j++)
{
for (int i = 0; i < Nt ; i++)
{
x22[jj]=i;
y22[ii]=wht[j][i];
ui->widget_2->addGraph();
ui->widget_2->graph(0)->setData(x22,y22);
ii++;
}
jj++;
}
ui->widget_2->xAxis->setLabel("OsX");
ui->widget_2->yAxis->setLabel("OsY");
ui->widget_2->xAxis->setRange(30,30);
ui->widget_2->replot();
}
Doesn't work correctly.
Result is the empty widget
In first I with help debugger check the QVectors data
In this pictures see that my dinamic array wht[j][i] in work and loaded in QVector yy[ii]
I think the problem in the loop.
In QtCustomPlot tutorial this problem solving this code
ui->widget_2->graph(0)->setData(x,y);
ui->widget_2->graph(1)->setData(x11,y11);
ui->widget_2->graph(2)->setData(x22,y22);
But in my situation the quantity of lines is know when the program working.
How I create and assigned my array
void created(int Nt, int Nx) ///This function creating my dynamic array
{
wht = new double *[Nt];
for (int i = 0; i < Nt; i++)
wht[i] = new double[Nx];
}
inline double fn(int T, double x) ///these 4 functions for my mathematical part(works good)
{
if (x >= 0)
return T;
return 0;
}
inline double u0(int T, double x)
{
return fn(T, x);
}
inline double u1(int T, double a, int xmin, double t)
{
return fn(T, xmin - a * t);
}
inline double u2(int T, double a, int xmax, double t)
{
return fn(T, xmax - a * t);
}
void calculatedifnet(int xmin, double hx, double ht, double a, int Nx, int Nt, int T)
//These main function.We have the empty array and in this function we fill array. Then we solve in the main loop and the fill the first indexes wht[j]
{
for (int i = 0; i < Nt; i++)
{
wht[0][i] = u0(T, xmin + i*hx);//fill the second indexeswht[null][i]
}
for (int j = 0; j < Nt - 1; j++)//the calculated code(works right).The result writing in wht[j]
{
wht[j + 1][0] = u1(T, a, xmin, j*ht);
for (int i = 1; i < Nt; i++)
{
double dudx = (wht[j][i] - wht[j][i - 1]) / hx;
wht[j + 1][i] = -a * dudx * ht + wht[j][i];
}
}
}
In your code there are the following errors:
If we observe x is a constant vector from 0 to Nt-1, then we only have to create it once:
QVector<double> x(Nt);
for (int i = 0; i < Nt ; i++)
x[i]=i;//0 to Nt-1
addGraph() adds a graph and places it in the last position, if you want to graph you must access by the last index, not by the index 0:
ui->widget_2->addGraph()->setData(xx, yy);
Assuming that wht is of type QVector<QVector<double>> and of size NtxNt, then is not necessary to access each element, we can access each QVector<double> since the function setData() accepts as input this type of data. To the function setData() you must pass 2 vectors of the same size, but you were passing 2 vectors of Nt and Nt*Nt, this generated a warning:
ui->widget_2->addGraph()->setData(x, wht[j]);
setRange() places the range from a to b, but if they are the same QCustomPlot will never fit the range, for my test I set it as follows:
ui->widget_2->xAxis->setRange(0,Nt);
ui->widget_2->yAxis->setRange(0,Nt*Nt);
In short the code would be as follows:
void MainWindow::drawdifnet(int Nt){
QVector<double> x(Nt);
for (int i = 0; i < Nt ; i++)
x[i]=i;//0 to Nt-1
for (int j = 0; j < Nt ; j++)
ui->widget_2->addGraph()->setData(x, wht[j]);
/* if c++11
for (auto& row: wht)
ui->widget_2->addGraph()->setData(x, row);
*/
ui->widget_2->xAxis->setLabel("OsX");
ui->widget_2->yAxis->setLabel("OsY");
ui->widget_2->xAxis->setRange(0,Nt);
ui->widget_2->yAxis->setRange(0,Nt*Nt);
ui->widget_2->replot();
}
Output:
Note: For the test wht[i][j] = i*j
In your case wht is a variable of type double**, also assume that Nx>=Nt, for this you must use the following code:
void MainWindow::drawdifnet(int Nt)
{
QVector<double> x(Nt);
for (int i = 0; i < Nt ; i++){
x[i]=i;//0 to Nt-1
}
QVector<double> y(Nt);
for(int i=0; i<Nt; i++){
for(int j=0; j<Nt; j++){
y[j] = wht[i][j];
}
ui->widget_2->addGraph()->setData(x, y);
}
ui->widget_2->xAxis->setLabel("OsX");
ui->widget_2->yAxis->setLabel("OsY");
ui->widget_2->xAxis->setRange(0,12);
ui->widget_2->yAxis->setRange(0,3.5);
ui->widget_2->replot();
}
Input:
created(12, 12);
calculatedifnet(1, .5, .5, 0.9, 12, 12, 3);
Output:
Here is my code for creating the hough accumulator for lines in image :
void hough_lines_acc(cv::Mat img_a_edges, std::vector<std::vector<int> > &hough_acc) {
for (size_t r = 0; r < img_a_edges.rows; r++) {
for (size_t c = 0; c < img_a_edges.cols; c++) {
int theta = static_cast<int> (std::atan2(r, c) * 180 / M_PI);
int rho = static_cast<int> ((c * cos(theta)) + (r * sin(theta)));
if (theta < -90) theta = -90;
if (theta > 89) theta = 89;
++hough_acc[abs(rho)][theta];
}
}
cv::Mat img_mat(hough_acc.size(), hough_acc[0].size(), CV_8U);
std::cout << hough_acc.size() << " " << hough_acc[0].size() << std::endl;
for (size_t i = 0; i < hough_acc.size(); i++) {
for (size_t j = 0; j < hough_acc[0].size(); j++) {
img_mat.at<int> (i,j) = hough_acc[i][j];
}
}
imwrite("../output/ps1-2-b-1.png", img_mat);
}
theta varies from -90 to 89. I am getting negative rho values. Right now I am just replacing the negative who with a positive one but am not getting a correct answer. What do I do to the negative rho? Please explain the answer.
theta = arctan (y / x)
rho = x * cos(theta) + y * sin(theta)
Edited code :
bool hough_lines_acc(cv::Mat img_a_edges, std::vector<std::vector<int> > &hough_acc,\
std::vector<double> thetas, std::vector<double> rhos, int rho_resolution, int theta_resolution) {
int img_w = img_a_edges.cols;
int img_h = img_a_edges.rows;
int max_votes = 0;
int min_votes = INT_MAX;
for (size_t r = 0; r < img_h; r++) {
for (size_t c = 0; c < img_w; c++) {
if(img_a_edges.at<int>(r, c) == 255) {
for (size_t i = 0; i < thetas.size(); i++) {
thetas[i] = (thetas[i] * M_PI / 180);
double rho = ( (c * cos(thetas[i])) + (r * sin(thetas[i])) );
int buff = ++hough_acc[static_cast<int>(abs(rho))][static_cast<int>(i)];
if (buff > max_votes) {
max_votes = buff;
}
if (buff < min_votes) {
min_votes = buff;
}
}
}
}
}
double div = static_cast<double>(max_votes) / 255;
int threshold = 10;
int possible_edge = round(static_cast<double>(max_votes) / div) - threshold;
props({
{"max votes", max_votes},
{"min votes", min_votes},
{"scale", div}
});
// needed for scaling intensity for contrast
// not sure if I am doing it correctly
for (size_t r = 0; r < hough_acc.size(); r++) {
for (size_t c = 0; c < hough_acc[0].size(); c++) {
double val = hough_acc[r][c] / div;
if (val < 0) {
val = 0;
}
hough_acc[r][c] = static_cast<int>(val);
}
}
cv::Mat img_mat = cv::Mat(hough_acc.size(), hough_acc[0].size(), CV_8UC1, cv::Scalar(0));
for (size_t i = 0; i < hough_acc.size(); i++) {
for (size_t j = 0; j < hough_acc[0].size(); j++) {
img_mat.at<uint8_t> (i,j) = static_cast<uint8_t>(hough_acc[i][j]);
}
}
imwrite("../output/ps1-2-b-1.png", img_mat);
return true;
}
Still not correct output. What is the error here?
atan2 of two positive numbers... should not be giving you negative angles, it should only be giving you a range of 0-90
also for the hough transform, I think you want everything relative to one point (ie 0,0 in this case). I think for that you would actually want to make theta=90-atan2(r,c)
Admittedly though, I am a bit confused as I thought you had to encode line direction, rather than just "edge pt". ie I thought at each edge point you had to provide a discrete array of guessed line trajectories and calculate rho and theta for each one and throw all of those into your accumulator. As is... I am not sure what you are calculating.
I am trying to make an alphatrimmed filter in openCV library. My code is not working properly and the resultant image is not looking as image after filtering.
The filter should work in the following way.
Chossing some (array) of pixels in my example it is 9 pixels '3x3' window.
Ordering them in increasing way.
Cutting our 'array' both sides for alpha-2.
calculating arithmetic mean of remaining pixels and inserting them in proper place.
int alphatrimmed(Mat img, int alpha)
{
Mat img9 = img.clone();
const int start = alpha/2 ;
const int end = 9 - (alpha/2);
//going through whole image
for (int i = 1; i < img.rows - 1; i++)
{
for (int j = 1; j < img.cols - 1; j++)
{
uchar element[9];
Vec3b element3[9];
int k = 0;
int a = 0;
//selecting elements for window 3x3
for (int m = i -1; m < i + 2; m++)
{
for (int n = j - 1; n < j + 2; n++)
{
element3[a] = img.at<Vec3b>(m*img.cols + n);
a++;
for (int c = 0; c < img.channels(); c++)
{
element[k] += img.at<Vec3b>(m*img.cols + n)[c];
}
k++;
}
}
//comparing and sorting elements in window (uchar element [9])
for (int b = 0; b < end; b++)
{
int min = b;
for (int d = b + 1; d < 9; d++)
{
if (element[d] < element[min])
{
min = d;
const uchar temp = element[b];
element[b] = element[min];
element[min] = temp;
const Vec3b temporary = element3[b];
element3[b] = element3[min];
element3[min] = temporary;
}
}
}
// index in resultant image( after alpha-trimmed filter)
int result = (i - 1) * (img.cols - 2) + j - 1;
for (int l = start ; l < end; l++)
img9.at<Vec3b>(result) += element3[l];
img9.at<Vec3b>(result) /= (9 - alpha);
}
}
namedWindow("AlphaTrimmed Filter", WINDOW_AUTOSIZE);
imshow("AlphaTrimmed Filter", img9);
return 0;
}
Without actual data, it's somewhat of a guess, but an uchar can't hold the sum of 3 channels. It works modulo 256 (at least on any platform OpenCV supports).
The proper solution is std::sort with a proper comparator for your Vec3b :
void L1(Vec3b a, Vec3b b) { return a[0]+a[1]+a[2] < b[0]+b[1]+b[2]; }