I have question to mesh drawed by triangle_strip and line_strip with AndEngine.
I'm generating 2d terrain using triangle_strip , triangles are created this way
1 3
|\ |\
| \| \
0 2 4
final int pSegmentsCount = 51;
final int pVertexCount = ( Mesh.VERTEX_SIZE * (pSegmentsCount) );
final float pColor = new Color(0f,0f,0f).getABGRPackedFloat();
final float pSegmentWidth = ( CAMERA_WIDTH/pSegmentsCount );
float[] pBufferData = new float[pVertexCount];
mHeightOffsetCurrent = new float[pVertexCount];
float x = 0f,y = 0f;
for (int i = 0;i<(pSegmentsCount);i++){
if (i%2!=0) { //every 3rd point goes up 2-4-6 , 0-1-3-5 stays down at 0 , x increments every third point
y = 200;
} else {
x = pSegmentWidth*i; //step right by segment
y = 0;
}
mHeightOffsetCurrent[i] = 0; //init default offset
pBufferData[(i * Mesh.VERTEX_SIZE) + Mesh.VERTEX_INDEX_X] = x;
pBufferData[(i * Mesh.VERTEX_SIZE) + Mesh.VERTEX_INDEX_Y] = y;
pBufferData[(i * Mesh.VERTEX_SIZE) + Mesh.COLOR_INDEX] = pColor;
}
pBufferData[((pSegmentsCount-1) * Mesh.VERTEX_SIZE) + Mesh.VERTEX_INDEX_Y] = -300;
final VertexBufferObjectManager VBOM = getVertexBufferObjectManager();
final HighPerformanceMeshVertexBufferObject pMeshVBO = new HighPerformanceMeshVertexBufferObject(VBOM, pBufferData, pVertexCount, DrawType.DYNAMIC, true, Mesh.VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT);
pMesh = new Mesh(0, 0,pVertexCount,DrawMode.LINE_STRIP,pMeshVBO);
i'm changing last vertex y position to better illustrate it
here is what i get ,
line_strip
triangle_strip
when i set Y of the last point to 0 i still see line with gradient to starting point.
What i'm doing wrong ? Why the last element is connected with the first one and how to fix this?
Arrays are drawed by glDrawArrays.
public static final int VERTEX_INDEX_X = 0;
public static final int VERTEX_INDEX_Y = Mesh.VERTEX_INDEX_X + 1;
public static final int COLOR_INDEX = Mesh.VERTEX_INDEX_Y + 1;
public static final int VERTEX_SIZE = 2 + 1;
Related
The shape of the tflite model is [1, 2535, 85]. You can find the tflite model here and label text here.
This is how the bug looks
This is the project I used https://github.com/hunglc007/tensorflow-yolov4-tflite/tree/master/android with some few changes. The changes are as following
Added the tflite model and the text in the assets folder (the label text is already present in the project, its the same)
Line 57 DetectorActivity.java
private static final String TF_OD_API_MODEL_FILE = "yolov3-tiny.tflite";
private static final String TF_OD_API_LABELS_FILE = "file:///android_asset/coco.txt";
line 181 tflite/YoloV4Classifier.java
private static boolean isTiny = true;
line 426 tflite/YoloV4Classifier.java (Replace the function to the down below)
This is the code
private ArrayList<Recognition> getDetectionsForTiny(ByteBuffer byteBuffer, Bitmap bitmap) {
ArrayList<Recognition> detections = new ArrayList<Recognition>();
Map<Integer, Object> outputMap = new HashMap<>();
// outputMap.put(0, new float[1][OUTPUT_WIDTH_TINY[0]][4]);
outputMap.put(0, new float[1][OUTPUT_WIDTH_TINY[1]][labels.size() + 5]);
Object[] inputArray = {byteBuffer};
tfLite.runForMultipleInputsOutputs(inputArray, outputMap);
int gridWidth = OUTPUT_WIDTH_TINY[0];
float[][][] bboxes = (float [][][]) outputMap.get(0);
// float[][][] out_score = (float[][][]) outputMap.get(1);
int count = 0;
for (int i = 0; i < gridWidth;i++){
float maxClass = 0;
int detectedClass = -1;
final float[] classes = new float[labels.size()];
for (int c = 0;c< labels.size();c++){
classes [c] = bboxes[0][i][c+5];
}
for (int c = 0;c<labels.size();++c){
if (classes[c] > maxClass){
detectedClass = c;
maxClass = classes[c];
}
}
final float score = maxClass;
if (score > getObjThresh()){
final float xPos = bboxes[0][i][0];
final float yPos = bboxes[0][i][1];
final float w = bboxes[0][i][2];
final float h = bboxes[0][i][3];
final RectF rectF = new RectF(
Math.max(0, xPos - w / 2),
Math.max(0, yPos - h / 2),
Math.min(bitmap.getWidth() - 1, xPos + w / 2),
Math.min(bitmap.getHeight() - 1, yPos + h / 2));
detections.add(new Recognition("" + i, labels.get(detectedClass),score,rectF,detectedClass ));
count++;
}
}
Log.d("Count", " "+count);
return detections;
}
Please I donno where I'm going wrong! Struggling with it since days! Thanks for helping.
I have array of 2d points and I need to create a Path that passes through all of the points. I think I should use Path.cubicTo() method which creates bezier curve between two points using specified control points. The problem is that I don't know control points of my curve. How do I calculate them?
Maybe there's a better way of doing this? Maybe there's some sort of library that could help me?
After I read this articles it became quite simple.
This is how you do it on android. After you run this code your path p will go through all points from knotsArr array.
Point[] knotsArr = {new Point(0, 0),
new Point(5, 5),
new Point(10, 0),
new Point(15, 5)};
Point[][] controlPoints = BezierSplineUtil.getCurveControlPoints(knotsArr);
Point[] firstCP = controlPoints[0];
Point[] secondCP = controlPoints[1];
Path p = new Path();
p.moveTo(knots.get(0).x, knots.get(0).y);
for (int i = 0; i < firstCP.length; i++) {
p.cubicTo(firstCP[i].x, firstCP[i].y,
secondCP[i].x, secondCP[i].y,
knots.get(i + 1).x, knots.get(i + 1).y);
}
BezierSplineUtil.java
public class BezierSplineUtil {
public static class Point {
public final float x;
public final float y;
public Point(float x, float y) {
this.x = x;
this.y = y;
}
}
/**
* Get open-ended bezier spline control points.
*
* #param knots bezier spline points.
* #return [2 x knots.length - 1] matrix. First row of the matrix = first
* control points. Second row of the matrix = second control points.
* #throws IllegalArgumentException if less than two knots are passed.
*/
public static Point[][] getCurveControlPoints(Point[] knots) {
if (knots == null || knots.length < 2) {
throw new IllegalArgumentException("At least two knot points are required");
}
final int n = knots.length - 1;
final Point[] firstControlPoints = new Point[n];
final Point[] secondControlPoints = new Point[n];
// Special case: bezier curve should be a straight line
if (n == 1) {
// 3P1 = 2P0 + P3
float x = (2 * knots[0].x + knots[1].x) / 3;
float y = (2 * knots[0].y + knots[1].y) / 3;
firstControlPoints[0] = new Point(x, y);
// P2 = 2P1 - P0
x = 2 * firstControlPoints[0].x - knots[0].x;
y = 2 * firstControlPoints[0].y - knots[0].y;
secondControlPoints[0] = new Point(x, y);
return new Point[][] { firstControlPoints, secondControlPoints };
}
// Calculate first bezier control points
// Right hand side vector
float[] rhs = new float[n];
// Set right hand side X values
for (int i = 1; i < n - 1; i++) {
rhs[i] = 4 * knots[i].x + 2 * knots[i + 1].x;
}
rhs[0] = knots[0].x + 2 * knots[1].x;
rhs[n - 1] = (8 * knots[n - 1].x + knots[n].x) / 2f;
// Get first control points X-values
float[] x = getFirstControlPoints(rhs);
// Set right hand side Y values
for (int i = 1; i < n - 1; i++) {
rhs[i] = 4 * knots[i].y + 2 * knots[i + 1].y;
}
rhs[0] = knots[0].y + 2 * knots[1].y;
rhs[n - 1] = (8 * knots[n - 1].y + knots[n].y) / 2f;
// Get first control points Y-values
float[] y = getFirstControlPoints(rhs);
for (int i = 0; i < n; i++) {
// First control point
firstControlPoints[i] = new Point(x[i], y[i]);
// Second control point
if (i < n - 1) {
float xx = 2 * knots[i + 1].x - x[i + 1];
float yy = 2 * knots[i + 1].y - y[i + 1];
secondControlPoints[i] = new Point(xx, yy);
} else {
float xx = (knots[n].x + x[n - 1]) / 2;
float yy = (knots[n].y + y[n - 1]) / 2;
secondControlPoints[i] = new Point(xx, yy);
}
}
return new Point[][] { firstControlPoints, secondControlPoints };
}
/**
* Solves a tridiagonal system for one of coordinates (x or y) of first
* bezier control points.
*
* #param rhs right hand side vector.
* #return Solution vector.
*/
private static float[] getFirstControlPoints(float[] rhs) {
int n = rhs.length;
float[] x = new float[n]; // Solution vector
float[] tmp = new float[n]; // Temp workspace
float b = 2.0f;
x[0] = rhs[0] / b;
// Decomposition and forward substitution
for (int i = 1; i < n; i++) {
tmp[i] = 1 / b;
b = (i < n - 1 ? 4.0f : 3.5f) - tmp[i];
x[i] = (rhs[i] - x[i - 1]) / b;
}
// Backsubstitution
for (int i = 1; i < n; i++) {
x[n - i - 1] -= tmp[n - i] * x[n - i];
}
return x;
}
}
I am new to game development.am using and-engine to develop the game.am create the scene like fall of object randomly from top of the screen use code below.
TimerHandler spriteTimerHandler;
float mEffectSpawnDelay = 3f;
spriteTimerHandler = new TimerHandler(mEffectSpawnDelay, true,
new ITimerCallback() {
#Override
public void onTimePassed(TimerHandler pTimerHandler) {
Random rand = new Random();
int y = (int) (resourcesManager.camera.getHeight() + resourcesManager.ball2.getHeight());
int minx = (int) (resourcesManager.ball1.getHeight());
int maxx = (int) (resourcesManager.camera.getWidth() - resourcesManager.ball2.getWidth());
int rangex = maxx- minx;
int x = rand.nextInt(rangex) + minx;
Sprite target = new Sprite(x, y, resourcesManager.ball2.deepCopy(),vbom);
attachChild(target);
int minDuration = 4;
int maxDuration = 8;
int rangeDuration = maxDuration - minDuration;
int actualDuration = rand.nextInt(rangeDuration) + minDuration;
MoveYModifier mod = new MoveYModifier(actualDuration, target.getY(),-target.getHeight());
target.registerEntityModifier(mod.deepCopy());
TargetsToBeAdded.add(target);
}
});
registerUpdateHandler(spriteTimerHandler);
from this code the object comes from the top of the screen but it comes all over the width.I want to set fall of the object from half of the screen to till end of the screen.Can any one know please help me to solve this issue.
int minx = (int) (resourcesManager.camera.getWidth() / 2);
I am new to android and I need to know how to make a graph or chart (eg. line chart) move i.e, from right to left.
Basically I am going to draw the graph in accordance with the RAM Memory Usage of the phone. I need to draw a graph similarly present in Task Manager of Windows.
Please help on this.
Take A Look This Class.
It's Simple and Useful.
Original Author is Arno den Hond, Google it.
I redesign this Class.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.view.View;
/**
* GraphView creates a scaled line or bar graph with x and y axis labels.
* #author Arno den Hond
* #redesign Reinhard & kimkmkm
*
*/
public class GraphView extends View {
public static boolean BAR = true;
public static boolean LINE = false;
private Paint paint;
private float[] values;
private String[] horlabels;
private String[] verlabels;
private String title;
private boolean type;
/**
* Generate Graph
* Variable Array for GraphView
* verlabel : Background Height Values
* horlabel : Background Width Values
* values : Max Values of Foreground Active Graph
*
* basic draw rule
* if Array is not null
* Draw Background width, height & active Graph all time
* or Array is null
* Draw Background width, height
* active Graph fixed 0
*
*/
public GraphView(Context context, float[] values, String title, String[] horlabels, String[] verlabels, boolean type) {
super(context);
if (values == null)
values = new float[0];
else
this.values = values;
if (title == null)
title = "";
else
this.title = title;
if (horlabels == null)
this.horlabels = new String[0];
else
this.horlabels = horlabels;
if (verlabels == null)
this.verlabels = new String[0];
else
this.verlabels = verlabels;
this.type = type;
paint = new Paint();
}
/**
* Graph for Background
* &
* Value for Background
*/
#Override
protected void onDraw(Canvas canvas) {
float border = 20;
float horstart = border * 2;
float height = getHeight();
float width = getWidth() - 1;
float max = 700;
float min = 0;
float diff = max - min;
float graphheight = height - (2 * border);
float graphwidth = width - (2 * border);
paint.setTextAlign(Align.LEFT);
/** vers : BackGround Height Values length*/
int vers = verlabels.length - 1;
for (int i = 0; i < verlabels.length; i++) {
paint.setColor(Color.LTGRAY);
// Width Line of background
float y = ((graphheight / vers) * i) + border;
// float y : ((getHeight / Height values length) * Height values length ) + 20
canvas.drawLine(horstart, y, width, y, paint);
// drawLine ( 40, y, getWidth()-1, y, paint)
paint.setColor(Color.WHITE);
// Left Height of background
canvas.drawText(verlabels[i], 0, y, paint);
}
/** hors : BackGround width Values length*/
int hors = horlabels.length - 1;
for (int i = 0; i < horlabels.length; i++) {
// Height Line of background
paint.setColor(Color.DKGRAY);
float x = ((graphwidth / hors) * i) + horstart;
canvas.drawLine(x, height - border, x, border, paint);
paint.setTextAlign(Align.CENTER);
if (i==horlabels.length-1)
paint.setTextAlign(Align.RIGHT);
if (i==0)
paint.setTextAlign(Align.LEFT);
// Value of Width
paint.setColor(Color.WHITE);
canvas.drawText(horlabels[i], x, height - 4, paint);
}
paint.setTextAlign(Align.CENTER);
canvas.drawText(title, (graphwidth / 2) + horstart, border - 4, paint);
/**
* Yellow Line Graph
* continue Repaint....
*
*/
if (max != min) {
paint.setColor(Color.YELLOW);
if (type == BAR) {
float datalength = values.length;
float colwidth = (width - (10 * border)) / datalength;
for (int i = 0; i < values.length; i++) {
float val = values[i] - min;
float rat = val / diff;
//diff : max - min
float h = graphheight * rat;
canvas.drawRect((i * colwidth) + horstart, (border - h) + graphheight, ((i * colwidth) + horstart) + (colwidth - 1), height - (border - 1), paint);
}
} else {
float datalength = values.length;
float colwidth = (width - (2 * border)) / datalength;
float halfcol = colwidth / 2;
float lasth = 0;
for (int i = 0; i < values.length; i++) {
float val = values[i] - min;
float rat = val / diff;
float h = graphheight * rat;
if (i > 0)
canvas.drawLine(((i - 1) * colwidth) + (horstart + 1) + halfcol, (border - lasth) + graphheight, (i * colwidth) + (horstart + 1) + halfcol, (border - h) + graphheight, paint);
lasth = h;
}
}
}
}
It's My Sample Code.
I did not test yet.
But I think This code works fine.
public class DrawGraph extends Activity{
/**
* Variable Array for GraphView
* verlabel : Background Height Values
* horlabel : Background Width Values
* values : Max Values of Foreground Active Graph
*/
private float[] values = new float[60];
private String[] verlabels = new String[] { "600","500","400","300","200","100","80","60","40","20","0", };
private String[] horlabels = new String[] { "0","10", "20", "30", "40", "50", "60"};
private GraphView graphView;
private LinearLayout graph;
private boolean runnable = false;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
graph = (LinearLayout)findViewById(R.id.graph);
graphView = new GraphView(DrawGraph.this, values, "TEST GRAPH", horlabels, verlabels, GraphView.LINE);
graph.addView(graphView);
runnable = true;
startDraw.start();
}
#Override
public void onDestroy(){
super.onDestroy();
runnable = false;
}
public void setGraph(int data){
for(int i=0; i<values.length-1; i++){
values[i] = values[i+1];
}
values[values.length-1] = (float)data;
graph.removeView(graphView);
graph.addView(graphView);
}
public Handler handler = new Handler(){
#Override
public void handleMessage(android.os.Message msg){
switch(msg.what){
case 0x01:
int testValue = (int)(Math.random() * 600)+1;
setGraph(testValue);
break;
}
}
}
public Thread startDraw = new Thread(){
#Override
public void run(){
while(runnable){
handler.sendEmptyMessage(0x01);
try{
Thread.sleep(1000);
} catch (Exception e){
e.printstacktrace();
}
}
}
}
Try AndroidPlot, it's a simple to use library!
See also achartengine.
I am developing an application in which there is a module for Image warping.I referred several sites but could not get any solution that could solve my problem.
Any tutorials/links or suggestions for face warping would be helpful.
This is from the samples shipped with Android SDK. From your question it's not clear if you want to know the Android API or the very warping algorithm
public class BitmapMesh extends GraphicsActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
private static class SampleView extends View {
private static final int WIDTH = 20;
private static final int HEIGHT = 20;
private static final int COUNT = (WIDTH + 1) * (HEIGHT + 1);
private final Bitmap mBitmap;
private final float[] mVerts = new float[COUNT*2];
private final float[] mOrig = new float[COUNT*2];
private final Matrix mMatrix = new Matrix();
private final Matrix mInverse = new Matrix();
private static void setXY(float[] array, int index, float x, float y) {
array[index*2 + 0] = x;
array[index*2 + 1] = y;
}
public SampleView(Context context) {
super(context);
setFocusable(true);
mBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.beach);
float w = mBitmap.getWidth();
float h = mBitmap.getHeight();
// construct our mesh
int index = 0;
for (int y = 0; y <= HEIGHT; y++) {
float fy = h * y / HEIGHT;
for (int x = 0; x <= WIDTH; x++) {
float fx = w * x / WIDTH;
setXY(mVerts, index, fx, fy);
setXY(mOrig, index, fx, fy);
index += 1;
}
}
mMatrix.setTranslate(10, 10);
mMatrix.invert(mInverse);
}
#Override protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFCCCCCC);
canvas.concat(mMatrix);
canvas.drawBitmapMesh(mBitmap, WIDTH, HEIGHT, mVerts, 0,
null, 0, null);
}
private void warp(float cx, float cy) {
final float K = 10000;
float[] src = mOrig;
float[] dst = mVerts;
for (int i = 0; i < COUNT*2; i += 2) {
float x = src[i+0];
float y = src[i+1];
float dx = cx - x;
float dy = cy - y;
float dd = dx*dx + dy*dy;
float d = FloatMath.sqrt(dd);
float pull = K / (dd + 0.000001f);
pull /= (d + 0.000001f);
// android.util.Log.d("skia", "index " + i + " dist=" + d + " pull=" + pull);
if (pull >= 1) {
dst[i+0] = cx;
dst[i+1] = cy;
} else {
dst[i+0] = x + dx * pull;
dst[i+1] = y + dy * pull;
}
}
}
private int mLastWarpX = -9999; // don't match a touch coordinate
private int mLastWarpY;
#Override public boolean onTouchEvent(MotionEvent event) {
float[] pt = { event.getX(), event.getY() };
mInverse.mapPoints(pt);
int x = (int)pt[0];
int y = (int)pt[1];
if (mLastWarpX != x || mLastWarpY != y) {
mLastWarpX = x;
mLastWarpY = y;
warp(pt[0], pt[1]);
invalidate();
}
return true;
}
}
}
Image warping generally consists of two main stages. In the first stage you look for points that match on each image. The second stage involves finding a transformation between the set of matched points. Neither stage is trivial and image warping (generally speaking) remains a difficult problem. I have had to solve this problem in the past and so can speak from experience.
By dividing the problem into two parts you can devise solutions for each part independently. It would be helpful to read some material on the web, http://groups.csail.mit.edu/graphics/classes/CompPhoto06/html/lecturenotes/14_WarpMorph_6.pdf, for example.
In stage one, cross correlation is often used as the basis for finding matching points on the two images.
The transformations used in stage two will determine how accurately you can warp one image onto another. A linear transformation will now be very good while a two dimensional transformation that uses spline approximation will certainly cope with nonlinearities.
Here is another helpful link