This is in C++ and I'm using VC++ 2010.
I am creating a tile-based game, each tile is 32 pixels. If you are given an amount of time, and in that time you want to move an image 32 pixels in a direction, how would I calculate the amount to move per each frame? The frame rate is not fixed and I have access to the frame delta time.
If you need more information just ask.
The basic formula you need to calculate it is:
P pixels / S seconds * delta T seconds/frame = X pixels/frame
For example we'll use your tile size and move it in 1 second and the current frame rate is 30 fps.
32 pixels / 1 second * .033 seconds/frame = 1.056 pixels/frame
int P = 32;
double S = 1.0;
double T = getFrameTime();
double X = P / S * T;
Related
I am using OpenCV's aruco::CharucoBoard object for calibration purposes and noticed that its marker detection doesn't find all visible markers/corners in the images.
I started investigate the matter and tried to detect the markers on the image of the board that was printed for the calibration.
The aruco::detectMarkers fails to detect all markers unless the image size is 640x480.
I'm sure that some tweaking in the aruco::DetectorParameters is required, but I've yet to find the optimal values.
Here is the relevant code:
int nx = 16;
int ny = 10;
double sqrLength = 1.0;
double markerLength = 0.8;
Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
Ptr<aruco::CharucoBoard> board = aruco::CharucoBoard::create(nx, ny, sqrLength, markerLength, dictionary);
aruco::DetectorParameters params = aruco::DetectorParameters::create();
Mat boardImg;
Size boardImgSize = Size(640 * 2, 480 * 2);
board->draw(boardImgSize, boardImg);
vector<int> markerIds;
vector<vector<Point2f>> markerCorners, rejected;
aruco::detectMarkers(boardImg, board->dictionary, markerCorners, markerIds, params, rejected);
cout << markerIds.size() << endl;
aruco::drawDetectedMarkers(boardImg, markerCorners);
imshow("board", boardImg);
waitKey(30);
The total number of markers on the board is 80 and the above code manages to find all of them only for
Size boardImgSize = Size(640, 480)
Any idea on how to improve the detection/which parameters should be tweaked?
First of all it looks like the total number of markers on the board should be 160: nx * ny = 16 * 10 = 160.
But the reason of your issue is related to incorrect sqrLength and markerLength parameter values. As you may find at https://docs.opencv.org/4.5.0/d0/d3c/classcv_1_1aruco_1_1CharucoBoard.html#aa83b0a885d4dd137a41686991f85594c (create() description):
squareLength is a chessboard square side length (normally in meters)
markerLength is a marker side length (same unit than squareLength)
So you should provide values in meters which are measured from printed pattern.
Best choice for your case is to measure square side length and marker side length and set this to sqrLength and markerLength. For example, if your pattern was printed on paper 1x1m values will be:
sqrLength = PatternWidth / nx = 1 / 16 = 0.0625
markerLength = sqrLength * 0.8 = 0.0625 * 0.8 = 0.05
I am doing a music visualizer program in C++. It gives the frequency spectrum of the audio input. I used Aquila-dsp for getting audio samples, Kiss-fft for doing FFT, and SMFL to play the audio. The input is in (.wav) format. OpenGL is used to plot the graph.
Algorithm Used:
1. *framePointer = 0, N = 10000;*
2. Load audio file and play it using SFML.
3. For *i* = framePointer to --> *framePointer* + *N* < *total_samples_count*
Collect audio samples.
4. Apply Window Function (Hann window)
5. Apply *FFT*
6. Calculate magnitude of first N/2 *FFT* data
*Magnitude* = sqrt( re * re + im * im)
7. Convert to dB(log) scale (optional)
10*log(magnitude)
8. Plot N/2, log(magnitude) values
9. If *framaPointer* >= *toatl_samples_count - N*
Exit
Else go to step 3.
#define N 10000
int framePointer = 0;
void getData()
{
int i,j,x;
Aquila::WaveFile wav(fileName);
double mag[N/2];
double roof = wav.getSamplesCount();
//Get first N samples
for( i = framePointer, j = 0; i < (framePointer + N)
&& framePointer < roof - N ; i++,j++ ){
//Apply window function on the sample
double multiplier = 0.5 * (1 - cos(2*M_PI*j/(N-1)));
in[j].r = multiplier * wav.sample(i);
in[j].i = 0; //stores N samples
}
if(framePointer < roof-N -1){
framePointer = i;
}
else {
printf("Frame pointer > roof - N \n");
printf("Framepointer = %d\n",framePointer );
//get total time and exit
timestamp_t t1 = get_timestamp();
double secs = (t1 - tmain) / 1000000.0L;
std::cout<<"Program exit.\nTotal time: "<<secs<<std::endl;
exit(0);
}
// Apply FFT
getFft(in,out);
// calculate magnitude of first N/2 FFT
for(i = 0; i < N/2; i++ ){
mag[i] = sqrt((out[i].r * out[i].r) + (out[i].i * out[i].i));
graph[i] = log(mag[i]) *10;
}
}
I plot the graph using OpenGL.
Full source code
The problem I got is in choosing the frame length (N value).
For a certain length of audio having:
Length: 237191 ms
Sample frequency: 44100 Hz
Channels: 2
Byte rate: 172 kB/s
Bits per sample: 16b
The graph is synchronized with the audio if I choose N = 10000. Or at least it is stopping while the audio ends.
How to chose the N (frame length) such that the audio will be synchronized with the spectrum.
The audio is dual channel, will this algorithm work for that?
Start by deciding how often you want the visualizer to update. Let's say we want it to update 25 times per second (similar to TV or movie frame rates). That means every 1 / 25 seconds, or every 40 ms. At a sample rate of 44.1 kHz this translates to 44100 / 25 = 1764 samples. Since we typically want a power of 2 FFT size then let's go for N = 2048.
This gives a resolution in the frequency axis of 44100 / 2048 = 21.5 Hz. If you want higher resolution then you can overlap successive FFT windows, e.g. keeping the same update rate and overlapping by 50% then you can have N = 4096 for a resolution of 10.75 Hz.
I'm wondering the best way to simulate a sunrise/sunset on the y and z axis. At the moment it does what I want but is moving too fast (say every 3 seconds it's already completed an entire sun path and is already moving in reverse back to the origin).
I know this has to do with seconds variable combined with sin and cos, as this function is called and moves the light's position every frame. Basically I want it to be linked to my game's timer of 50:
50 seconds it's sunrise
25 seconds it's noon
0 seconds it's sunset/game over
Currently I have:
lightPosition = Point_E3d(0,
std::abs(100 *std::cos(seconds)),
-100 * std::sin(seconds));
Wondering what's the correct code format to achieve this effect.
This is just simple trigonometry. The period (Time until the function repeats) of sine(x * n) and cosine(x * n) are both 2*pi / n. In this case, n = 1, so the period is 6.28, meaning one full day (and night) will last 6.28 seconds. If you want to increase the period, multiply your seconds argument by a number smaller than one. A little bit of algebra shows that:
period of sin(x * n) = 2*pi / n
period of sin(.1256 * x) = 2*pi / .1256 = 6.28 / 0.1256 = 50
Therefore, take sine and cosine of seconds * 0.1256, rather than just seconds.
lightPosition = Point_E3d(0,
std::abs(100 *std::cos(seconds * 0.1256 )),
-100 * std::sin(seconds * 0.1256));
Note that this is also including the night time. If you want just the 12 hour day time period to last 50 seconds, multiply by half of 0.1256, aka 0.0628.
I am trying to draw a clock face in which the second hand moves as the time changes.
I am using the following to calculate the points on my circle:
def points_on_circle():
global time, radius, centre, x, y
theta = time% math.pi * 2
c = math.cos(theta)
s = math.sin(theta)
x= centre[0] + radius * c
y =centre[1] + radius * s
return x,y
my timer 'ticks' every tenth second, the radius of my circle is 50, the centre is at (150,150) which is also the origin of my hand, the other end of the hand being (x,y) as calculated above. How do I calculate , I assume by multiplying time by some constant, how fast the x,y should change for this circle ( but for any circle) .
I am using CodeSkulptor from Coursera to try to do this ( the original assignment created a digital timer which I am done. This is not part of the homework ( yet??)
The hand rotates 2 Pi radians every 60 seconds. Assuming you're syncing with real time, time.time() will return the current time in seconds (and milliseconds which I suggest you ignore). If you take the time and first do numseconds = int(time.time()) % 60, you now need to translate that, which is a simple as numseconds * 2 * pi / 60. (Example: numseconds = 0, theta = 0, numseconds = 15, theta = pi /2 (90 degrees).
You will also need to play with your equations as normally theta=0 implies the line is horizontal pointing right (which would be numseconds = 15) and theta=Pi implies the line is vertical pointing up (which would be numseconds = 0)
I am looking for optimized functions in c++ for calculating areal averages of floats. the function is passed a source float array, a destination float array (same size as source array), array width and height, "blurring" area width and height.
The function should "wrap-around" edges for the blurring/averages calculations.
Here is example code that blur with a rectangular shape:
/*****************************************
* Find averages extended variations
*****************************************/
void findaverages_ext(float *floatdata, float *dest_data, int fwidth, int fheight, int scale, int aw, int ah, int weight, int xoff, int yoff)
{
printf("findaverages_ext scale: %d, width: %d, height: %d, weight: %d \n", scale, aw, ah, weight);
float total = 0.0;
int spos = scale * fwidth * fheight;
int apos;
int w = aw;
int h = ah;
float* f_temp = new float[fwidth * fheight];
// Horizontal
for(int y=0;y<fheight ;y++)
{
Sleep(10); // Do not burn your processor
total = 0.0;
// Process entire window for first pixel (including wrap-around edge)
for (int kx = 0; kx <= w; ++kx)
if (kx >= 0 && kx < fwidth)
total += floatdata[y*fwidth + kx];
// Wrap
for (int kx = (fwidth-w); kx < fwidth; ++kx)
if (kx >= 0 && kx < fwidth)
total += floatdata[y*fwidth + kx];
// Store first window
f_temp[y*fwidth] = (total / (w*2+1));
for(int x=1;x<fwidth ;x++) // x width changes with y
{
// Substract pixel leaving window
if (x-w-1 >= 0)
total -= floatdata[y*fwidth + x-w-1];
// Add pixel entering window
if (x+w < fwidth)
total += floatdata[y*fwidth + x+w];
else
total += floatdata[y*fwidth + x+w-fwidth];
// Store average
apos = y * fwidth + x;
f_temp[apos] = (total / (w*2+1));
}
}
// Vertical
for(int x=0;x<fwidth ;x++)
{
Sleep(10); // Do not burn your processor
total = 0.0;
// Process entire window for first pixel
for (int ky = 0; ky <= h; ++ky)
if (ky >= 0 && ky < fheight)
total += f_temp[ky*fwidth + x];
// Wrap
for (int ky = fheight-h; ky < fheight; ++ky)
if (ky >= 0 && ky < fheight)
total += f_temp[ky*fwidth + x];
// Store first if not out of bounds
dest_data[spos + x] = (total / (h*2+1));
for(int y=1;y< fheight ;y++) // y width changes with x
{
// Substract pixel leaving window
if (y-h-1 >= 0)
total -= f_temp[(y-h-1)*fwidth + x];
// Add pixel entering window
if (y+h < fheight)
total += f_temp[(y+h)*fwidth + x];
else
total += f_temp[(y+h-fheight)*fwidth + x];
// Store average
apos = y * fwidth + x;
dest_data[spos+apos] = (total / (h*2+1));
}
}
delete f_temp;
}
What I need is similar functions that for each pixel finds the average (blur) of pixels from shapes different than rectangular.
The specific shapes are: "S" (sharp edges), "O" (rectangular but hollow), "+" and "X", where the average float is stored at the center pixel on destination data array. Size of blur shape should be variable, width and height.
The functions does not need to be pixelperfect, only optimized for performance. There could be separate functions for each shape.
I am also happy if anyone can tip me of how to optimize the example function above for rectangluar blurring.
What you are trying to implement are various sorts of digital filters for image processing. This is equivalent to convolving two signals where the 2nd one would be the filter's impulse response. So far, you regognized that a "rectangular average" is separable. By separable I mean, you can split the filter into two parts. One that operates along the X axis and one that operates along the Y axis -- in each case a 1D filter. This is nice and can save you lots of cycles. But not every filter is separable. Averaging along other shapres (S, O, +, X) is not separable. You need to actually compute a 2D convolution for these.
As for performance, you can speed up your 1D averages by properly implementing a "moving average". A proper "moving average" implementation only requires a fixed amount of little work per pixel regardless of the averaging "window". This can be done by recognizing that neighbouring pixels of the target image are computed by an average of almost the same pixels. You can reuse these sums for the neighbouring target pixel by adding one new pixel intensity and subtracting an older one (for the 1D case).
In case of arbitrary non-separable filters your best bet performance-wise is "fast convolution" which is FFT-based. Checkout www.dspguide.com. If I recall correctly, there is even a chapter on how to properly do "fast convolution" using the FFT algorithm. Although, they explain it for 1-dimensional signals, it also applies to 2-dimensional signals. For images you have to perform 2D-FFT/iFFT transforms.
To add to sellibitze's answer, you can use a summed area table for your O, S and + kernels (not for the X one though). That way you can convolve a pixel in constant time, and it's probably the fastest method to do it for kernel shapes that allow it.
Basically, a SAT is a data structure that lets you calculate the sum of any axis-aligned rectangle. For the O kernel, after you've built a SAT, you'd take the sum of the outer rect's pixels and subtract the sum of the inner rect's pixels. The S and + kernels can be implemented similarly.
For the X kernel you can use a different approach. A skewed box filter is separable:
You can convolve with two long, thin skewed box filters, then add the two resulting images together. The center of the X will be counted twice, so will you need to convolve with another skewed box filter, and subtract that.
Apart from that, you can optimize your box blur in many ways.
Remove the two ifs from the inner loop by splitting that loop into three loops - two short loops that do checks, and one long loop that doesn't. Or you could pad your array with extra elements from all directions - that way you can simplify your code.
Calculate values like h * 2 + 1 outside the loops.
An expression like f_temp[ky*fwidth + x] does two adds and one multiplication. You can initialize a pointer to &f_temp[ky*fwidth] outside the loop, and just increment that pointer in the loop.
Don't do the division by h * 2 + 1 in the horizontal step. Instead, divide by the square of that in the vertical step.