Weighted linear least squares in OpenCV - c

OpenCV's cvSolve can solve a linear least-squares problem like this:
// model: y = a1*x1 + a2*x2 + a3
CvMat *y = cvCreateMat(N, 1, CV_64FC1);
CvMat *X = cvCreateMat(N, 3, CV_64FC1);
CvMat *coeff = cvCreateMat(3, 1, CV_64FC1);
// fill vector y and matrix X
for (int i=0; i<N; ++i)
{
cvmSet(y, i, 0, my_y_value(i) );
cvmSet(X, i, 0, my_x1_value(i) );
cvmSet(X, i, 1, my_x2_value(i) );
cvmSet(X, i, 2, 1 );
}
cvSolve(X, y, coeff, CV_SVD);
// now coeff contains a1, a2, a3
However, I would like to apply different weights to my data points. How do I apply the weights?

I found out it's actually not that difficult:
for (int i=0; i<N; ++i)
{
double w = weight(i);
cvmSet(y, i, 0, w * my_y_value(i) );
cvmSet(X, i, 0, w * my_x1_value(i) );
cvmSet(X, i, 1, w * my_x2_value(i) );
cvmSet(X, i, 2, w );
}
cvSolve(X, y, coeff, CV_SVD);
This fragment simply multiplies both the left-hand side and the right-hand side of the linear equation with weight w. The error term for sample i is effectively multiplied by w².

Related

QE solve and a check if the roots satisfy the equation : using C language

I am writing a code in C. Checking the roots if they satisfy the quadratic equation.
In printf, while %lf outputs 0, %e returns a very small value (between 10-15 and 10-19).
I tried to declare the variable as float or double, nothing is working when I am printing using %e. What is wrong?
Also any suggestions to improve the logic would be appreciated. I am a beginner in C. thanks.
----------------------code-------------------------------
#include <stdio.h>
#include <math.h>
struct param {
double a[11];
} x, y, z;
double slvequad(double a1, double b1, double c1) {
double quad_sol1, quad_sol2;
double dcrm = b1 * b1 - 4.0 * a1 * c1;
printf("\n ( %+0.2e, %+0.2e, %+0.2e)", a1, b1, c1);
if (a1 != 0 && dcrm >= 0) {
quad_sol1 = (-b1 + sqrt(dcrm)) / (2.0 * a1);
quad_sol2 = (-b1 - sqrt(dcrm)) / (2.0 * a1);
printf("( %+0.2e , %+0.2e ) ", quad_sol1, quad_sol2);
quadcheck(a1, b1, c1, quad_sol1, quad_sol2);
} else
if (a1 == 0 && b1 != 0) {
quad_sol1 = quad_sol2 = -c1 / b1;
printf("( %+0.2e ) ", quad_sol1);
quadcheck(a1, b1, c1, quad_sol1, quad_sol2);
} else {
printf(" No solution ");
}
}
void quadcheck(double x1, double y1, double z1, double sol1, double sol2) {
double v1 = (x1 * (sol1) * (sol1) + y1 * sol1 + z1);
double v2 = (x1 * (sol2) * (sol2) + y1 * sol2 + z1);
printf("( %+0.2e , %+0.2e ) \n ", v1, v2);
}
int main() {
struct param x = { 1e-10, 0, 1, 0, 0, 1e-35, 1, 3, 4, 1, 1.0 };
struct param y = { 2.0, 1, 0, 1, 0, 0, 4, 5, -20, 6, -1e-1 };
struct param z = { 1e-10, 5, -4, 0, 0, -1e35, 1, -7, 25, 34, 0.0025 };
int i;
int len = *(&x.a + 1) - x.a;
for (i = 0; i < len; i++) {
slvequad(x.a[i], y.a[i], z.a[i]);
}
return 0;
}
output: In format: (a1,b1,c1)(quad_sol1, quad_sol2)(v1,v1)
Technically, v1 and v2 should print 0, but it prints very small value in a few cases (using %e) as shown in the image.
The roots for x2 + 4x + 1 are irrational numbers -2 +/-sqrt(3). They cannot be represented exactly in types float or double, only approximations are stored, precise to about 17 significant digits for type double. Computing the polynomial with these approximations produce very small, yet non zero numbers.
You may want to read these questions:
Is floating point math broken?
Why are floating point numbers inaccurate?
Is floating-point == ever OK?

