I draw the constellation line in the AR view of android device. using the following code. At beginning ,the response speed of objects in AR view is ok. After I closed the AR view or left the AR view, and reopen or back to the AR view. The response speed of objects(constellations) in AR view became slower(may take it 1 second). How to deal with this issue and speed up. lenght1 = 352, length2 = 384. how to improve the performance.
By the way, after I uninstall the app, and run the app again, the response speed of objects in AR view become the normal.
private void drawConstellationLine(Canvas canvas, int displayHeight,
int displayWidth) {
int length;
float ex = 0, ey = 0, bx = 0, by = 0;
Paint pline = new Paint();
pline.setColor(Color.RED);
double time1 = System.currentTimeMillis();
int i,j,length1,length2;
for( i = 0, length1 = ShowMoon.starlinelist.size(); i<length1;i++)
{
for( j = 0, length2 = ShowMoon.starlist.size(); j<length2;j++){
//System.out.println("length2:"+length2);
if(ShowMoon.starlinelist.get(i).beginhr ==ShowMoon.starlist.get(j).hr) {
bx = (float)ShowMoon.starlist.get(j).x;
by = (float)ShowMoon.starlist.get(j).y;
}
if(ShowMoon.starlinelist.get(i).endhr ==ShowMoon.starlist.get(j).hr) {
ex = (float)ShowMoon.starlist.get(j).x;
ey = (float)ShowMoon.starlist.get(j).y;
}
}
if (((bx >= 0 && bx <=displayWidth) ||( ex >= 0 && ex <= displayWidth))
&& ((ey >= 0 && ey <=displayHeight) || (by >= 0 && by <= displayHeight))){
canvas.drawLine(bx, by, ex, ey, pline);
//
double time2 = System.currentTimeMillis();
System.out.println("time dif:"+(time2-time1));
}
}
these two codes: if(ShowMoon.starlinelist.get(i).beginhr ==ShowMoon.starlist.get(j).hr).
if(ShowMoon.starlinelist.get(i).endhr ==ShowMoon.starlist.get(j).hr)
take a lot of time.
Related
I'm trying to deal with ECG signal processing in android. I want to implement simple digital filters (lowpass, highpass)
I've got a transfer function:
here is what i've found:
wikipedia - lowpass filter - it looks quite easy here.
for i from 1 to n
y[i] := y[i-1] + α * (x[i] - y[i-1])
but there is nothing about transfer function which I want to use.
I also found the following matlab code
%% Low Pass Filter H(z) = (1 - 2z^(-6) + z^(-12)) / (1 - 2z^(-1) + z^(-2))
b = [1 0 0 0 0 0 -2 0 0 0 0 0 1];
a = [1 -2 1];
h_l = filter(b,a,[1 zeros(1,12)]);
ecg_l = conv (ecg ,h_l);
but there is no function like filter and conv in java (or I missed something).
Also I was looking on stackoverflow for an answer. But I didn't found anything about transfer function.
so can someone help me? I just want to move on with my project.
Given a time-domain recurrence equation (such as the one you quoted from wikipedia), the corresponding transfer function in the z-domain can relatively easily be obtained by using the following properties:
Where X(z) and Y(z) are the z-transforms of the time-domain input sequence x and output sequence y respectively.
Going the other way around, given a transfer function which can be expressed as a ratio of polynomials in z, such as:
the recurrence equation of the transfer function can be written as:
There are of course many different ways to implement such a recurrence equation, but a simple filter implementation following the Direct Form II would be along the line of:
// Implementation of an Infinite Impulse Response (IIR) filter
// with recurrence equation:
// y[n] = -\sum_{i=1}^M a_i y[n-i] + \sum_{i=0}^N b_i x[n-i]
public class IIRFilter {
public IIRFilter(float a_[], float b_[]) {
// initialize memory elements
int N = Math.max(a_.length, b_.length);
memory = new float[N-1];
for (int i = 0; i < memory.length; i++) {
memory[i] = 0.0f;
}
// copy filter coefficients
a = new float[N];
int i = 0;
for (; i < a_.length; i++) {
a[i] = a_[i];
}
for (; i < N; i++) {
a[i] = 0.0f;
}
b = new float[N];
i = 0;
for (; i < b_.length; i++) {
b[i] = b_[i];
}
for (; i < N; i++) {
b[i] = 0.0f;
}
}
// Filter samples from input buffer, and store result in output buffer.
// Implementation based on Direct Form II.
// Works similar to matlab's "output = filter(b,a,input)" command
public void process(float input[], float output[]) {
for (int i = 0; i < input.length; i++) {
float in = input[i];
float out = 0.0f;
for (int j = memory.length-1; j >= 0; j--) {
in -= a[j+1] * memory[j];
out += b[j+1] * memory[j];
}
out += b[0] * in;
output[i] = out;
// shift memory
for (int j = memory.length-1; j > 0; j--) {
memory[j] = memory[j - 1];
}
memory[0] = in;
}
}
private float[] a;
private float[] b;
private float[] memory;
}
which you could use to implement your specific transfer function like so:
float g = 1.0f/32.0f; // overall filter gain
float[] a = {1, -2, 1};
float[] b = {g, 0, 0, 0, 0, 0, -2*g, 0, 0, 0, 0, 0, g};
IIRFilter filter = new IIRFilter(a, b);
filter.process(input, output);
Note that you can alternatively also factorize the numerator and denominator into 2nd order polynomials and obtain a cascade of 2nd order filters (known as biquad filters).
I need an algorithm that can detect a 'wiggle' gesture on Android, and by that I mean where the phone is held in portrait mode and the wrist is twisted left and right, like the motion of opening a round door handle. So I need to capture rotation back and forth around the z axis for a period of time.
A (crude) picture to illustrate the motion I need to capture:
I've tried a number of different algorithms that capture shaking, such as this "Shoogle For Yer Photos" solution seen here on Github, which work quite well, but capture shaking on every axis using the accelerometer. How would I restrict an algorithm like this to only detect rotation back and forth on the Z-axis, 'wiggling' for a minimum of say 4 seconds?
Here is an extract from the 'Shoogle For Yer Photos' code posted above, which shows how they handle shake detection:
private static final long KEEP_DATA_POINTS_FOR = 1500;
private static final long MINIMUM_EACH_DIRECTION = 7;
private static final float POSITIVE_COUNTER_THRESHHOLD = (float) 2.0;
private static final float NEGATIVE_COUNTER_THRESHHOLD = (float) -2.0;
public void checkForShake() {
long curTime = System.currentTimeMillis();
long cutOffTime = curTime - KEEP_DATA_POINTS_FOR;
while(dataPoints.size() > 0 && dataPoints.get(0).atTimeMilliseconds < cutOffTime) dataPoints.remove(0);
int x_pos =0, x_neg=0, x_dir = 0, y_pos=0, y_neg=0, y_dir=0, z_pos=0, z_neg = 0, z_dir = 0;
for(DataPoint dp: dataPoints){
if (dp.x > POSITIVE_COUNTER_THRESHHOLD && x_dir < 1) {
++x_pos;
x_dir = 1;
}
if (dp.x < NEGATIVE_COUNTER_THRESHHOLD && x_dir > -1) {
++x_neg;
x_dir = -1;
}
if (dp.y > POSITIVE_COUNTER_THRESHHOLD && y_dir < 1) {
++y_pos;
y_dir = 1;
}
if (dp.y < NEGATIVE_COUNTER_THRESHHOLD && y_dir > -1) {
++y_neg;
y_dir = -1;
}
if (dp.z > POSITIVE_COUNTER_THRESHHOLD && z_dir < 1) {
++z_pos;
z_dir = 1;
}
if (dp.z < NEGATIVE_COUNTER_THRESHHOLD && z_dir > -1) {
++z_neg;
z_dir = -1;
}
}
if ((x_pos >= MINIMUM_EACH_DIRECTION && x_neg >= MINIMUM_EACH_DIRECTION) ||
(y_pos >= MINIMUM_EACH_DIRECTION && y_neg >= MINIMUM_EACH_DIRECTION) ||
(z_pos >= MINIMUM_EACH_DIRECTION && z_neg >= MINIMUM_EACH_DIRECTION) ) {
lastShake = System.currentTimeMillis();
last_x = 0; last_y=0; last_z=0;
dataPoints.clear();
triggerShakeDetected();
return;
}
}
Any help will be greatly appreciated, thanks.
I want to get the dominant color in an Android CvCameraViewFrame object. I use the following OpenCV Android code to do that. This code is converted from OpenCV c++ code to OpenCV Android code. In the following code I loop through all the pixels in my camera frame and find the color of each pixel and store them in a HashMap to find the dominant color at the end of the loop. To loop through each pixel it takes about 30 seconds. This is unacceptable for me. Could somebody please review this code and point me how can I find the dominant color in a camera frame.
private String[] colors = {"cBLACK", "cWHITE", "cGREY", "cRED", "cORANGE", "cYELLOW", "cGREEN", "cAQUA", "cBLUE", "cPURPLE", "cPINK", "cRED"};
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
mRgba = inputFrame.rgba();
if (mIsColorSelected) {
Imgproc.cvtColor(mRgba, mRgba, Imgproc.COLOR_BGR2HSV);
int h = mRgba.height(); // Pixel height
int w = mRgba.width(); // Pixel width
int rowSize = (int)mRgba.step1(); // Size of row in bytes, including extra padding
float initialConfidence = 1.0f;
Map<String, Integer> tallyColors = new HashMap<String, Integer>();
byte[] pixelsTotal = new byte[h*rowSize];
mRgba.get(0,0,pixelsTotal);
//This for loop takes about 30 seconds to process for my camera frame
for (int y=0; y<h; y++) {
for (int x=0; x<w; x++) {
// Get the HSV pixel components
int hVal = (int)pixelsTotal[(y*rowSize) + x + 0]; // Hue
int sVal = (int)pixelsTotal[(y*rowSize) + x + 1]; // Saturation
int vVal = (int)pixelsTotal[(y*rowSize) + x + 2]; // Value (Brightness)
// Determine what type of color the HSV pixel is.
String ctype = getPixelColorType(hVal, sVal, vVal);
// Keep count of these colors.
int totalNum = 0;
try{
totalNum = tallyColors.get(ctype);
} catch(Exception ex){
totalNum = 0;
}
totalNum++;
tallyColors.put(ctype, totalNum);
}
}
int tallyMaxIndex = 0;
int tallyMaxCount = -1;
int pixels = w * h;
for (int i=0; i<colors.length; i++) {
String v = colors[i];
int pixCount;
try{
pixCount = tallyColors.get(v);
} catch(Exception e){
pixCount = 0;
}
Log.i(TAG, v + " - " + (pixCount*100/pixels) + "%, ");
if (pixCount > tallyMaxCount) {
tallyMaxCount = pixCount;
tallyMaxIndex = i;
}
}
float percentage = initialConfidence * (tallyMaxCount * 100 / pixels);
Log.i(TAG, "Color of currency note: " + colors[tallyMaxIndex] + " (" + percentage + "% confidence).");
}
return mRgba;
}
private String getPixelColorType(int H, int S, int V)
{
String color;
if (V < 75)
color = "cBLACK";
else if (V > 190 && S < 27)
color = "cWHITE";
else if (S < 53 && V < 185)
color = "cGREY";
else { // Is a color
if (H < 14)
color = "cRED";
else if (H < 25)
color = "cORANGE";
else if (H < 34)
color = "cYELLOW";
else if (H < 73)
color = "cGREEN";
else if (H < 102)
color = "cAQUA";
else if (H < 127)
color = "cBLUE";
else if (H < 149)
color = "cPURPLE";
else if (H < 175)
color = "cPINK";
else // full circle
color = "cRED"; // back to Red
}
return color;
}
Thank you very much.
OpenCV has an Histogram method which counts all image colors. After the histogram is calculated all you would have to do is to chose the one with the biggest count...
Check here for a tutorial (C++): Histogram Calculation.
You might also the this stackoverflow answer which shows an example on how to use Android's histogram function Imgproc.calcHist().
Think about to resize your images, then you may multiply the results by the same scale:
resize( larg_image, smallerImage , interpolation=cv.CV_INTER_CUBIC );
Or,
you may check these solutions:
You could find dominant color using k-mean clustering method.
this link will be useful.
https://www.youtube.com/watch?v=f54-x3PckH8
I'm using this opencv code on Android for an intensity equalization. The time of execution is around 300ms per frame (720x480). Does anybody have an idea for a possible time optimization ?
Here is the code :
cvtColor(image, hsvImage, CV_BGR2HSV);
// Get intensity
intensity = hsvImage.at<Vec3b>((int)reference.Point_::y, (int)reference.Point_::x);
float value = (float)REGULAR_INTENSITY / intensity[2];
float saturation = (float)REGULAR_SATURATION / intensity[1];
if (counter == 15 && (int)intensity[2] < REGULAR_INTENSITY) {
equalization = false;
}
// Modify intensity
float transformedSaturation, transformedValue;
for(int i = 0; i < hsvImage.rows; i++) {
unsigned char *data = hsvImage.ptr(i);
for(int j = 0; j < hsvImage.cols; j++) {
transformedSaturation = (uchar)*++data * saturation;
if (transformedSaturation > MAX_COLOR) {
transformedSaturation = MAX_COLOR;
}
*data++ = transformedSaturation;
transformedValue = (uchar)*data * value;
if (transformedValue > MAX_COLOR) {
transformedValue = MAX_COLOR;
}
*data++ = transformedValue;
}
}
cvtColor(hsvImage, image, CV_HSV2BGR);
Have you tried using OpenCV transform ? I guess it is optimised, but I dont know about the saturating cast (that is if > max_color, then = max color)
I have drawn multiple circles of varying sizes and positions to a canvas, but I need to detect collisions between them.
public void run() {
while(Run){
if(!sHold.getSurface().isValid())
continue;
c[0][cnum].r++;
canvas = sHold.lockCanvas();
canvas.drawRGB(02, 02, 150);
Paint white = new Paint();
white.setColor(Color.WHITE);
if(c[0][cnum].x != 0 && c[0][cnum].y != 0)
canvas.drawCircle(c[0][cnum].x, c[0][cnum].y, c[0][cnum].r, white);
if(cnum!=0)
for(int i=0; i<cnum; i++)
canvas.drawCircle(c[1][i].x, c[1][i].y, c[1][i].r, white);
sHold.unlockCanvasAndPost(canvas);
if(((c[0][cnum].x - c[0][cnum].r)<0)||((c[0][cnum].y-c[0][cnum].r)<0)||((c[0][cnum].y+c[0][cnum].r)>height)||((c[0][cnum].x+c[0][cnum].r>width))){
c[1][cnum].x = c[0][cnum].x;
c[1][cnum].y = c[0][cnum].y;
c[1][cnum].r = c[0][cnum].r;
broken = true;
break;
}
}
}
You shouldn't do that on render phases.
When processing the logics you should check if circles intersects as described:
v1 = center of circle1
v2 = center of circle2
intersects = v1 - v2 < circle1radius + circle2radius
This Link is pretty useful!
Circle-Circle Collisions
It's very detailed and didatic
At the bottom of that page there are another links, to even more detailed stuff!
I used the Distance Between Centers method ---
Circles
By measuring the distance between each center you can say if they are colliding.
The distance should never be more then the sum of the 2 radius.
Here's what I did:
private boolean checkDrawContains(ShapeDrawable newHole)
{
long newCenterX = newHole.getBounds().left + (newHole.getBounds().width()/2); //Get the center of my shapes
long newCenterY = newHole.getBounds().top + (newHole.getBounds().height()/2);
for(ShapeDrawable hole: mHoles) // I was storing the circles in an ArrayList
{
long centerX = hole.getBounds().left + (hole.getBounds().width()/2); //Get the center of my shapes
long centerY = hole.getBounds().top + (hole.getBounds().height()/2);
long x = centerX - newCenterX;
long y = centerY - newCenterY;
long aux = (long) ((Math.pow(Math.abs(x),2)) + (Math.pow(Math.abs(y),2))); //Pythagoras the hard way :P
long distance = (long) Math.sqrt(aux);
long sRads = (newHole.getBounds().width()/2) + (hole.getBounds().width()/2);
if(distance <= sRads ) {
return true; //Is Colliding!
}
}
return false; // Is not Colliding!
}