Texture renders incorrectly (OpenGL) - java

I've been trying to render an 8x8 texture. I've used code from 2 tutorials, but the texture doesn't render correctly. For now I have this initialization code:
int shaderProgram,fragmentShader,vertexShader,texture,elementBuffer,vertexBuffer, vertexArray;
public Texture2D(String texturePath_, String vertexShader_,String fragmentShader_)
{
vertexArray=GL30.glGenVertexArrays();
GL30.glBindVertexArray(vertexArray);
String[] vertexshader=Utilities.loadShaderFile(vertexShader_,getClass());
String[] fragmentshader=Utilities.loadShaderFile(fragmentShader_,getClass());
if(vertexshader==null)
throw new NullPointerException("The vertex shader is null");
if(fragmentshader==null)
throw new NullPointerException("The fragment shader is null");
vertexShader=GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
GL20.glShaderSource(vertexShader,vertexshader);
GL20.glCompileShader(vertexShader);
Utilities.showShaderCompileLog(vertexShader);
fragmentShader=GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
GL20.glShaderSource(fragmentShader,fragmentshader);
GL20.glCompileShader(fragmentShader);
Utilities.showShaderCompileLog(fragmentShader);
shaderProgram= GL20.glCreateProgram();
GL20.glAttachShader(shaderProgram,fragmentShader);
GL20.glAttachShader(shaderProgram,vertexShader);
GL30.glBindFragDataLocation(shaderProgram,0,"fragcolor");
GL20.glLinkProgram(shaderProgram);
GL20.glUseProgram(shaderProgram);
texture= GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D,texture);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D,GL11.GL_TEXTURE_WRAP_S, GL13.GL_CLAMP_TO_BORDER);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D,GL11.GL_TEXTURE_WRAP_T,GL13.GL_CLAMP_TO_BORDER);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D,GL11.GL_TEXTURE_MIN_FILTER,GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D,GL11.GL_TEXTURE_MAG_FILTER,GL11.GL_LINEAR);
ByteBuffer image;
FloatBuffer verteces;
IntBuffer imagewidth,imageheight, positions,imagechannels;
try(MemoryStack memoryStack=MemoryStack.stackPush())
{
imageheight=memoryStack.mallocInt(1);
imagewidth=memoryStack.mallocInt(1);
positions=memoryStack.mallocInt(6);
imagechannels=memoryStack.mallocInt(1);
image= STBImage.stbi_load(texturePath_,imagewidth,imageheight,imagechannels,0);
if(image==null) throw new NullPointerException("Failed to load image");
verteces=memoryStack.mallocFloat(28);
}
positions.put(0).put(1).put(2).put(2).put(3).put(0).flip();
int width=imagewidth.get();
int height=imageheight.get();
GL11.glTexImage2D(GL11.GL_TEXTURE_2D,0,GL11.GL_RGBA,width,height,0,GL11.GL_RGBA,GL11.GL_UNSIGNED_BYTE,image);
elementBuffer=GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER,elementBuffer);
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER,positions,GL15.GL_STATIC_DRAW);
float x1=0f, x2=1f;
float y1=1f,y2=-1f;
verteces.put(x1).put(y1).put(1).put(1).put(1).put(0).put(0);
verteces.put(x1).put(y2).put(1).put(1).put(1).put(1).put(0);
verteces.put(x2).put(y2).put(1).put(1).put(1).put(1).put(1);
verteces.put(x2).put(y1).put(1).put(1).put(1).put(0).put(1).flip();
vertexBuffer=GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER,vertexBuffer);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER,verteces,GL15.GL_STATIC_DRAW);
int uniform=GL20.glGetUniformLocation(shaderProgram,"texture_image");
GL20.glUniform1i(uniform,0);
int position=GL20.glGetAttribLocation(shaderProgram,"position");
GL20.glEnableVertexAttribArray(position);
GL20.glVertexAttribPointer(position,2,GL11.GL_FLOAT,false,0,0);
int color=GL20.glGetAttribLocation(shaderProgram,"color");
GL20.glEnableVertexAttribArray(color);
GL20.glVertexAttribPointer(color,3,GL11.GL_FLOAT,false,7*Float.BYTES, 2 * Float.BYTES);
int textureST=GL20.glGetAttribLocation(shaderProgram,"textureCoord");
GL20.glEnableVertexAttribArray(textureST);
GL20.glVertexAttribPointer(textureST,3,GL11.GL_FLOAT,false,7*Float.BYTES, 5 * Float.BYTES);
Utilities.showErrors(1);
}
The result is:
But I'd like the texture to occupy all area. The shaders compile fine, and there are no GL errors.
If I change values to the ones from the tutorial:
verteces.put(-1f).put(1f).put(1).put(1).put(1).put(0).put(0);
verteces.put(1f).put(1f).put(1).put(1).put(1).put(1).put(0);
verteces.put(1f).put(-1f).put(1).put(1).put(1).put(1).put(1);
verteces.put(-1f).put(-1f).put(1).put(1).put(1).put(0).put(1).flip();
I get:
The tutorials: https://open.gl/textures and https://github.com/SilverTiger/lwjgl3-tutorial/wiki/Textures
I'm using profile 3.0 with shaders version 300 ES. The texture's format is PNG.

