Fast image smoothing in C - c

Problem: Given a square matrix, A, whose dimension, N, is a divisor of 64, find a fast way to smoothe A by letting a 3 x 3 grid slide over the A, s.t. for each entry A_{ij}, we replace this with the average of the 8 nearby neighbors.
My solution: Let's assume A is a 4x4 matrix, we initialize as:
int A[NxN] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
Which is equivalent to:
In the first iteration, we see A_ij is equivalent to 0, which is in the center of the 3x3 matrix. We realize that indices (0,0), (0,1), (0,2), (1,0), (1,3) of the 3x3 matrix is trying to find numbers not existing. Therefore, we see that the result must be that if $A_{ij}$ = 0, then we must replace it by $0+1+4+5 = \frac{10}{4}$.
Next iteration, we see A_ij is equivalent to 1, which is now the new center of the 3x3 matrix, and we see that the numbers to be included in the averaging is: 0,1,2,4,5,6.
So when we are in a corner of our matrix, A, we need 4 numbers for averaging, in the top of the matrix, we need 6 numbers, and if A_{ij} = 6, meaning in the middle of the matrix, we will need 9 numbers.
What I am trying to find is a general pattern for these sequences of needed numbers in order to do this in hopefully a single \texttt{for loop}.
I found that when i % dim == 0, we are in the left side of the matrix, when i % dim == 3 we are in the left side, but I have tried to find a general index pattern to define my averaging functions to pair with my if conditions.
#include <stdio.h>
int smooth(int dim);
int main() {
smooth(4);
}
int smooth(int dim) {
int A[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
int K[dim*dim]; // Replacement array, otherwise we average averages
for (int i = 0; i < dim; i++) {
for (int j = 0; j < dim; j++)
{
// Corner cases
if ((i % dim == 0 && j % dim == 0) || (i % dim == dim - 1 && j % dim == 0) || (i % dim == 0 && j % dim == dim -1) || (i % dim == dim -1 && j % dim == dim-1))
{
// Average function on corners
}
// else if not corner and in "edge row", top/bottom {
// Average 6 numbers
}
}
}
return 0;
}

