I came across an 5x5 gaussian mask code in c, when I googling..
but I need 15x15 gaussian mask so I was just modified like this.
void createFilter(double gKernel[][15])
{
// set standard deviation to 1.0
double sigma = 7.0;
double r, s = 2.0 * sigma * sigma;
// sum is for normalization
double sum = 0.0;
// generate 5x5 kernel
//for (int x = -2; x <= 2; x++)
for (int x = -7; x <= 7; x++)
{
//for (int y = -2; y <= 2; y++)
for (int y = -7; y <= 7; y++)
{
r = sqrt(x*x + y*y);
gKernel[x + 7][y + 7] = (exp(-(r*r) / s)) / (M_PI * s);
sum += gKernel[x + 7][y + 7];
}
}
// normalize the Kernel
for (int i = 0; i < 15; ++i)
for (int j = 0; j < 15; ++j)
gKernel[i][j] /= sum;
}
but the output is different between the correct number of 15x15 gaussian mask.
What am I supposed to do to get the correct 15x15 mask coefficients?
Related
Given the code below, is it possible to modify it so that there's a single set of M "random" numbers for x and y that will "restart" at the beginning of the set for every iteration of i?
What I know I can do is pre-generate an array for x and y of length M but I cannot use arrays because of limited memory. I was thinking of using random numbers with seeds somehow but haven't been able to figure it out.
double sampleNormal()
{
double u = ((double) rand() / (RAND_MAX)) * 2 - 1;
double v = ((double) rand() / (RAND_MAX)) * 2 - 1;
double r = u * u + v * v;
if (r == 0 || r > 1) return sampleNormal();
double c = sqrt(-2 * log(r) / r);
return u * c;
}
...
double x = 0;
double y = 0;
double a = 0;
double f = 100e6;
double t = 0;
double fsamp = 2e9;
for(int i = 0; i < N; i++)
{
for(int j = 0; j < M; j++)
{
x = sampleNormal();
y = sampleNormal();
t = j/fsamp;
a = x*cos(2*pi*f*t)+y*sin(2*pi*f*t);
}
}
that will "restart" at the beginning of the set for every iteration of i
was thinking of using random numbers with seeds somehow but haven't been able to figure it out.
Code could abuse srand()
// Get some state info from rand() for later.
unsigned start = rand();
start = start*(RAND_MAX + 1u) + rand();
for(int i = 0; i < N; i++) {
// Initialize the random number generator to produce the same sequence.
srand(42); // Use your favorite constant.
for(int j = 0; j < M; j++) {
x = sampleNormal();
y = sampleNormal();
t = j/fsamp;
a = x*cos(2*pi*f*t)+y*sin(2*pi*f*t);
}
}
// Re-seed so other calls to `rand()` are not so predictable.
srand(start);
I need to write a function to get a curve fit of a dataset. The code below is what I have. It attempts to use gradient descent to find polynomial coefficients which best fit the data.
//solves for y using the form y = a + bx + cx^2 ...
double calc_polynomial(int degree, double x, double* coeffs) {
double y = 0;
for (int i = 0; i <= degree; i++)
y += coeffs[i] * pow(x, i);
return y;
}
//find polynomial fit
//returns an array of coefficients degree + 1 long
double* poly_fit(double* x, double* y, int count, int degree, double learningRate, int iterations) {
double* coeffs = malloc(sizeof(double) * (degree + 1));
double* sums = malloc(sizeof(double) * (degree + 1));
for (int i = 0; i <= degree; i++)
coeffs[i] = 0;
for (int i = 0; i < iterations; i++) {
//reset sums each iteration
for (int j = 0; j <= degree; j++)
sums[j] = 0;
//update weights
for (int j = 0; j < count; j++) {
double error = calc_polynomial(degree, x[j], coeffs) - y[j];
//update sums
for (int k = 0; k <= degree; k++)
sums[k] += error * pow(x[j], k);
}
//subtract sums
for (int j = 0; j <= degree; j++)
coeffs[j] -= sums[j] * learningRate;
}
free(sums);
return coeffs;
}
And my testing code:
double x[] = { 0, 1, 2, 3, 4 };
double y[] = { 5, 3, 2, 3, 5 };
int size = sizeof(x) / sizeof(*x);
int degree = 1;
double* coeffs = poly_fit(x, y, size, degree, 0.01, 1000);
for (int i = 0; i <= degree; i++)
printf("%lf\n", coeffs[i]);
The code above works when degree = 1, but anything higher causes the coefficients to come back as nan.
I've also tried replacing
coeffs[j] -= sums[j] * learningRate;
with
coeffs[j] -= (1/count) * sums[j] * learningRate;
but then I get back 0s instead of nan.
Anyone know what I'm doing wrong?
I tried degree = 2, iteration = 10 and got results other than nan (values around a few thousands) Adding one to iteration seems making magnitude of the results larger by about 3 times after that.
From this observation, I guessed that the results are being multiplied by count.
In the expression
coeffs[j] -= (1/count) * sums[j] * learningRate;
Both of 1 and count are integers, so integer division is done in 1/count and it will become zero if count is larger than 1.
Instead of that, you can divide the result of multiplication by count.
coeffs[j] -= sums[j] * learningRate / count;
Another way is using 1.0 (double value) instead of 1.
coeffs[j] -= (1.0/count) * sums[j] * learningRate;
Aside:
A candidate NAN source is adding opposite signed values where one is an infinity. Given OP is using pow(x, k), which grows rapidly, using other techniques help.
Consider a chained multiplication rather than pow(). The result is usually more numerically stable. calc_polynomial() for example:
double calc_polynomial(int degree, double x, double* coeffs) {
double y = 0;
// for (int i = 0; i <= degree; i++)
for (int i = degree; i >= 0; i--)
//y += coeffs[i] * pow(x, i);
y = y*x + coeffs[i];
}
return y;
}
Similar code could be used for the main() body.
I made a sphere filled by the value "den" in 3x3 matrix in c language.
double ***pos;
int nx = 10;
int ny = 10;
int nz = 10;
double radius = 4;
double den = 3;
for (int x =0; x <nx; x ++){
for (int y =0; y <ny; y ++){
for (int z =0; x <nz; z ++){
double dis = (dx - x) *(dx - x)+ (dy - y)*(dy - y) + (dz - z)*(dz - z);
if(radius*radius > dis)
pos[x][y][z] = den;
else
pos[x][y][z] = 0;
}
}
}
I want to reduce the volume of sphere without simple modification of "double radius".
I have coded a 1 dimension cfd problem but my numerical solution is coming same as to the analytical solution (up to 6 decimal places).
I am using TDMA method for numerical solution and for the analytical solution I am directly substituting the x value in the function T(x).
Analytical solution T(x) comes out to be T(x) = -(x^2)/2 +11/21(x);
E. g. 4 grid points then ;
x0 = 0.000000, x1 = 0.333333 , x2 = 0.666666 , x3 = 0.999999 .
T(x0) = 0.000000 , T(x1) = 0.119048 , T(x2) = 0.126984 , T(x3) = 0.023810.
And for numerical solution I have used TDMA technique, please refer the code below.
Enter n = 4 for the results.
#include<stdio.h>
void temp_matrix(int n, double *a, double *b, double *c, double *d, double *T);
int main() {
int Bi = 20.0;
int n;
printf("%s ", "Enter the Number of total Grid Points");
scanf("%d", &n);
float t = (n - 1);
double dx = 1.0 / t;
int i;
printf("\n");
double q; // analytical solution below
double z[n];
for (i = 0; i <= n - 1; i++) {
q = (dx) * i;
z[i] = -(q * q) / 2 + q * (11.0 / 21);
printf("\nT analytical %lf ", z[i]);
}
double b[n - 1];
b[n - 2] = -2.0 * Bi * dx - 2.0;
for (i = 0; i <= n - 3; i++) {
b[i] = -2.0;
}
double a[n - 1];
a[n - 2] = 2.0;
a[0] = 0;
for (i = 1; i < n - 2; i++) {
a[i] = 1.0;
}
double c[n - 1];
for (i = 0; i <= n - 2; i++) {
c[i] = 1.0;
}
double d[n - 1];
for (i = 0; i <= n - 2; i++) {
d[i] = -(dx * dx);
}
double T[n];
temp_matrix(n, a, b, c, d, T);
return 0;
}
void temp_matrix(int n, double *a, double *b, double *c, double *d, double *T) {
int i;
double beta[n - 1];
double gama[n - 1];
beta[0] = b[0];
gama[0] = d[0] / beta[0];
for (i = 1; i <= n - 2; i++) {
beta[i] = b[i] - a[i] * (c[i - 1] / beta[i - 1]);
gama[i] = (d[i] - a[i] * gama[i - 1]) / beta[i];
}
int loop;
for (loop = 0; loop < n - 1; loop++)
for (loop = 0; loop < n - 1; loop++)
T[0] = 0;
T[n - 1] = gama[n - 2];
for (i = n - 2; i >= 1; i--) {
T[i] = gama[i - 1] - (c[i - 1] * (T[i + 1])) / beta[i - 1];
}
printf("\n");
for (i = 0; i < n; i++) {
printf("\nT numerical %lf", T[i]);
}
}
Why is the numerical solution coming same as analytical solution in C language?
They differ, by about 3 bits.
Print with enough precision to see the difference.
Using the below, we see a a difference in the last hexdigit of the significand of x620 vs x619 of T[3]. This is only 1 part in 1015 difference.
#include<float.h>
printf("T analytical %.*e\t%a\n", DBL_DECIMAL_DIG - 1, z[i], z[i]);
printf("T numerical %.*e\t%a\n", DBL_DECIMAL_DIG - 1, T[i], T[i]);
C allows double math to be performed at long double math when FLT_EVAL_METHOD == 2 and then the same analytical/numerical results. Your results may differ from mine due to that as well as other subtle FP nuances.
printf("FLT_EVAL_METHOD %d\n", FLT_EVAL_METHOD);
Output
T analytical 0.0000000000000000e+00 0x0p+0
T analytical 1.1904761904761907e-01 0x1.e79e79e79e7ap-4
T analytical 1.2698412698412700e-01 0x1.0410410410411p-3
T analytical 2.3809523809523836e-02 0x1.861861861862p-6
T numerical 0.0000000000000000e+00 0x0p+0
T numerical 1.1904761904761904e-01 0x1.e79e79e79e79ep-4
T numerical 1.2698412698412698e-01 0x1.041041041041p-3
T numerical 2.3809523809523812e-02 0x1.8618618618619p-6
FLT_EVAL_METHOD 0
I'm trying to make a simple blur effect in c. I have an image loaded in an 512*512 array of RGB pixels and I'm using 3x3 kernel to blur that image
here is the kernel
float matrix[9] = {1.0f/9.0f, 1.0f/9.0f, 1.0f/9.0f, 1.0f/9.0f, 1.0f/9.0f, 1.0f/9.0f, 1.0f/9.0f, 1.0f/9.0f, 1.0f/9.0f};
and here is the code that is doing the bluring
void useBlur(){
for(int i = 0; i < ARRAY_SIZE; i++){
float r = 0;
float g = 0;
float b = 0;
int m, n;
for(int y = -1, m = 0; y <= 1; y++, m++){
for(int z = -1, n = 0; z <= 1; z++, n++){
r += (float)orig_image[i + 512 * y + z].r * (float)matrix[m*3+n];
g += (float)orig_image[i + 512 * y + z].g * (float)matrix[m*3+n];
b += (float)orig_image[i + 512 * y + z].b * (float)matrix[m*3+n];
}
}
image[i].r = r;
image[i].g = g;
image[i].b = b;
}
}
I'm not sure what is wrong with that code, but it is producing result:
Any ideas why the colors are wrong? And how to fix it?
EDIT:
fixed matrix[7] from 9.0/9.0 to 1.0/9.0 and uploaded new image
I tried your code with some changes, the images I have are BGRA and I am using opencv for my image container but the structure of the code is the same and it works perfectly.
for (int i = 2*image.cols; i < image.rows*image.cols-2*image.cols; i++)
{
float r = 0;
float g = 0;
float b = 0;
for (int y = -1; y <=1; y++)
{
for (int z = -1; z <=1; z++)
{
b += (float)image.at<cv::Vec4b>(i + image.cols*y+z)(0)*(1.0/9);
g += (float)image.at<cv::Vec4b>(i + image.cols*y+z)(1)*(1.0/9);
r += (float)image.at<cv::Vec4b>(i + image.cols*y+z)(2)*(1.0/9);
}
}
image.at<cv::Vec4b>(i)(0) = b;
image.at<cv::Vec4b>(i)(1) = g;
image.at<cv::Vec4b>(i)(2) = r;
}
I would assume that means the problem is either not in the code you posted, or somehow the opencv cv::Mat class is handling something your image container is not. The obvious candidate for that would be that you seem to be implicitly converting from float to uchar at the end of your code. Could you test running this loop over your image but without modifying it? It could look like this, or any number of other ways. This is ugly, but a quick conversion.
void useBlur(){
for(int i = 0; i < ARRAY_SIZE; i++){
float r = 0;
float g = 0;
float b = 0;
int m, n;
for(int y = -1, m = 0; y <= 1; y++, m++){
for(int z = -1, n = 0; z <= 1; z++, n++){
if(y == 0 && z == 0)
{
r += (float)orig_image[i + 512 * y + z].r * (float)matrix[m*3+n]*9;
g += (float)orig_image[i + 512 * y + z].g * (float)matrix[m*3+n]*9;
b += (float)orig_image[i + 512 * y + z].b * (float)matrix[m*3+n]*9;
}
}
}
image[i].r = r;
image[i].g = g;
image[i].b = b;
}
}
Theoretically nothing should change about the image when you do that, so if the image is changing it is because of some conversion error. I admit the theory is unlikely but the structure of your code seems sound so I don't know what else to suggest.