The vertex attribute layout:
GL20.glVertexAttribPointer(position,2,GL11.GL_FLOAT,false,0,0);
GL20.glVertexAttribPointer(color,3,GL11.GL_FLOAT,false,7*Float.BYTES, 2 * Float.BYTES);
GL20.glVertexAttribPointer(textureST,3,GL11.GL_FLOAT,false,7*Float.BYTES, 5 * Float.BYTES);
doesn't look correct. There are multiple problems with it:
The texture coordinates try to read 3 floats from the array. In combination with the stride, your last vertex will read outside the VBO. Most probably texture coordinates should only read 2 floats.
The total number of floats used (2+3+3=8) does not fit to the data where only 7 floats per vertex are given. This is solved when texture coordinates read only two floats.
The stride of the positions look wrong. 0 means that all positions are tightly packed. Basically, the positions use the first 8 floats in the VBO. If you look at them: {-1, 1, 1, 1, 1, 0, 0, 1}, then this is exactly the geometry you see. It was just luck that it worked in first place. Solution: Change position layout to:
GL20.glVertexAttribPointer(position,2,GL11.GL_FLOAT,false,7*Float.BYTES,0);

Related

How do I draw a rectangular polygon without a triangular cutout?

I am creating a rectangular polygon that represents the box bounding the player sprite in a simple 2D game. This is the implementation I use:
float[] vertices = new float[] {player.getSprite().getX(), player.getSprite().getY(),
player.getSprite().getX() + player.getSprite().getWidth(),
player.getSprite().getY(), player.getSprite().getX(),
player.getSprite().getY() + player.getSprite().getHeight(),
player.getSprite().getX() + player.getSprite().getWidth(),
player.getSprite().getY() + player.getSprite().getHeight()};
Polygon rPoly = new Polygon(vertices);
polyBatch.draw(
new PolygonRegion(new TextureRegion(healthImage), rPoly.getTransformedVertices(),
new EarClippingTriangulator().computeTriangles(vertices).toArray()),
player.getSprite().getScaleX(), player.getSprite().getScaleY());
Where the "Sprite" is an actual LibGDX sprite object. When I try to use this implementation I get this as a result:
How do I get this polygon to be drawn without that triangular cut in it?
I will start this answer with a disclaimer: I have never used LibGDX before. Nonetheless I can see a potential problem with your code.
Let's number the corners of your rectangle as follows:
1 2
3 4
Your array of vertex coordinates includes these corners in the order 1, 2, 3, 4.
You are using a polygon object to represent this rectangle. Polygon objects will typically expect the vertex coordinates that they are given to go around the polygon in one direction or the other. For example, if you had a polygon with 10 points, how would the Polygon class know in which order to connect the points? Of course, order 1, 2, 3, 4 is not going around your rectangle in either direction.
Try swapping the order of the last two pairs of coordinates, so that your array of vertices includes the corners in the order 1, 2, 4, 3.
Bonus hint for readability: try to format your array of vertices so that it contains one pair of coordinates per line, perhaps something like the following:
Sprite sprite = player.getSprite();
float[] vertices = new float[] {
sprite.getX(), sprite.getY(),
sprite.getX() + sprite.getWidth(), sprite.getY(),
sprite.getX() + sprite.getWidth(), sprite.getY() + sprite.getHeight(),
sprite.getX(), sprite.getY() + sprite.getHeight()
};
To reduce the line length, I've created a local variable for the value of player.getSprite(). I've guessed the name of the class as Sprite: feel free to adjust this if necessary. You could potentially create further local variables for the values of sprite.getX(), sprite.getY() and so on.

Efficient Way to Draw Lots of Triangles (OpenGL)

