I am trying to draw a bitmap on a polygon has sides more than 4. ı am dealing with opengl to do this but i realised in 2d there is a method called drawBitmapMesh in Canvas for this. It worked for 4 side polygon but not working for 5.
This works
float verts[] = {0,0, 0,10, 0,20 ,0,30, 10,0, 10,10, 10,20, 10,30, 20,0, 20,10, 20,20, 20,30, 30,0, 30,10, 30,20, 30,30};
canvas.drawBitmapMesh(bitmap, 3, 3, verts, 0, null, 0, null);
This does not work gives runtime error.
float verts[] = {0,0, 0,10, 0,20 ,0,30, 0,40, 10,0, 10,10, 10,20, 10,30,10,40, 20,0, 20,10, 20,20, 20,30,20,40, 30,0, 30,10, 30,20, 30,30,30,40};
canvas.drawBitmapMesh(bitmap, 4, 4, verts, 0, null, 0, null);
From the SDK documentation:
verts Array of x,y pairs, specifying where the mesh should be drawn. There must be at least (meshWidth+1) * (meshHeight+1) * 2 + meshOffset values in the array
You have 38 values in your array, whereas the above calculation with the parameters gives: (4+1)*(4+1)*2 + 0 = 50 values ...
Related
I am trying to detect coin ( circle ) detection using Opencv4Android.
So far I have tried two approaches
1 ) Regular method :
// convert image to grayscale
Imgproc.cvtColor(mRgba, mGray, Imgproc.COLOR_RGBA2GRAY);
// apply Gaussian Blur
Imgproc.GaussianBlur(mGray, mGray, sSize5, 2, 2);
iMinRadius = 20;
iMaxRadius = 400;
iAccumulator = 300;
iCannyUpperThreshold = 100;
//apply houghCircles
Imgproc.HoughCircles(mGray, mIntermediateMat, Imgproc.CV_HOUGH_GRADIENT, 2.0, mGray.rows() / 8,
iCannyUpperThreshold, iAccumulator, iMinRadius, iMaxRadius);
if (mIntermediateMat.cols() > 0)
for (int x = 0; x < Math.min(mIntermediateMat.cols(), 10); x++) {
double vCircle[] = mIntermediateMat.get(0,x);
if (vCircle == null)
break;
pt.x = Math.round(vCircle[0]);
pt.y = Math.round(vCircle[1]);
radius = (int)Math.round(vCircle[2]);
// draw the found circle
Core.circle(mRgba, pt, radius, colorRed, iLineThickness);
}
2 ) Sobel and then Hough Cicles
// apply Gaussian Blur
Imgproc.GaussianBlur(mRgba, mRgba, sSize3, 2, 2,
Imgproc.BORDER_DEFAULT);
// / Convert it to grayscale
Imgproc.cvtColor(mRgba, mGray, Imgproc.COLOR_RGBA2GRAY);
// / Gradient X
Imgproc.Sobel(mGray, grad_x, CvType.CV_16S, 1, 0, 3, scale, delta,
Imgproc.BORDER_DEFAULT);
Core.convertScaleAbs(grad_x, abs_grad_x);
// / Gradient Y
Imgproc.Sobel(mGray, grad_y, CvType.CV_16S, 0, 1, 3, scale, delta,
Imgproc.BORDER_DEFAULT);
Core.convertScaleAbs(grad_y, abs_grad_y);
// / Total Gradient (approximate)
Core.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad);
iCannyUpperThreshold = 100;
Imgproc.HoughCircles(grad, mIntermediateMat,
Imgproc.CV_HOUGH_GRADIENT, 2.0, grad.rows() / 8,
iCannyUpperThreshold, iAccumulator, iMinRadius, iMaxRadius);
if (mIntermediateMat.cols() > 0)
for (int x = 0; x < Math.min(mIntermediateMat.cols(), 10); x++) {
double vCircle[] = mIntermediateMat.get(0, x);
if (vCircle == null)
break;
pt.x = Math.round(vCircle[0]);
pt.y = Math.round(vCircle[1]);
radius = (int) Math.round(vCircle[2]);
// draw the found circle
Core.circle(mRgba, pt, radius, colorRed, iLineThickness);
}
method one gives fair result in case of coin detection and method two gives better result
Out of these two methods second method processing is slow but results are good
Both of these methods are working when camera frmae is caputured using JavaCameraView or NativeCameraView from opencv library .
If I use same procedure on image captured from android naive image capture intent which returns Bitmap , I am unable to get any results at all i.e. no circles are detected at all.
In methods one sometimes I get circle detected when using Bitmap captured using android camera intent.
I also tried changing the captured bitmap as suggested in this Post but still no circle detection.
Can anybody tell me what modifications I have to do.
And also I want to know which algorithm will give better results in coin ( circle ) detection but with less processing.
I have played with various values of houghCircle method and also tried canny edge out put as intput to houghCircles but its not considerably good enough.
My requirement is to create a 3d surface plot(should also display the x y z axis) from a list of data points (x y z) values.The 3d visualization should be done on ANDROID.
My Inputs : Currently planning on using open gl 1.0 and java. I m also considering Adore3d , min3d and rgl package which uses open gl 1.0. Good at java ,but a novice at 3d programming.
Time Frame : 2 months
I would like to know the best way to go about it? Is opengl 1.0 good for 3d surface plotting?Any other packages/libraries that can be used with Android?
Well, you can plot the surface using OpenGL 1.0 or OpenGL 2.0. All you need to do is to draw the axes as lines and draw the surface as triangles. If you have your heightfield data, you would do:
float[][] surface;
int width, height; // 2D surface data and it's dimensions
GL.glBegin(GL.GL_LINES);
GL.glVertex3f(0, 0, 0); // line starting at 0, 0, 0
GL.glVertex3f(width, 0, 0); // line ending at width, 0, 0
GL.glVertex3f(0, 0, 0); // line starting at 0, 0, 0
GL.glVertex3f(0, 0, height); // line ending at 0, 0, height
GL.glVertex3f(0, 0, 0); // line starting at 0, 0, 0
GL.glVertex3f(0, 50, 0); // line ending at 0, 50, 0 (50 is maximal value in surface[])
GL.glEnd();
// display the axes
GL.glBegin(GL.GL_TRIANGLES);
for(int x = 1; x < width; ++ x) {
for(int y = 1; y < height; ++ y) {
float a = surface[x - 1][y - 1];
float b = surface[x][y - 1];
float c = surface[x][y];
float d = surface[x - 1][y];
// get four points on the surface (they form a quad)
GL.glVertex3f(x - 1, a, y - 1);
GL.glVertex3f(x, b, y - 1);
GL.glVertex3f(x, c, y);
// draw triangle abc
GL.glVertex3f(x - 1, a, y - 1);
GL.glVertex3f(x, c, y);
GL.glVertex3f(x - 1, d, y);
// draw triangle acd
}
}
GL.glEnd();
// display the data
This draws simple axes and heightfield, all in white color. It should be pretty straight forward to extend it from here.
Re the second part of your question:
Any other packages/libraries that can be used with Android?
Yes, it's now possible to draw an Android 3D Surface Plot with SciChart.
Link to Android Chart features page
Link to Android 3D Surface Plot example
Lots of configurations are possible including drawing wireframe, gradient colour maps, contours and real-time updates.
Disclosure, I'm the tech lead on the scichart team
I need gluUnProject to convert screen coordinates to world coordinates and right now I just about have it working. When my app runs it accurately tells me the coordinates on screen which I know are stored in my renderer thread and then pumps out screen coordinates. Unfortunately the screen coordinates seem to have no effect of world coordinates and the world coordinates remain at zero.
Here is my gluUnProject method
public void vector3 (GL11 gl){
int[] viewport = new int[4];
float[] modelview = new float[16];
float[] projection = new float[16];
float winx, winy, winz;
float[] newcoords = new float[4];
gl.glGetIntegerv(GL11.GL_VIEWPORT, viewport, 0);
((GL11) gl).glGetFloatv(GL11.GL_MODELVIEW_MATRIX, modelview, 0);
((GL11) gl).glGetFloatv(GL11.GL_PROJECTION_MATRIX, projection, 0);
winx = (float)setx;
winy = (float)viewport[3] - sety;
winz = 0;
GLU.gluUnProject(setx, (float)viewport[3] - sety, 0, modelview, 0, projection, 0, viewport, 0, newcoords, 0);
posx = (int)newcoords[0];
posy = (int)newcoords[1];
posz = (int)newcoords[2];
Log.d(TAG, "x= " + String.valueOf(posx));
Log.d(TAG, "y= " + String.valueOf(posy));
Log.d(TAG, "z= " + String.valueOf(posz));
}
Now I've searched and found this forum post and they came to the conclusion that it was to do with using getFloatv instead of getDoublev, but getDoublev does not seem to be supported by GL11
The method glGetDoublev(int, float[], int) is undefined for the type GL11
and also
The method glGetDoublev(int, double[], int) is undefined for the type GL11
should the double and float thing matter and if so how do I go about using doubles
Thank you
EDIT:
I was told that gluUnproject fails when too close to the near far clipping plane so I set winz to -5 when near is 0 and far is -10. This had no effect on the output.
I also logged each part of the newcoords[] array and they all return something that is NaN (not a number) could this be the problem or something higher up in the algorithm
I'm guessing you're working on the emulator? Its OpenGL implementation is rather buggy, and after testing I found that it returns all zeroes for the following calls:
gl11.glGetIntegerv(GL11.GL_VIEWPORT, viewport, 0);
gl11.glGetFloatv(GL11.GL_MODELVIEW_MATRIX, modelview, 0);
gl11.glGetFloatv(GL11.GL_PROJECTION_MATRIX, projection, 0);
The gluUnProject() function needs to calculate the inverse of the combined modelview-projection matrix, and since these are all zeroes, the inverse does not exist and will consist of NaNs. The resulting newcoords vector is therefor also all Nans.
Try it on a device with a proper OpenGL implementation, it should work. Keep in mind to still divide by newcoords[3] though ;-)
I'm developing on a Droid, version 2.1-update1. My supported GL extensions include GL_OES_point_sprite and GL_OES_point_size_array.
I am unable to get point sprites to render. The code below throws UnsupportedOperationException from GLWrapperBase at the glTexEnvi call. If I disable textures and comment out the glTexEnvi all, it throws the same exception further down, at glPointSizePointerOES().
Are point sprites properly supported in Android? Has anyone gotten them working? Or is there an issue with my code below?
// Note that gl is cast to GL11
gl.glEnable(GL11.GL_TEXTURE_2D);
gl.glEnable(GL11.GL_BLEND);
gl.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
gl.glDepthMask(false);
gl.glEnable(GL11.GL_POINT_SPRITE_OES);
gl.glTexEnvi( GL11.GL_POINT_SPRITE_OES, GL11.GL_COORD_REPLACE_OES, GL11.GL_TRUE );
gl.glEnableClientState(GL11.GL_VERTEX_ARRAY);
gl.glVertexPointer(2, GL11.GL_SHORT, 0, .vertBuffer);
gl.glEnableClientState(GL11.GL_POINT_SIZE_ARRAY_OES);
gl.glPointSizePointerOES(GL11.GL_FLOAT, 0, pointSizeBuffer);
Thanks
I got this working, here is my draw function
Initialize everything
gl.glEnable(GL10.GL_TEXTURE);
TextureManager.activateTexture(gl, R.drawable.water1); //Don't look for this, it's not public api, just looks upd texture id for android resource if loaded, and then activates it. it's the gl.glBindTexture() call replacement
gl.glEnable(GL11.GL_POINT_SPRITE_OES);
gl.glEnableClientState(GL11.GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES);
gl.glEnableClientState(GL11.GL_POINT_SIZE_ARRAY_OES);
gl.glEnableClientState(GL11.GL_POINT_SPRITE_OES);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
Set the texture environment up to use point sprites
gl.glTexEnvf(GL11.GL_POINT_SPRITE_OES, GL11.GL_COORD_REPLACE_OES, GL11.GL_TRUE);
Set up pointers to the data (First array is 2d laid out [x,y,x2,y2,...] second is 1d [s1,s2,..])
gl.glVertexPointer(2,GL11.GL_FLOAT,0,PosData);
((GL11)(gl)).glPointSizePointerOES(GL10.GL_FLOAT, 0, SizeData);
Draw
gl.glDrawArrays(GL10.GL_POINTS,0,MAX);
Disable stuff
gl.glDisableClientState(GL11.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL11.GL_POINT_SIZE_ARRAY_OES);
gl.glDisableClientState(GL11.GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES);
gl.glDisableClientState(GL11.GL_POINT_SIZE_ARRAY_OES);
gl.glDisable(GL10.GL_TEXTURE);
In my initializer I only have my projection setup and GL_BLEND enabled for blending. I think you would need GL_COLOR_MATERIAL if you wanted to color your sprite.
I got the point sprites working with ES 1.1 & 2 on a nexus one. I use a fixed point size so I didn´t have to use a size buffer but you can use my code to first get it working and then add the size buffer.
In my draw method:
gl.glEnable(GL11.GL_POINT_SPRITE_OES);
gl.glTexEnvf(GL11.GL_POINT_SPRITE_OES, GL11.GL_COORD_REPLACE_OES, GL11.GL_TRUE);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
// 2 dimensional array, (x1,y1, x2, y2, ...).
gl.glVertexPointer(2, GL10.GL_FLOAT, 0, mVerticesBuffer);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId);
gl.glPointSize(32); // Fixed point size for all points
// This only worked with GLES11 & GLES20.
GLES11.glDrawArrays(GLES11.GL_POINTS, 0, vertices.length);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisable(GL10.GL_TEXTURE_2D);
gl.glDisable(GL11.GL_POINT_SPRITE_OES);
if like me you're using MatrixTrackingGL you need to use glTexEnvf rather than glTexEnvi (f not i at the end) and you need to go into MatrixTrackingGL and change glPointSizePointerOES:
public void glPointSizePointerOES(int type, int stride, Buffer pointer) {
mgl11.glPointSizePointerOES(type, stride, pointer);
//throw new UnsupportedOperationException();
}
I'm sure there is a good reason why it is unsupported in the first place but I don't know it and it works for me on a ZTE Blade running android 2.1
For anyone wondering, MatrixTrackerGL comes from C:\Program Files\android-sdk-windows\samples\android-7\ApiDemos\src\com\example\android\apis\graphics\spritetext
It is used when setting up your GLSurface View:
// GraphicsRenderer is my implementation of Renderer
Graphics Renderer graphicsRenderer = new GraphicsRenderer(this);
GLSurfaceView mGLView = (GLSurfaceView) findViewById(R.id.graphics_glsurfaceview1);
mGLView.setGLWrapper(new GLSurfaceView.GLWrapper() {
public GL wrap(GL gl) {
return new MatrixTrackingGL(gl);
}});
mGLView.setEGLConfigChooser(true);
mGLView.setRenderer(graphicsRenderer);
and means you can use GLU.gluUnProject to do picking!:
MatrixGrabber matrixGrabber = new MatrixGrabber();
matrixGrabber.getCurrentModelView(gl);
matrixGrabber.getCurrentProjection(gl);
float[] vector = new float[4];
GLU.gluUnProject(x, y, 0f, matrixGrabber.mModelView, 0, matrixGrabber.mProjection, 0, new int[]{mGLView .getTop(),mGLView .getLeft(),mGLView .getWidth(),mGLView .getHeight()}, 0, vector, 0);
I'm not sure I'm using glDrawTex_OES correctly. In fact, I'm sure I'm not because I'm getting a black rectangle on the screen rather than the intended texture.
To get the silly points out of the way: Yes, the GL Extension string contains the OES_draw_texture token. Yes, the texture is loaded into memory/etc. correctly: it displays just fine if I map it to a polygon.
From reading the various bits of documentation I can find for it, it looks like I need to "configur[e] the texture crop rectangle ... via TexParameteriv() with pname equal to TEXTURE_CROP_RECT_OES". According to this post in the khronos forums (best documentation google can find for me), the values for that are "Ucr, Vcr, Wcr, Hcr. That is, left/bottom/width/height"
Here's the render code:
void SetUpCamera( int windowWidth, int windowHeight, bool ortho ) // only called once
{
glViewport( 0, 0, windowWidth, windowHeight );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
if( ortho )
{
float aspect = (float)windowWidth / (float)windowHeight;
float halfHeight = 32;
glOrthof( -halfHeight*aspect, halfHeight*aspect, -halfHeight, halfHeight, 1.0f, 100.0f );
}
else
{
mygluPerspective( 45.0f, (float)windowWidth / (float)windowHeight, 1.0f, 100.0f ); // I don't _actually_ have glu, but that's irrelevant--this does what you'd expect.
}
}
void DrawTexture( int windowWidth, int windowHeight, int texID )
{
// Clear back/depth buffer
glClearColor( 1, 1, 1, 1 );
glClearDepth( 1.0f );
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// Next 2 lines probably not necessary, but, you know, sanity check:
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
// set up texture
glBindTexture( GL_TEXTURE_2D, texID ); // texID is the glGenTexture result for a 64x64 2D RGB_8 texture - nothing crazy.
GLint coords [] = {0, 0, 64, 64};
glTexParameteriv( GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, coords );
// blit? =(
glDrawTexiOES( windowWidth / 2 - 32, windowHeight - 70, 10, 64, 64 );
}
Am I missing something obvious? Doing anything just plain dumb?
Apparently the problem is that you're (or I am, as the case may be) not calling glColor() with all full color channels first. This seems like a bug in the implementation I'm working with (Android, NDK), as the default Color should be (1, 1, 1, 1). Yet calling glColor4f(1, 1, 1, 1) is enough to fix things.
(I have no other calls to glColor in my program. Not sure if there's any other way to update the current color, but the textures render correctly using the default color and drawing them with glEnableClientState(GL_TEXTURE_COORD_ARRAY) / glDrawArrays() )