When I use Aparapi with an AMD Radeon R7 450 graphics card with older drivers installed, the maximum value of the size parameter in the code below can be 268,435,455.
Which corresponds to the 2D image size 16384 X 16384 = 268,435,456 (screenshot below).
When I usually use the AMD Radeon RX 5700 XT graphics card, which also has a 2D image size of 16384 X 16384 = 268,435,456, I get this error:
Total Local Kernel Size: Exceeds Maximum Allowed Local Kernel Size: 256 failed [ERROR] Failed to execute command
That is size value cannot be greater than 256.
Same issue with NVIDIA GeForce RTX 3060 Ti even though it has a 2D image size of 32768 X 32768 = 1,073,741,824.
Tell me what could be the problem? Why is code performance lower in this case on newer video cards?
Code:
int size = 268435455;
double[] a = new double[size];
double[] b = new double[size];
double[] c = new double[size];
for (int i = 0; i < size; i++)
{
a[i] = i;
b[i] = i;
}
Kernel kernel = new Kernel()
{
#Override
public void run()
{
int gid = getGlobalId();
c[gid] = a[gid] + b[gid];
}
};
kernel.execute(size);
kernel.dispose();
screen GPU Caps Viewer
AMD Radeon R7 450:
AMD Radeon RX 5700 XT:
NVIDIA GeForce RTX 3060 Ti:
Related
I wanted to convert some images to pdf
So in order to do that, I need to make pages for the image first
I will have to provide the width and height of the page and put the image on the page,
The problem is that the resolution of some images is greater than the other so the pdf does not get formed on a constant scale.
I need to make the page's scale constant without changing the resolution.
some image resolution which I tried
4160 × 3120,
720 × 1560,
466 × 400,
577 × 360,
492 × 144,
554 × 554,
I tried using this code
double ratio = (float) bitmap.getWidth() / (float) bitmap.getHeight();
double bestDelta = Double.MAX_VALUE;
int bestI = 0;
int bestJ = 0;
for (int i = 1; i < 100; i++)
{
for (int j = 1; j < 100; j++)
{
double newDelta = Math.abs ((double) i / (double) j - ratio);
if (newDelta < bestDelta)
{
bestDelta = newDelta;
bestI = i;
bestJ = j;
}
}
}
pageInfo = new PdfDocument.PageInfo.Builder(bestI, bestJ, page_no).create();
and getting the ratios but still some resolution give bigger values at some resolutions(here 466 × 400) which generates some bigger images
I'll recommend you to, use maxHeight field in you layout file.
android:maxHeight="50dp"
By this, your image cannot exceed that specified value.
I am dealing with a problem which kind of "forked" from a project I'm working on. It was not necessary solving for the project itself, but I'm mentioning the origin because it is kind of a 'strangely specific' task.
I am trying to read in a small BufferedImage from a file (8x8 pixels).
This image's pixels are written into an integer array, with length 64 (obviously).
Then, a new Array with the length 64*64 (=4096) is created. The pixels of the small array are copied into the large one 64 times, just resetting the smaller index to 0 everytime it reaches the end.
Finally, I create a new BufferedImage with width = 64 and height = 64. The large array is then set as rgbArray of said BufferedImage. The code is as follows:
public static void main(String[] args)throws IOException {
BufferedImage toCopy = ImageIO.read(new File("smallStripes.png"));
BufferedImage copiedNTimes = new BufferedImage(64, 64, BufferedImage.TYPE_BYTE_BINARY);
//copiedNTimes is to be the resulting image
Graphics2D g2d = (Graphics2D) copiedNTimes.getGraphics();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, 64, 64);
int[] smallPixels = new int[64];
toCopy.getRGB(0, 0, 8, 8, smallPixels, 0, 8);
//copy the rgb array of read image into the 64 - array
int[] copied = copyNTimes(smallPixels, new int[64*64]);
copiedNTimes.setRGB(0, 0, 64, 64, copied, 0, 8);
//setting the rgb array of result image to the copied one
FileOutputStream fos = new FileOutputStream(new File("result.png"));
ImageIO.write(copiedNTimes, "png", fos);
}
static int[] copyNTimes(int[] small, int[] big){
//this method copies the small array into the larger one
//until the larger one is 'filled up'
int index = 0;
for(int x = 0 ; x < big.length; x++){
big[x] = small[index];
index++;
if(index == small.length)
index = 0;
}
return big;
}
It works more or less as I expected it to, but images are written 'shifted':
smallStripes.png:
result.png :
My question is:
How could I accomplish that the stripes 'line up' to each other? Right now it is, from left to right, 8px black, 8px white, 8px black... and so forth.
Why not 64 px black (new line) 64 px white (new line) etc.?
As is already said, it is oddly specific and oversimplified so I can describe it better.
The code you have uses scanline=8 as last parameter to setRGB and also wrong logic in copyNTimes which causes your stripped effect. If you want 8x8 pixel image repeating into 64x64 pixel image as 8x8 blocks either replace your setRGB call with this to repeat the small image into the larger one:
for (int x = 0 ; x < 64 ; x += 8)
for (int y = 0 ; y < 64 ; y += 8)
copiedNTimes.setRGB(x, y, 8, 8, smallPixels, 0, 8);
Or replace your setRGB call with this to build the larger int[] first and apply it in one step:
copiedNTimes.setRGB(0, 0, 64, 64, copied, 0, 64);
static int[] copyNTimes(int[] small, int[] big){
for(int x = 0 ; x < big.length; x++){
big[x] = small[8 * ((x / 64) % 8) + (x % 8)];
}
return big;
}
I have been developing my java game for around 1.5 years now, and it has been running with around 3200 FPS on my PC (Intel I7, GTX 970, 8GB RAM).
However a few days back I tried it on my LAPTOP (Intel I7, GTX 1050TI, 16GB RAM). It's hardware is similar to my PC, however it barely hits 50 FPS. I noticed the GPU usage is 0 when running my game (on the laptop, unsure about PC). This difference seems abnormally big compared to the difference on the 2 machine.
I set the GTX 1050TI as first GPU, it increased the FPS from 30 to 50 on the laptop, still the usage is 0 (MSI Afterburner).
The two for loops below alone takes up 10 miliseconds on the laptop, but it runs fine on the PC, so I don't think so it is an optimization problem.
int xStart = (int) Math.max(0, handler.getGameCamera().getxOffset() / Tile.TILEWIDTH);
int xEnd = (int) Math.min(width, (handler.getGameCamera().getxOffset()
+ handler.getWidth()) / Tile.TILEWIDTH + 1);
int yStart = (int) Math.max(0, handler.getGameCamera().getyOffset() / Tile.TILEHEIGHT);
int yEnd = (int) Math.min(height, (handler.getGameCamera().getyOffset()
+ handler.getHeight()) / Tile.TILEHEIGHT + 1);
for(int y = yStart; y < yEnd; y++) {
for(int x = xStart; x < xEnd; x++) {
getTile(x, y).render(g, (int) (x * Tile.TILEWIDTH
- handler.getGameCamera().getxOffset()),
(int) (y * Tile.TILEHEIGHT - handler.getGameCamera().getyOffset()));
}
}
Looking at the hardware of both the PC and the LAPTOP, the FPS should be similar. Is it the GPU usage, or something else?
--UPDATE:
The GPU is working now! on 60% usage, so
I managed to get the laptop to 400FPS, with OPENGL hardware acceleration
Still, is 3200 FPS - 400 FPS realistic for two machines that are this similar in terms of hardware?
I am trying to use canny edge detection on each frame in a video. I can use it no problem but because each image is different the threshold parameters in the canny method will need to be custom to that image.
I have got good advice on here about calculating the median and then using .33 percentile above and below that for high and low threshold parameters in the canny method.
something like
Imgproc.Canny(gray, fullCanny, thirdAboveMedian, thirdBelowMedian);
So I have tried calculating the median and the percentiles and plugging them in but my calculations must be wrong somewhere as I am only getting a black screen with these values??
here is the code i used to work it out.
Mat fullCanny = new Mat();
fullCanny=gray.clone();
fullCanny.reshape(0,1);
double median;
double thirdAboveMedian;
double thirdBelowMedian;
int[] histogram = hist(fullCanny);
if(histogram.length%2==0)
{
median = (histogram[histogram.length/2] + histogram[histogram.length/2 - 1 ])/2;
thirdAboveMedian = histogram[(histogram.length/2)+(histogram.length/2/3)];
thirdBelowMedian = histogram[(histogram.length/2)-(histogram.length/2/3)];
}
else
{
median = histogram[(int)histogram.length/2];
thirdAboveMedian = histogram[(int)(histogram.length/2)+(histogram.length/2/3)];
thirdBelowMedian = histogram[(histogram.length/2)-(histogram.length/2/3)];
}
System.out.println("median is "+median);
System.out.println("thirdAboveMedian is "+thirdAboveMedian);
System.out.println("thirdBelowMedian is "+thirdBelowMedian);
//run edge detection on the blurred gray image and display it on fullCanny mat
Imgproc.Canny(gray, fullCanny, thirdAboveMedian, thirdBelowMedian);
And the hist method
public static int[] hist(Mat img) {
// array for intensities
int hist[] = new int[256];
byte data[] = new byte[img.rows() * img.cols() * img.channels()];
img.get(0, 0, data);
for (int i = 0; i < data.length; i++) {
hist[(data[i] & 0xff)]++;
}
return hist;
}
Thanks
For some reason the frequencies as displaced
391 hz => 1162
440 hz => 2196
493 hz => 2454
I am using this values
final int audioFrames= 1024;
final float sampleRate= 44100.0f;
final int bitsPerRecord= 16;
final int channels= 1;
final boolean bigEndian = true;
final boolean signed= true;
byteData= new byte[audioFrames * 2]; //two bytes per audio frame, 16 bits
dData= new double[audioFrames * 2]; // real & imaginary
This is how I ready the data and transform it to doubles:
format = new AudioFormat(sampleRate, bitsPerRecord, channels, signed, bigEndian);
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
microphone = (TargetDataLine) AudioSystem.getLine(info);
microphone.open(format);
microphone.start();
int numBytesRead = microphone.read(byteData, 0, byteData.length);
Once the data is read, cast from 16 bit, big endian, signed to double
public void byteToDouble(){
ByteBuffer buf= ByteBuffer.wrap(byteData);
buf.order(ByteOrder.BIG_ENDIAN);
int i=0;
while(buf.remaining()>1){
short s = buf.getShort();
dData[ 2 * i ] = (double) s / 32768.0; //real
dData[ 2 * i + 1] = 0.0; // imag
++i;
}
}
And at last, run the FFT and find the frequency:
public void findFrequency(){
double frequency;
DoubleFFT_1D fft= new DoubleFFT_1D(audioFrames);
/* edu/emory/mathcs/jtransforms/fft/DoubleFFT_1D.java */
fft.complexForward(dData); // do the magic so we can find peak
for(int i = 0; i < audioFrames; i++){
re[i] = dData[i*2];
im[i] = dData[(i*2)+1];
mag[i] = Math.sqrt((re[i] * re[i]) + (im[i]*im[i]));
}
double peak = -1.0;
int peakIn=-1;
for(int i = 0; i < audioFrames; i++){
if(peak < mag[i]){
peakIn=i;
peak= mag[i];
}
}
frequency = (sampleRate * (double)peakIn) / (double)audioFrames;
System.out.print("Peak: "+peakIn+", Frequency: "+frequency+"\n");
}
You can interpolate between FFT result bins (parabolic or Sinc interpolation) to get a more accurate estimate of frequency. But you may have a bigger problem: your frequency source may be producing (or be being clipped to produce) some very strong odd harmonics or overtones that mask any fundamental sinusoid in the FFT result magnitudes. Thus you should try using a pitch detection/estimation algorithm instead of just trying to look for a (possibly missing) FFT peak.
Firstly, if the audio you're recording is long, you'll need to do FFT in chunks, preferably with windowing each chunk before performing FFT. FFT only computes one fundamental frequency, so you need to take FFT at many places if the frequency changes many times.
Accuracy can also be improved from sliding windows. This means that you would take a chunk, then slide over slightly and take another chunk, so that the chunks overlap. How much you slide over is variable, and the size of each chunk is also variable.
Then, FFT alone might produce false results. You can do more analysis like Cepstrum analysis or Harmonic Product Spectrum analysis on the power spectrum produces by the FFT to try and estimate the pitch more accurately.