I am a little bit new to OpenGL. I am trying to draw 3D dynamic trail for aircraft using Java OpenGL and WorldWind Java I can draw it by using glDrawArrays. Since the trail of the aircraft increases in every frame(25fps) I put new vertice values to verticeBuffer. I also use rightFloatBuffer and leftFloatBuffer to draw GL_LINE_STRIP to the both sides of the trail as you may see in the attached firstpicture. Since the trail gets longer and longer as the aircraft flies I thought that I need to create a large FloatBuffer for the triangles (verticeBuffer) and 2 large FloatBuffers for the left and right lines.
My first question: What is the most efficient way to draw to many triangles? Based on my code I think after 5 hours of flight the FloatBuffers will be full. If I try to update values with for loop in each frame and if I have, say 50-75 aircraft at the same time, this will reduce the performance. And because of that, I update one triangle at each frame.
Second question: I want to draw a trail like in the second picture. As you see trail gets more transparent as it gets closer to aircraft. And when the aircraft turns color the bottom side of the trail seems different. How can I do it?
Third question: I use gl.DepthMask(false) and draw line_strip and gl.DepthMask(true) to draw smooth lines without a gap between the lines. But this time aircraft trail which is added to the scene first always seems on the top no matter if it is under another trail. What can I do to overcome this? Or what can I do to draw smooth lines without gaps considering the amount of the vertices?
My code to draw the trail is below:
private final FloatBuffer verticeBuffer = GLBuffers.newDirectFloatBuffer(3000000);
private final FloatBuffer rightFloatBuffer = GLBuffers.newDirectFloatBuffer(1500000);
private final FloatBuffer leftFloatBuffer = GLBuffers.newDirectFloatBuffer(1500000);
protected void drawTrail() {
gl.glPushAttrib(GL2.GL_CURRENT_BIT | GL2.GL_COLOR_BUFFER_BIT | GL2.GL_LINE_BIT | GL2.GL_ENABLE_BIT
| GL2.GL_DEPTH_BUFFER_BIT);
try {
gl.glEnable(GL.GL_BLEND);
gl.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
doDrawTrail(dc);
gl.glDisableClientState(GL2.GL_VERTEX_ARRAY);
gl.glDisable(GL.GL_BLEND);
} finally {
gl.glPopAttrib();
}
}
protected void doDrawTrail() {
updateTrailVertices();
float[] colors = new float[]{trailColor.getRed() / 255.f, trailColor.getGreen() / 255.f, trailColor.getBlue() / 255.f};
gl.glColor4f(colors[0], colors[1], colors[2], 0.6f);
gl.glEnable(GL2.GL_LINE_SMOOTH);
gl.glHint(GL2.GL_LINE_SMOOTH_HINT, GL2.GL_NICEST);
gl.glVertexPointer(3, GL.GL_FLOAT, 0, verticeBuffer.rewind());
gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, verticeBuffer.limit() / 3);
gl.glColor3f(colors[0], colors[1], colors[2]);
gl.glLineWidth(3f);
//To draw smooth lines
gl.glDepthMask(false);
gl.glVertexPointer(3, GL.GL_FLOAT, 0, rightFloatBuffer.rewind());
gl.glDrawArrays(GL.GL_LINE_STRIP, 0, rightFloatBuffer.limit() / 3);
gl.glVertexPointer(3, GL.GL_FLOAT, 0, leftFloatBuffer.rewind());
gl.glDrawArrays(GL.GL_LINE_STRIP, 0, leftFloatBuffer.limit() / 3);
gl.glDepthMask(true);
}
protected void updateTrailVertices() {
// In each frame when the aircraft position changes this function updates the last vertices
if (positionChange) {
positionChange = false;
//I need to set the position and the limit of the buffers to draw only updated parts
verticeBuffer.position(lastIndex * 2);
rightFloatBuffer.position(lastIndex);
leftFloatBuffer.position(lastIndex);
verticeBuffer.limit((lastIndex * 2) + 6);
rightFloatBuffer.limit(lastIndex + 3);
leftFloatBuffer.limit(lastIndex + 3);
List<Vec4> pointEdges = computeVec4(this.currentPosition, this.currentHeading, this.currentRoll, this.span);
verticeBuffer.put((float) pointEdges.get(0).x).put((float) pointEdges.get(0).y).put((float) pointEdges.get(0).z);
verticeBuffer.put((float) pointEdges.get(1).x).put((float) pointEdges.get(1).y).put((float) pointEdges.get(1).z);
rightFloatBuffer.put((float) pointEdges.get(0).x).put((float) pointEdges.get(0).y).put((float) pointEdges.get(0).z);
leftFloatBuffer.put((float) pointEdges.get(1).x).put((float) pointEdges.get(1).y).put((float) pointEdges.get(1).z);
lastIndex = rightFloatBuffer.position();
}
}
If you can use geometry shaders, the most efficient way to display the flight track is to have one vertexbuffer and render it as a line strip. The vertexbuffer contains the earlier locations and a normal vector (plane up direction). With these two values the the geometry shader you can transform it into quads. These quads should contain texture coordinates, which can be used in the fragment shader to display the borders.
You need only one draw call and reduce the data stored on the gpu to the absolute minimum.
The fading of the flight track can be done by using a uniform with the plane coordinates. One of your shades can calculate the distance to the plane and with that a alpha value for the pixel.