Your mre is a bit theoretical, I will leave all parts which are not practically plausible out of this. They obviously only serve to provide a MRE quick.
Interpret your input as 2D.
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
More abstractly as
0 ... ( 0*dim + (dim-1))
(1 * dim) ... ( 1*dim + (dim-1))
(2 * dim) ... ( 2*dim + (dim-1))
.
.
.
((dim-1) * dim) ... ((dim-1)*dim + (dim-1))
Here is the structure I propose for your function
int smooth(int dim)
{
int A[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; //obvious MRE weirdness, ignored
int K[dim*dim]; // Replacement array, otherwise we average averages
// Corner cases
K[0] = A[0]; /* dummy, to be calculated */
K[dim-1] = A[dim-1]; /* dummy, to be calculated */
K[dim*(dim-1)] = A[dim*(dim-1)]; /* dummy, to be calculated */
K[dim*dim-1] = A[dim*dim-1]; /* dummy, to be calculated */
for (int i = 0; i < dim-2; i++)
{
// edge cases
{
K[1+i] = A[1+i]; /* dummy, average to be calculated */
K[dim*(1+i)] = A[dim*(1+i)]; /* dummy, average to be calculated */
K[dim*(1+i)+dim-1] = A[dim*(1+i)+dim-1]; /* dummy, average to be calculated */
K[dim*(dim-1)+i+1] = A[dim*(dim-1)+i+1]; /* dummy, average to be calculated */
}
// center part
for (int j = 0; j < dim-2; j++)
{
K[(i+1)*dim+1+j] = A[(i+1)*dim+1+j]; /* dummy, average to be calculated */
}
}
return 0;
}
For all cases of A[...]; /* dummy, average to be calculated */ you can use the same index for reading from A as for writing into K and
subtract 1 to get to the pixel to the left
add one to get to the pixel to the right
add dim to get to the pixel below
subtract dim to get to the pixel above
do that for all neigbouring pixels you decide to use
sum the values up to determine the average
In all cases where you need a neighbour pixel you will always arrive at a valid pixel, because either there is one or you are not going to need it.
(Note: I strictly practice starting for loops from 0 and count up with <needed_length. There is an alternative to start from 1 and count up to needed length +1. It will in this case here make the index calculations read easier. This is a matter of habits. I come from an environment where you have to prepare strong reasoning for loops not starting at 0. Habits are hard to shed. Going through the alternative concept will probably provide you with some helpful learning opportunity.)

Related

Taking minimum value of neighboring cells

I'm trying to write a function that takes receives some matrix[N][M] (N and M are defined at the beginning and they're both always 3), two integers and returns the smallest value of neighboring cells (horizontally, vertically and diagonally) to that specific (y,x) cell (The function is part of a larger code that takes specific (y,x)s and not any (y,x). it is called in some specific cases) in a 2D array - Minimum(int mat[N][M], int y, int x).
Say for example I have the 2D array and I'm looking specifically at the 0,0 element
1 10 9
18 9 10
19 10 8
I want that cell to change to 9 since its the smallest value of the neighboring cells (the cell itself doesn't matter if it's the minimum of them all or not) so the array becomes
9 10 9
18 9 10
19 10 8
What I tried: First I went over each neighboring cell. After that, I mainly tried storing the value of that neighboring cell in some other variable
tmp=mat[y+i][x+j]
that changes in every iteration and then add some if condition after it which takes the minimum value to the mat[y][x]=mat[y+i][x+j] cell. I tried a lot of conditions and none worked.
Another thing I thought of and tried implementing was adding a 1D array that stores the values of the all the neighboring cells (if there are less than the size of the array - store 0) and then checking the minimum between every two cells excluding the 0s. The code got scrambled and I got lost on where I would put the loop for that array.
I went over the neighboring cells of some specific y,x cell in the following way:
Min(int mat[N][M], int y, int x)
{
for(i=-1;i<=1;i++)
{
if((y+i>=0) && (y+i<=N))
{
for(j=-1;j<=1;j++)
{
if((x+j>=0) && (x+j<=M))
{
if((x+i != 0) && (y+j != 0))
{
/*CONDITION TO TAKE MINIMUM*/
}
}
}
}
}
}
Any help would be very much appreciated.
1) matr[N][M] it doesn't have elements like matr[?][M] and matr[N][?] because numeration is from 0 to N-1 (or M-1). So you should change condition y+i<=N to y+i<N and x+j<=M to x+j<M.
2) To check that you aren't looking at the cell [y][x] itself you should check if(!(i == 0 && j == 0)) or, equivalent, if(i != 0 || j != 0) instead of if(x+i != 0 && y+j != 0)
3) To find minimum first make int min = INT_MAX; at beginning of the function. The condition to take minimum will be
if (mat[y+i][x+j] < min)
min = mat[y+i][x+j];
4) To write the minimum to the cell [y][x], use matr[y][x] = Min(matr, y, x); in main function or where you want
Alternatively you can walk through all possible cells [i][j] such a way:
int u = max(0, y - 1), d = min(y + 1, N - 1);
int l = max(0, x - 1), r = min(x + 1, M - 1);
for (i = d; i <= u; i++)
for (j = l; j <= r; j++)
if (i != y || j != x)
if (mat[i][j] < min)
min = mat[i][j];
return min;

C Language - General algorithm to read a square matrix, based on the square number of it's side?