Bspline implementation not working as expected

I made this implementation of the BSPLINE curve. I Followed the usual definition presented in http://en.wikipedia.org/wiki/B-spline
t is the knot vector.
#include <stdio.h>
double N(int i, int k, double u, double t[])
{
if(k == 1)
{
if(u >= t[i] && u < t[i+1])
return 1.0e0;
else {
return 0.0e0;
}
}
return ((u - t[i])*N(i, k -1, u, t))/(t[i+k-1] - t[i]) + ((t[i+k] - u)*N(i+1, k-1, u, t))/(t[i+k] - t[i+1]);
}
double pu(double u, double x[], int n, int k, double t[])
{
int i;
double r = 0.0e0;
for(i = 0; i < n; i++)
{
r += x[i]*N(i, k, u, t);
}
return r;
}
int main()
{
double t[] = {0.0, 0.5, 1, 2, 3, 4, 4.5, 5}; //knot vector
double x[] = {-30.0, 25.0, 9.0, 20.0, 25.0, 31.0}, y[] = {-5.0, -10.0, 3.0, -10.0, -5.0, 25.0}; //the points
double u;
for(u = 0.0e0; u < 5.0; u+=0.01e0)
{
printf("%lf %lf\n", pu(u, x, 6, 2, t), pu(u, y, 6, 2, t));
}
return 0;
}
The problem is that when I plot the computed points I see that there is an unexpected behavior at the beginning and end of the curve.
For instance:
I can not understand why this happens, try changing the values of t, but it seems that is not it.
There are two implementations of bspline: uniform and standard. In uniform the first and the last control points are not interpolated and in the standard knot sequence both are interpolated. In uniform, you can have uniform knots usually 1,2,3,... For standard knot sequence if you have order k (degree k-1) you should have k zeros, k ones and fill in the middle with 1/(m-k+2) where m is the number of control points. For example, having 5 control points and order 3, knot sequences are 0, 0, 0, 0.25, 0.5, 0.75, 1, 1, 1.
In addition, using delta functions you can have a much better implementation rather than computing N function. Delta function benefits from the local support of bspline. I suggest you take a look at the course notes that I teach at the University of Calgary:
http://pages.cpsc.ucalgary.ca/~amahdavi/pmwiki-2.2.8/uploads/Site/notes1.pdf
Check page 40 algorithm 3.3.
Hopefully it's helpful.
In general: if you have n control points and you construct a bspline curve of degree k, your knot vector has n+k+1 knots. The domain of the curve (i.e. where the summation of the basis functions are =1) is given in the interval [t_k, ... t_n] (as far as my details are right).
In the loop, your parameter values range from 0.0 to 5.0. This should be t[k] = t[2] = 1.0 to t[n] = t[6] = 4.0.
The wiki examples do it the other way, as the knot vectors given there have multiple values (i.e. k-times) at the beginning and the end. So the shown spline curve starts/ends at the first/last control point. Your construction does not give this property.

Solving linear equation with LAPACKE