Wrong Display of a simple Cube in Android with OpenGL ES [duplicate]

I'm working on a 2d engine. It already works quite good, but I keep getting pixel-errors.
For example, my window is 960x540 pixels, I draw a line from (0, 0) to (959, 0). I would expect that every pixel on scan-line 0 will be set to a color, but no: the right-most pixel is not drawn. Same problem when I draw vertically to pixel 539. I really need to draw to (960, 0) or (0, 540) to have it drawn.
As I was born in the pixel-era, I am convinced that this is not the correct result. When my screen was 320x200 pixels big, I could draw from 0 to 319 and from 0 to 199, and my screen would be full. Now I end up with a screen with a right/bottom pixel not drawn.
This can be due to different things:
where I expect the opengl line primitive is drawn from a pixel to a pixel inclusive, that last pixel just is actually exclusive? Is that it?
my projection matrix is incorrect?
I am under a false assumption that when I have a backbuffer of 960x540, that is actually has one pixel more?
Something else?
Can someone please help me? I have been looking into this problem for a long time now, and every time when I thought it was ok, I saw after a while that it actually wasn't.
Here is some of my code, I tried to strip it down as much as possible. When I call my line-function, every coordinate is added with 0.375, 0.375 to make it correct on both ATI and nvidia adapters.
int width = resX();
int height = resY();
for (int i = 0; i < height; i += 2)
rm->line(0, i, width - 1, i, vec4f(1, 0, 0, 1));
for (int i = 1; i < height; i += 2)
rm->line(0, i, width - 1, i, vec4f(0, 1, 0, 1));
// when I do this, one pixel to the right remains undrawn
void rendermachine::line(int x1, int y1, int x2, int y2, const vec4f &color)
{
... some code to decide what std::vector the coordinates should be pushed into
// m_z is a z-coordinate, I use z-buffering to preserve correct drawing orders
// vec2f(0, 0) is a texture-coordinate, the line is drawn without texturing
target->push_back(vertex(vec3f((float)x1 + 0.375f, (float)y1 + 0.375f, m_z), color, vec2f(0, 0)));
target->push_back(vertex(vec3f((float)x2 + 0.375f, (float)y2 + 0.375f, m_z), color, vec2f(0, 0)));
}
void rendermachine::update(...)
{
... render target object is queried for width and height, in my test it is just the back buffer so the window client resolution is returned
mat4f mP;
mP.setOrthographic(0, (float)width, (float)height, 0, 0, 8000000);
... all vertices are copied to video memory
... drawing
if (there are lines to draw)
glDrawArrays(GL_LINES, (int)offset, (int)lines.size());
...
}
// And the (very simple) shader to draw these lines
// Vertex shader
#version 120
attribute vec3 aVertexPosition;
attribute vec4 aVertexColor;
uniform mat4 mP;
varying vec4 vColor;
void main(void) {
gl_Position = mP * vec4(aVertexPosition, 1.0);
vColor = aVertexColor;
}
// Fragment shader
#version 120
#ifdef GL_ES
precision highp float;
#endif
varying vec4 vColor;
void main(void) {
gl_FragColor = vColor.rgb;
}
In OpenGL, lines are rasterized using the "Diamond Exit" rule. This is almost the same as saying that the end coordinate is exclusive, but not quite...
This is what the OpenGL spec has to say:
http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node47.html
Also have a look at the OpenGL FAQ, http://www.opengl.org/archives/resources/faq/technical/rasterization.htm, item "14.090 How do I obtain exact pixelization of lines?". It says "The OpenGL specification allows for a wide range of line rendering hardware, so exact pixelization may not be possible at all."
Many will argue that you should not use lines in OpenGL at all. Their behaviour is based on how ancient SGI hardware worked, not on what makes sense. (And lines with widths >1 are nearly impossible to use in a way that looks good!)
Note that OpenGL coordinate space has no notion of integers, everything is a float and the "centre" of an OpenGL pixel is really at the 0.5,0.5 instead of its top-left corner. Therefore, if you want a 1px wide line from 0,0 to 10,10 inclusive, you really had to draw a line from 0.5,0.5 to 10.5,10.5.
This will be especially apparent if you turn on anti-aliasing, if you have anti-aliasing and you try to draw from 50,0 to 50,100 you may see a blurry 2px wide line because the line fell in-between two pixels.