So we're reading a matrix and saving it in an array sequentially. We read the matrix from a starting [x,y] point which is provided. Here's an example of some code I wrote to get the values of [x-1,y] [x+1,y] [x,y-1] [x,y+1], which is a cross.
for(i = 0, n = -1, m = 0, array_pos = 0; i < 4; i++, n++, array_pos++) {
if(x+n < filter_matrix.src.columns && x+n >= 0 )
if(y+m < filter_matrix.src.lines && y+m >= 0){
for(k = 0; k < numpixels; k++) {
arrayToProcess[array_pos].rgb[h] = filter_matrix.src.points[x+n][y+m].rgb[h];
}
}
m = n;
m++;
}
(The if's are meant to avoid reading null positions, since it's an image we're reading the origin pixel can be located in a corner. Not relevant to the issue here.)
Now is there a similar generic algorithm which can read ALL the elements around as a square (not just a cross) based on a single parameter, which is the size of the square's side squared?
If it helps, the only values we're dealing with are 9, 25 and 49 (a 3x3 5x5 and 7x7 square).
Here is a generalized code for reading the square centered at (x,y) of size n
int startx = x-n/2;
int starty = y-n/2;
for(int u=0;u<n;u++) {
for(int v=0;v<n;v++) {
int i = startx + u;
int j = starty + v;
if(i>=0 && j>=0 && i<N && j<M) {
printf(Matrix[i][j]);
}
}
}
Explanation: Start from top left value which is (x - n/2, y-n/2) now consider that you are read a normal square matrix from where i and j are indices of Matrix[i][j]. So we just added startx & starty to shift the matrix at (0,0) to (x-n/2,y-n/2).
Given:
static inline int min(int x, int y) { return (x < y) ? x : y; }
static inline int max(int x, int y) { return (x > y) ? x : y; }
or equivalent macros, and given that:
the x-coordinates range from 0 to x_max (inclusive),
the y-coordinates range from 0 to y_max (inclusive),
the centre of the square (x,y) is within the bounds,
the square you are creating has sides of (2 * size + 1) (so size is 1, 2, or 3 for the 3x3, 5x5, and 7x7 cases; or if you prefer to have sq_side = one of 3, 5, 7, then size = sq_side / 2),
the integer types are all signed (so x - size can produce a negative value; if they're unsigned, you will get the wrong result using the expressions shown),
then you can ensure that you are within bounds by setting:
x_lo = max(x - size, 0);
x_hi = min(x + size, x_max);
y_lo = max(y - size, 0);
y_hi = min(y + size, y_max);
for (x_pos = x_lo; x_pos <= x_hi; x_pos++)
{
for (y_pos = y_lo; y_pos <= y_hi; y_pos++)
{
// Process the data at array[x_pos][y_pos]
}
}
Basically, the initial assignments determine the bounds of the the array from [x-size][y-size] to [x+size][y+size], but bounded by 0 on the low side and the maximum sizes on the high end. Then scan over the relevant rectangular (usually square) sub-section of the matrix. Note that this determines the valid ranges once, outside the loops, rather than repeatedly within the loops.
If the integer types are signed, you have ensure you never try to create a negative number during subtraction. The expressions could be rewritten as:
x_lo = x - min(x, size);
x_hi = min(x + size, x_max);
y_lo = y - min(y, size);
y_hi = min(y + size, y_max);
which isn't as symmetric but only uses the min function.
Given the coordinates (x,y), you first need to find the surrounding elements. You can do that with a double for loop, like this:
for (int i = x-1; i <= x+1; i++) {
for (int j = y-1; j <= y+1; j++) {
int elem = square[i][j];
}
}
Now you just need to do a bit of work to make sure that 0 <= i,j < n, where n is the length of a side;
I don't know whether the (X,Y) in your code is the center of the square. I assume it is.
If the side of the square is odd. generate the coordinates of the points on the square. I assume the center is (0,0). Then the points on the squares are
(-side/2, [-side/2,side/2 - 1]); ([-side/2 + 1,side/2], -side/2); (side/2,[side/2 - 1,-side/2]);([side/2 - 1, side/2],-side/2);
side is the length of the square
make use of this:
while(int i<=0 && int j<=0)
for (i = x-1; i <= x+1; i++) {
for (j = y-1; j <= y+1; j++) {
int elem = square[i][j];
}
}
}

Algorithm for linear equations with more solutions

Can someone help me out with algorithm for solving linear equations in modular arithmetic (!). I need only the "smallest" solution. Smallest means lexicographically first.
Let's have this system:
3x1+2x2=3
4x1+3x2+1x3+2x4=4
Number next to x is index.
Matrix for this system where we use modulo 5 (0<=x<=p where p is our modulo) is
3 2 0 0 0 | 3
4 3 1 2 0 | 4
The smallest solution for this is (0,4,0,1,0). I have to write an algorithm which will give me that solution.
I was thinking about brute-force, because p<1000. But I dont how to do it, because in this situation in first row I have to x1=0 ... p-1 , then solve x2, in the second row i have to pick x3= 0 ... p-1. And solve x4. I have to do this until that system of equations hold. If I go from 0 .. p-1, then the first solution I get will be the smallest one.
PS:There can a lot of forms of matrix, like:
3 2 4 0 0 | 3
4 3 1 2 1 | 4
1 2 0 0 0 | 3
3 0 3 0 0 | 3
4 3 1 2 3 | 4
etc.
Sorry for my english, I am from asia.
Edit: I was thinking about how to determine which variables are parameters. But can't figure it out....
Ah well, what the heck, why not, here you go
#include <stdio.h>
#define L 2
#define N 5
#define MOD 5
static int M[L][N] =
{ { 3, 2, 0, 0, 0 }
, { 4, 3, 1, 2, 0 }
};
static int S[L] =
{ 3, 4
};
static void init(int * s)
{
int i;
for (i = 0; i < N; i++)
{
s[i] = 0;
}
}
static int next(int * s)
{
int i, c;
c = 1;
for (i = N-1; i >= 0 && c > 0; i--)
if ( (++s[i]) == MOD)
{
s[i] = 0;
}
else
{
c = 0;
}
return c == 0;
}
static int is_solution(int * s)
{
int i, j, sum;
for (i = 0; i < L; i++)
{
sum = 0;
for (j = 0; j < N; j++)
{
sum += M[i][j]*s[j];
}
if (sum % MOD != S[i])
{
return 0;
}
}
return 1;
}
int main(void)
{
int s[N];
init(s);
do
{
if (is_solution(s))
{
int i;
for (i = 0; i < N; i++)
{
printf(" %d", s[i]);
}
printf("\n");
break;
}
} while (next(s));
return 0;
}
You can treat this as a problem in linear algebra and Gaussian elimination mod p.
You are trying to find solutions of Mx = y mod p. Start with a square M by adding rows of 0'x = 0 if necessary. Now use Gaussian elimination mod p to reduce M, as far as possible, to upper triangular form. You end up with a system of equations such as
ax + by + cz = H
dy + ez = G
but with some zeros on the diagonal, either because you have run out of equations, or because all of the equations have zero at a particular column. If you have something that says 0z = 1 or similar there is no solution. If not you can work out one of possibly many solutions by solving from the bottom up as usual, and putting in z=0 if there is no equation left that has a non-zero coefficient for z on the diagonal.
I think that this will produce the lexicographically smallest answer if the most significant unknown corresponds to the bottom of the vector. The following shows how you can take an arbitrary solution and make it lexicographically smallest, and I think that you will find that it would not modify solutions produced as above.
Now look at http://en.wikipedia.org/wiki/Kernel_%28matrix%29. There is a linear space of vectors n such that Mn = 0, and all the solutions of the equation are of the form x + n, where n is a vector in this space - the null space - and x is a particular solution, such as the one you have worked out.
You can work out a basis for the null space by finding solutions of Mn = 0 much as you found x. Find a column where there is no non-zero entry on the diagonal, go to the row where the diagonal for that column should be, set the unknown for that column to 1, and move up the matrix from there, choosing the other unknowns so that you have a solution of Mn = 0.
Notice that all of the vectors you get from this have 1 at some position in that vector, 0s below that vector, and possibly non-zero entries above. This means that if you add multiples of them to a solution, starting with the vector which has 1 furthest down, later vectors will never disturb components of the solution where you have previously added in vectors with 1 low down, because later vectors always have zero there.
So if you want to find the lexicographically smallest solution you can arrange things so that you use the basis for the null space with the lexicographically largest entries first. Start with an arbitrary solution and add in null space vectors as best you can, in lexicographical order, to reduce the solution vector. You should end up with the lexicographically smallest solution vector - any solution can be produced from any other solution by adding in a combination of basis vectors from the null space, and you can see from the above procedure that it produces the lexicographically smallest such result - at each stage the most significant components have been made as small as possible and any alternatives must be lexicographically greater.

While(1) works first four times that function is called, then becomes infinite. (C) [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have a tic tac toe board that I'm working on for fun and I've come across a problem. Basically I generate the two x,y coordinates randomly and then run them through a while loop. If the coordinate position hasn't been marked, then it marks the spot. Else it'll continue running and generate a new pair of coordinates. This seems to work for the first four times that the function is called, but then any subsequent uses of the function cause it to spiral out of control. Hoping someone might be able to point me in the right direction as well as tell me if logic is incorrect somewhere. Constructive criticism is great.
Thanks in advance and here's the code for the X's move function (the O has almost the same code):
void Xmove(struct config *cp) {
int ran1, ran2;
srand((unsigned) time(NULL));
ran1 = rand() % 3;
ran2 = rand() % 3;
if(cp->grid[1][1] == ' ') {
cp->grid[1][1] = 'X';
printGrid(cp);
return;
}
while(ran1 == 1 && ran2 == 1) {
ran1 = (rand() % 3);
ran2 = (rand() % 3);
}
int looper = 1;
while (looper) {
if(cp->grid[ran1][ran2] != 'O' && cp->grid[ran1][ran2] != 'X') {
cp->grid[ran1][ran2] = 'X';
printGrid(cp);
looper = 0;
}
ran1 = (rand() % 3);
ran2 = (rand() % 3);
}
}
Back to the the original question about your infinite loop and your code, You cannot make the loop break solely on the assumption of finding an empty slot and filling it. You should not be even entering the loop if there are no slots left available. In fact, you should not even call either Move() function at all if there are no open tiles to fill, and honestly that should be maintained as a decrement-counter of the config struct.
But that aside, detection of open-tiles-remaining could be done a number of ways. One is presented below that requires no other modifications to the config table, etc. This you can easily do by building a list of viable tiles, and choosing a single random entry from that. The following replaces everything past your initial check for the center slot being open.
// build a table of open tiles
int ar[9] = {0};
int n=0,i=0,j=0;
for (i=0;i<3;++i)
for (j=0;j<3;++j)
if (cp->grid[i][j] != 'O' && cp->grid[i][j] != 'X')
ar[n++] = i*3+j;
// now you have the list of available tiles
// in `ar[0..n-1]`. choose ONE via `rand()`
if (n > 0)
{
n = ar[rand()%n];
cp->grid[n/3][n%3] = 'X'; // or 'O'
}
I'd eliminate the random looping altogether, instead every time I needed to make a move I would generate a random permutation of the digits 0-9 inclusive, and use that to walk the board, looking for where to put an X or an O as needed. Something like this:
int randperm[9], i = 0;
/* fill the array randperm with the numbers 0 through 8 in
* order
*/
for(i = 0; i != 9; i++)
randperm[i] = i;
/* Now mix the numbers up, so that the array ends up in
* some "random" order: that is, generate a permutation
* of the digits 0-8.
*/
for(i = 8; i > 0; i--)
{
int j = rand() % (i+1);
int temp = randperm[j];
randperm[j] = randperm[i];
randperm[i] = temp;
}
/* Now try to find a spot. We will use our randperm array to
* determine which cell to look at. Remember that the array
* contains the numbers 0-8 in some random order.
*/
for(i = 0; i != 9; i++)
{
/* We split a number from 0-8 into two numbers (x and y),
* each from 0 to 2:
*
* 0 -> 0 0, 1 -> 1 0, 2 -> 2 0,
* 3 -> 0 1, 4 -> 1 1, 5 -> 2 1,
* 6 -> 0 2, 7 -> 1 2, 8 -> 2 2
*
* notice that (y * 3) + x = randperm[i]
*/
int x = randperm[i] % 3;
int y = randperm[i] / 3;
/* check if the spot at grid[x][y] is available, if it is
* take it and return.
*/
}
/* If we get here there's no spot to put an X or an O... board is full */

Fastest way to calculate all the even squares from 1 to n?

I did this in c :
#include<stdio.h>
int main (void)
{
int n,i;
scanf("%d", &n);
for(i=2;i<=n;i=i+2)
{
if((i*i)%2==0 && (i*i)<= n)
printf("%d \n",(i*i));
}
return 0;
}
What would be a better/faster approach to tackle this problem?
Let me illustrate not only a fast solution, but also how to derive it. Start with a fast way of listing all squares and work from there (pseudocode):
max = n*n
i = 1
d = 3
while i < max:
print i
i += d
d += 2
So, starting from 4 and listing only even squares:
max = n*n
i = 4
d = 5
while i < max:
print i
i += d
d += 2
i += d
d += 2
Now we can shorten that mess on the end of the while loop:
max = n*n
i = 4
d = 5
while i < max:
print i
i += 2 + 2*d
d += 4
Note that we are constantly using 2*d, so it's better to just keep calculating that:
max = n*n
i = 4
d = 10
while i < max:
print i
i += 2 + d
d += 8
Now note that we are constantly adding 2 + d, so we can do better by incorporating this into d:
max = n*n
i = 4
d = 12
while i < max:
print i
i += d
d += 8
Blazing fast. It only takes two additions to calculate each square.
I like your solution. The only suggestions I would make would be:
Put the (i*i)<=n as the middle clause of your for loop, then it's checked earlier and you break out of the loop sooner.
You don't need to check and see if (i*i)%2==0, since 'i' is always positive and a positive squared is always positive.
With those two changes in mind you can get rid of the if statement in your for loop and just print.
Square of even is even. So, you really do not need to check it again. Following is the code, I would suggest:
for (i = 2; i*i <= n; i+=2)
printf ("%d\t", i*i);
The largest value for i in your loop should be the floor of the square root of n.
The reason is that the square of any i (integer) larger than this will be greater than n. So, if you make this change, you don't need to check that i*i <= n.
Also, as others have pointed out, there is no point in checking that i*i is even since the square of all even numbers is even.
And you are right in ignoring odd i since for any odd i, i*i is odd.
Your code with the aforementioned changes follows:
#include "stdio.h"
#include "math.h"
int main ()
{
int n,i;
scanf("%d", &n);
for( i = 2; i <= (int)floor(sqrt(n)); i = i+2 ) {
printf("%d \n",(i*i));
}
return 0;
}

Resources