I'm trying to solve some linear equation (which is symmetrical, tridiagonal and positive). I have to use LAPACKE. My code is as follows:
#include <lapacke.h>
#include <stdio.h>
void print_mtrx(double * mtrx, int n, int m)
{
int i, j;
for(i = 0; i < n; i++)
{
for(j = 0; j < m; j++)
{
printf("%f ", mtrx[i*m+j]);
}
printf("\n");
}
printf("\n");
}
int main()
{
double matrix[5*5] = {
2, 0, 0, 0, 0,
0, 2, 0, 0, 0,
0, 0, 2, 0, 0,
0, 0, 0, 2, 0,
0, 0, 0, 0, 2
};
double rozw[5] = {1,2,3,4,5};
double matrix2[5*5] = {
7, 0, 0, 0, 0,
0, 7, 0, 0, 0,
0, 0, 7, 0, 0,
0, 0, 0, 7, 0,
0, 0, 0, 0, 7
};
LAPACKE_dptsv(LAPACK_COL_MAJOR, 5, 5, matrix, matrix2, rozw, 5);
print_mtrx(matrix, 5, 5);
print_mtrx(matrix2, 5, 5);
print_mtrx(rozw, 5, 1);
}
LAPACKE's function seems to do nothing, without any errors. The main problem is, I have no idea what do the function parameters stand for. I've searched long, but there is no real documentation. Here is what I managed to found or guess:
int matrix_order -- LAPACK_COL_MAJOR or LAPACK_ROW_MAJOR, how is matrix represented in memory
lapack_int n -- size of matrix (i.e. number of columns)
lapack_int nrhs -- not sure, maybe size of vector b
double* d -- matrix of equations
double* e -- no idea.
double* b -- vector of solutions of equations from d
lapack_int ldb -- leading direction of b (wherefore? is it not identical to nrhs, which itself is identical to n?)
How can I find real meaning of these arguments? How can I make my code work?
So one must to look into documentation of pure LAPACK (http://www.netlib.org/lapack/explore-html/d0/dea/dptsv_8f.html#af1bd4c731915bd8755a4da8086fd79a8), and also ignore incorrect (in case of LAPACKE) remark that LDB be greater or equal max(1,N).
The correct program is as follows:
#include <lapacke.h>
#include <stdio.h>
void print_mtrx(double * mtrx, int n, int m)
{
int i, j;
for(i = 0; i < n; i++)
{
for(j = 0; j < m; j++)
{
printf("%f ", mtrx[i*m+j]);
}
printf("\n");
}
printf("\n");
}
int main()
{
double diagonal[5] = {5,1,5,1,5};
double subdiagonal[4] = {0,0,0,0};
double solution[5] = {1,2,3,4,5};
LAPACKE_dptsv(LAPACK_ROW_MAJOR, 5 /*size of matrix*/, 1 /*number of columns in solution*/,
diagonal, subdiagonal, solution, 1 /*leading dimension of solution vector*/);
print_mtrx(solution, 5, 1);
}
When it comes to documentation for BLAS and/or LAPACK, Intel is probably the most comprehensive out there. You can look up the docs for ?ptsv, which explains what each parameter is for.
(Hint: when searching for a BLAS or LAPACK in Google, be sure to drop the s/d/c/z prefix.)
Here's the relevant snippet:
The routine solves for X the real or complex system of linear equations A*X = B, where A is an n-by-n symmetric/Hermitian positive-definite tridiagonal matrix, the columns of matrix B are individual right-hand sides, and the columns of X are the corresponding solutions.
A is factored as A = L*D*LT (real flavors) or A = L*D*LH (complex flavors), and the factored form of A is then used to solve the system of equations A*X = B.
Input Parameters
n: The order of matrix A; n ≥ 0.
nrhs: The number of right-hand sides, the number of columns in B; nrhs ≥ 0.
d: Array, dimension at least max(1, n). Contains the diagonal elements of the tridiagonal matrix A.
e, b: Arrays: e(n - 1), b(ldb,*). The array e contains the (n - 1) subdiagonal elements of A. The array b contains the matrix B whose columns are the right-hand sides for the systems of equations. The second dimension of b must be at least max(1,nrhs).
ldb: The leading dimension of b; ldb ≥ max(1, n).
Output Parameters
d: Overwritten by the n diagonal elements of the diagonal matrix D from the L*D*LT (real) / L*D*LH (complex) factorization of A.
e: Overwritten by the (n - 1) subdiagonal elements of the unit bidiagonal factor L from the factorization of A.
b: Overwritten by the solution matrix X.
info: If info = 0, the execution is successful. If info = -i, the i-th parameter had an illegal value. If info = i, the leading minor of order i (and therefore the matrix A itself) is not positive-definite, and the solution has not been computed. The factorization has not been completed unless i = n.

Line fit from an array of 2d vectors

I have a problem in some C code, I assume it belonged here over the Mathematics exchange.
I have an array of changes in x and y position generated by a user dragging a mouse, how could I determine if a straight line was drawn or not.
I am currently using linear regression, is there a better(more efficient) way to do this?
EDIT:
Hough transformation attempt:
#define abSIZE 100
#define ARRAYSIZE 10
int A[abSIZE][abSIZE]; //points in the a-b plane
int dX[10] = {0, 10, 13, 8, 20, 18, 19, 22, 12, 23};
int dY[10] = {0, 2, 3, 1, -1, -2, 0, 0, 3, 1};
int absX[10]; //absolute positions
int absY[10];
int error = 0;
int sumx = 0, sumy = 0, i;
//Convert deltas to absolute positions
for (i = 0; i<10; i++) {
absX[i] = sumx+=dX[i];
absY[i] = sumy+=dY[i];
}
//initialise array to zero
int a, b, x, y;
for(a = -abSIZE/2; a < abSIZE/2; a++) {
for(b = -abSIZE/2; b< abSIZE/2; b++) {
A[a+abSIZE/2][b+abSIZE/2] = 0;
}
}
//Hough transform
int aMax = 0;
int bMax = 0;
int highest = 0;
for(i=0; i<10; i++) {
x = absX[i];
y = absX[i];
for(a = -abSIZE/2; a < abSIZE/2; a++) {
for(b = -abSIZE/2; b< abSIZE/2; b++) {
if (a*x + b == y) {
A[a+abSIZE/2][b+abSIZE/2] += 1;
if (A[a+abSIZE/2][b+abSIZE/2] > highest) {
highest++; //highest = A[a+abSIZE/2][b+abSIZE/2]
aMax = a;
bMax = b;
}
}
}
}
}
printf("Line is Y = %d*X + %d\n",aMax,bMax);
//Calculate MSE
int e;
for (i = 0; i < ARRAYSIZE; i++) {
e = absY[i] - (aMax * absX[i] + bMax);
e = (int) pow((double)e, 2);
error += e;
}
printf("error is: %d\n", error);
Though linear regression sounds like a perfectly reasonable way to solve the task, here's another suggestion: Hough transform, which might be somewhat more robust against outliers. Here is a very rough sketch of how this can be applied:
initialize a large matrix A with zeros
transform your deltas to some absolute coordinates (x, y) in a x-y-plane (e.g. start with (0,0))
for each point
there are non-unique parameters a and b such that a*x + b = y. All such points (a,b) define a straight line in the a-b-plane
draw this "line" in the a-b-plane by adding ones to the corresponding cells in A, which represents the quantized plane
now you can find a maximum in the a-b-plane-matrix A, which will correspond to the parameters (a, b) of the straight line in the x-y-plane that has most support by the original points
finally, calculate MSE to the original points and decide with some threshold if the move was a straight line
More details e.g. here:
http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/MARSHALL/node32.html
Edit: here's a quote from Wikipedia that explains why it's better to use a different parametrization to deal with vertical lines (where a would become infinite in ax+b=y):
However, vertical lines pose a problem. They are more naturally described as x = a and would give rise to unbounded values of the slope parameter m. Thus, for computational reasons, Duda and Hart proposed the use of a different pair of parameters, denoted r and theta, for the lines in the Hough transform. These two values, taken in conjunction, define a polar coordinate.
Thanks to Zaw Lin for pointing this out.

Doesn't move and rotate the triangle around a point - C Bgi graphics

Greeting,
I have this graphic homework in BGI graphic. We must use DevCPP and BGI, and matrices.
I wrote this code, and I think the transformations is good. But my triangle doesn't move and rotate around the circle, And I don't understand, why not it moves around the circle...
I don't know where and what I have to rewrite.
#include <math.h>
#include "graphics.h"
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define PI 3.14159265
typedef float Matrix3x3[3][3];
Matrix3x3 theMatrix;
int Round( double n ){
return (int)( n + 0.5 );
}
void matrix3x3SetIdentity(Matrix3x3 m)
{
int i, j;
for(i=0; i<3; i++)
for(j=0; j<3;j++)
m[i][j]=(i==j);
}
/* Multiplies matrix, result in b matrix */
void matrix3x3PreMultiply(Matrix3x3 a, Matrix3x3 b)
{
int r, c;
Matrix3x3 tmp;
for(r=0; r<3;r++)
for(c=0; c<3;c++)
tmp[r][c]=
a[r][0]*b[0][c]+a[r][1]*b[1][c]+a[r][2]*b[2][c];
for(r=0; r<3;r++)
for(c=0; c<3; c++)
b[r][c]-tmp[r][c];
}
void translate2(int tx, int ty)
{
Matrix3x3 m;
matrix3x3SetIdentity (m);
m[0][2] = tx;
m[1][2] = ty;
matrix3x3PreMultiply(m, theMatrix);
}
void scale2 (float sx, float sy, pont2d refpt)
{
Matrix3x3 m;
matrix3x3SetIdentity(m);
m[0][0]=sx;
m[0][2]=(1-sx)*refpt.x;
m[1][1]=sy;
m[1][2]=(1-sy)*refpt.y;
matrix3x3PreMultiply(m, theMatrix);
}
void rotate2 (float a, pont2d refpt)
{
Matrix3x3 m;
matrix3x3SetIdentity(m);
a=a/PI;
m[0][0] = cosf(a);
m[0][1] = -sinf(a);
m[0][2] = refpt.x * (1-cosf(a)) + refpt.y * sinf(a);
m[1][0] = sinf (a);
m[1][1] = cosf (a);
m[1][2] = refpt.y * (1-cosf(a)) - refpt.x * sinf(a);
matrix3x3PreMultiply(m, theMatrix);
}
void transformPoints2 (int npts, pont2d *pts)
{
int k;
float tmp;
for (k = 0; k < npts; k++) {
tmp = theMatrix[0][0] * pts[k].x + theMatrix[0][1] *
pts[k].y + theMatrix[0][2];
pts[k].y = theMatrix[1][0] * pts[k].x + theMatrix[1][1] *
pts[k].y + theMatrix[1][2];
pts[k].x = tmp;
}
}
int main()
{
int gd, gm, i, page=0;
gd=VGA;gm=VGAHI;
initgraph(&gd,&gm,"");
int ap;
while(!kbhit())
{
setactivepage(page);
cleardevice();
pont2d P[3] = { 50.0, 50.0, 150.0, 50.0, 100.0, 150.0};
pont2d refPt = {200.0, 250.0};
// Drawing the Triangle
moveto( Round( P[ 0 ].x ), Round( P[ 0 ].y ) );
for( i = 1; i < 3; i++ )
lineto( Round( P[ i ].x ), Round( P[ i ].y ) );
lineto( Round( P[ 0 ].x ), Round( P[ 0 ].y ) );
// Drawing the Circle
fillellipse(200, 250, 5,5);
setcolor (BLUE);
matrix3x3SetIdentity (theMatrix);
scale2 (0.5, 0.5, refPt);
//scale2 (20, 20, refPt);
rotate2 (90.0, refPt);
translate2 (0, 150);
transformPoints2 (3, P);
setvisualpage(page);
page = 1-page;
}
getch();
closegraph();
return 0;
}
If you want to see the object "spin", then rotations should be performed about the local origin. Rotation about the global origin will cause the object to "orbit" the global origin. Thus, to spin the object:
Translate the object to global origin
Apply the rotation
Translate the object back to its original position
Look at the discussion regarding transformation order here for an illustration. Specifically, look for the section entitled "Demonstration of the importance of transformation order".
To rotate a triangle, get the three points and use the formula:
x' = x + r cos (theta)
y' = y - r sin (theta)
The above formula can be applied into a loop where there being 0 to 360. You can have a graphics simulation by putting a delay (200) milliseconds in the loop.

Resources