Difference between glNormal3f and glNormalPointer

i'm getting these strange two results when drawing with immediate mode and vertex arrays. In immediate mode i'm passing the normals by glNormal3f. My shader takes the normal and computes something like a shadow, but nothing seriously.
Immediate Mode:
glBegin(GL_TRIANGLES);
for (Triangle tri : this.triangles) {
Vec3d normal = Vec3d.vectorProduct(
Vec3d.sub(tri.getB(), tri.getA()),
Vec3d.sub(tri.getC(), tri.getA())); //calculating normalvector
glNormal3d(normal.x, normal.y, normal.z);
glColor3d(1.0, 1.0, 1.0);
glVertex3d(tri.getA().x, tri.getA().y, tri.getA().z);
glVertex3d(tri.getB().x, tri.getB().y, tri.getB().z);
glVertex3d(tri.getC().x, tri.getC().y, tri.getC().z);
}
glEnd();
Result:
In the VAO variant, i'm storing the normals in a separate buffer, but calculated the same way:
for(Triangle tri : triangles) {
Vec3d normal = Vec3d.vectorProduct(
Vec3d.sub(tri.getB(), tri.getA()),
Vec3d.sub(tri.getC(), tri.getA()));
normals.put((float) normal.x);
normals.put((float) normal.y);
normals.put((float) normal.z);
}
normals.flip();
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(4, normals);
glVertexPointer(3,3*4, vertices);
glDrawArrays(GL_TRIANGLES, 0, (vertices.capacity() / 3));
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
Result 2:
Obviously the normals get somehow mismatched but i can't find my mistake.
And the final question: What is the difference between glNormal3f and glNormalPointer considering the values passed to the shader?
The stride of your normal array is suspect. Why are you passing 4 for the stride to glNormalPointer (...)?
You are telling GL that there are 4-bytes (1 float) worth of space between each of your normals. However, normals is built in your code with 12-bytes between each successive normal. Incidentally, this is what you would call tightly packed and therefore passing 0 for the stride implies the same thing (4-bytes per-component x 3-components).
Your vertex array and normal array should actually have the same stride. 4*3 or simply 0.

Using warpPerspective() on a sequence of points given by HoughCircles(), OpenCV

I'm trying to detect the positions of billiards balls on a table from an image taken at a perspective angle. I'm using the getPerspectiveTransform() method to find the transformation matrix and I want to apply that to only the circles I detect using HoughCircles. I'm trying to go from a rather large trapezoidal shape to a smaller rectangular shape. I don't want to do the transformation on the image first and then find the HoughCircles because the image gets too warped for houghcircles to provide useful results.
Here's my code:
CvMat mmat = cvCreateMat(3,3,CV_32FC1);
double srcX1 = 462;
double srcX2 = 978;
double srcX3 = 1440;
double srcX4 = 0;
double srcY = 241;
double srcHeight = 772;
double dstX = 56.8;
double dstY = 33.5;
double dstWidth = 262.4;
double dstHeight = 447.3;
CvSeq seq = cvHoughCircles(newGray, circles, CV_HOUGH_GRADIENT, 2.1d, (double)newGray.height()/40, 85d, 65d, 5, 50);
JavaCV.getPerspectiveTransform(new double[]{srcX1, srcY, srcX2,srcY, srcX3, srcHeight, srcX4, srcHeight},
new double[]{dstX, dstY, dstWidth, dstY, dstWidth, dstHeight, dstX, dstHeight}, mmat);
cvWarpPerspective(seq, seq, mmat);
for(int j=0; j<seq.total(); j++){
CvPoint3D32f point = new CvPoint3D32f(cvGetSeqElem(seq, j));
float xyr[] = {point.x(),point.y(),point.z()};
CvPoint center = new CvPoint(Math.round(xyr[0]), Math.round(xyr[1]));
int radius = Math.round(xyr[2]);
cvCircle(gray, center, 3, CvScalar.GREEN, -1, 8, 0);
cvCircle(gray, center, radius, CvScalar.BLUE, 3, 8, 0);
}
The problem is I get this error on the warpPerspective() method:
error: (-215) seq->total > 0 && CV_ELEM_SIZE(seq->flags) == seq->elem_size in function cv::Mat cv::cvarrToMat(const CvArr*, bool, bool, int)
Also I guess it's worth mentioning that I'm using JavaCV, in case the method calls look a bit different than what you're used to. Thanks for any help.
Answer:
the problem with what you want to do (besides the obvious, opencv wont let you) is that the radius cant really be warped correctly. AFAIK the xy coordinates are pretty easy to calculate x'=((m00x+m01y+m02)/(m20x+m21y+m22)) y'=((m10x+m11y+m12)/(m20x+m21y_m22)) when m is the transformation matrix. the radius you can hack by transforming all the points of the original circle and then find the max distance between x'y' and those points (atleast if the radius in the warped image is expected to cover all those points)
btw, mIJx = m(i,j)*x (just to clarify)
End Answer.
Everything i write is according to the c++ version, i've never used JavaCV but from what i could see its just a wrapper that calls the native c++ lib.
CvSeq is a sequance data structure that behaves like a linked list.
the assert your application crushes at is
CV_Assert(seq->total > 0 && CV_ELEM_SIZE(seq->flags) == seq->elem_size);
which means that either your seq instance is empty (total is the number of elements in the sequence) or somehow the inner seq flags are corrupted.
I'd recommend that you'd check the total member of your CvSeq, and the cvHoughCircles call.
all of this occurs before the actual implementation of cvWarpPerspective (its the first line in the implementation, that only converts your CvSeq to cv::Mat).. so its not the warping but what you're doing before that.
anyway, to understand whats wrong with cvHoughCircles we'll need more info about the creation of newGray and circles.
here is an example i've found on the javaCV page (Link)
IplImage gray = cvCreateImage( cvSize( img.width, img.height ), IPL_DEPTH_8U, 1 );
cvCvtColor( img, gray, CV_RGB2GRAY );
// smooth it, otherwise a lot of false circles may be detected
cvSmooth(gray,gray,CV_GAUSSIAN,9,9,2,2);
CvMemStorage circles = CvMemStorage.create();
CvSeq seq = cvHoughCircles(gray, circles.getPointer(), CV_HOUGH_GRADIENT,
2, img.height/4, 100, 100, 0, 0);
for(int i=0; i<seq.total; i++){
float xyr[] = cvGetSeqElem(seq,i).getFloatArray(0, 3);
CvPoint center = new CvPoint(Math.round(xyr[0]), Math.round(xyr[1]));
int radius = Math.round(xyr[2]);
cvCircle(img, center.byValue(), 3, CvScalar.GREEN, -1, 8, 0);
cvCircle(img, center.byValue(), radius, CvScalar.BLUE, 3, 8, 0);
}
from what i've seen in the implementation of cvHoughCircles, the answer is saved in the circles buff and at the end they create from it the CvSeq to return, so if you've allocated the circles buff wrong, it wont work.
EDIT:
as you can see, the CvSeq instance in case of the return from cvHoughCircles is a list of point-values, that is probably why the assertion failed. you cannot convert this CvSeq into a cv::Mat.. because its just not a cv::Mat. to get only the circles returned from cvHoughCircles in an cv::Mat instance, you'll need to create a new cv::Mat instance and than draw onto it all the circles in the CvSeq - as seen in the provided example above.
than the warping will work (you'll have a cv::Mat instance, and that is what the function expect - a cv::Mat as the only element in the CvSeq)
END EDIT
here is the c++ reference for CvSeq
and if you want to fiddle with the source code than
cvarrToMat is in matrix.cpp
CV_ELEM_SIZE is in types_c.h
cvWarpPerspective is in imgwarp.cpp
cvHoughCircles is in hough.cpp
I hope that will help.
BTW, your next error will probably be:
cv::warpPerspective in the C++ OpencCv asserts that dst.data != src.data
thus
cvWarpPerspective(seq, seq, mmat);
wont work cause your source mat and destination mat referencing the same data.
Not all the functions in OpenCV (and image processing in general) work in-situ (because there is no in-situ algorithm or because its slower then the other version eg. transpose of an n*n mat will work in-situ, but n*m where n!=m will be harder to do in-situ and might be slower)
you cant assume the using the src matrix as the dst will work.

Categories