Login  Register

Re: Object annotation in images (bounding box)

Posted by reisman on Dec 08, 2017; 9:48am
URL: https://forum.jogamp.org/Object-annotation-in-images-bounding-box-tp4038382p4038394.html

Hi,
and thank you for the response. Of course i can insert some code:

These 2 are the main functions to get the rectangle of an object in the image.

/**
 *
 * @param gl The current gl context, needed here to transform the bounding points in image points
 * @param activeCamera The current camera that sees the scene and holds the projection matrix and model view matrix. It
 * provides the method to transform image points.
 * @param objectsInView A List of Objects that in a previous step are detected.
 */
public void annotate(GL2 gl, Scene3DCamera activeCamera, List<ISimulatorObject> objectsInView)
{
        for (ISimulatorObject object : objectsInView) {
                if (object instanceof CarSimulator) {
                        //|| object instanceof Car || object instanceof Person) {
                        // rotate the hitbox points in the pose of the object TODO should already be done.
                        List<Vector3D> boundingPoints = addPose(object.getHitbox().toPolygon().getPoints(), object.getPose());

                        // adding the upper points of a 3D object
                        if (object.getHitbox().is3D()) {
                                double z = object.getHitbox().getLength();
                                int size = boundingPoints.size();
                                for (int i = 0; i < size; i++) {
                                        Vector3D v = boundingPoints.get(i);
                                        boundingPoints.add(new Vector3D(v.getX(), v.getY(), v.getZ() + z));
                                }
                        }
                        // TODO
                        // objectPointsBehindCamera(activeCamera, boundingPoints);
                        //show me the points of an object
                        boundingPoints.forEach(v -> GL3DUtils.drawPoint(gl, v, 0.02, Color.GREEN));
                        List<Vector3D> imagePoints = activeCamera.transformToImagePoint(gl, boundingPoints);

                        // TODO this should be done by a thread pool
                        rectangleObject(activeCamera, object, imagePoints);
                }
        }

        objects.forEach(p -> System.out.println(p)); // print each object and rectancle that are added
        System.out.println("ObjectCount: " + objects.size());
}



/**
 *
 * @param activeCamera The current camera that sees the scene.
 * @param object One of the object that is in the scene. Object can be 2D (4 imagePoints) or 3D (8 imagePoints).
 * @param imagePoints The transformed bounding points of the Object. Only x and y coordinate is relevant.
 */
private void rectangleObject(Scene3DCamera activeCamera, ISimulatorObject object, List<Vector3D> imagePoints)
{
        int width = activeCamera.getViewPortWidth();
        int height = activeCamera.getViewPortHeight();

        int xMin = width - 1;
        int yMin = height - 1;

        int xMax = 0;
        int yMax = 0;

        for (Vector3D ip : imagePoints) {
                int x = (int) ip.getX();
                int y = (int) ip.getY();

                System.out.println("x: " + x + " y:" + y);


                if (x < 0) {
                        x = 0;
                } else if (x > width - 1) {
                        x = width - 1;
                }

                if (y < 0) {
                        y = 0;
                } else if (y > height - 1) {
                        y = height - 1;
                }

                if (xMin > x)
                        xMin = x;
                if (yMin > y)
                        yMin = y;
                if (xMax < x)
                        xMax = x;
                if (yMax < y)
                        yMax = y;
        }
        System.out.println("xMin: " + xMin + " yMin:" + yMin);
        System.out.println("xMax: " + xMax + " yMax:" + yMax);

        Vector2D point = new Vector2D(xMin, yMin);
        Vector2D size = new Vector2D(xMax - xMin, yMax - yMin);
        if (size.getX() > 2 && size.getY() > 2) // prevent to small objects
                addObject(object, point, size);
}


The next 2 method are on of the Scene3DCamera. The first is called befor all calculations will be executed, to obtain the new matrices and the frustum of the camera.

/**
 *
 * @param gl The current gl render context. Needed to get all 3 matrices (projection, model view and viewPort).
 * these Matrices are needed to determine the frustum of the current view. Also this used to transform 3D world
 * points to image points.
 */
public void update(GL2 gl)
{
        gl.glGetFloatv(GL2.GL_PROJECTION_MATRIX, projection, 0);
        gl.glGetFloatv(GL2.GL_MODELVIEW_MATRIX, modelView, 0);
        gl.glGetIntegerv(GL2.GL_VIEWPORT, viewport, 0);

        frustum.updateByPMV(Mat4Util.matMulf(projection, modelView), 0);
        frustumReady = true;
}


And the last function which is calld in the annotate method to trasnform the object bounding points to an image point .

/**
 *
 * @param gl The current gl context. Needed here to create an GLU object, which provides the Project function.
 * This function performs the calculation to map a 3D world point in an 2D image point  
 * @param worldPoints A list of points which belongs to an object.
 * @return List of image points.
 */
public List<Vector3D> transformToImagePoint(GL2 gl, List<Vector3D> worldPoints)
{
        update(gl); // not needed because already done, when it performs this method.  

        GLU glu = GLU.createGLU(gl);
        int height = viewport[3];

        List<Vector3D> imagePoints = new ArrayList<>();

        worldPoints.forEach(p -> {
                float[] winPos = new float[3];
                glu.gluProject((float) p.getX(), (float) p.getY(), (float) p.getZ(), modelView, 0, projection, 0, viewport, 0, winPos, 0);
                imagePoints.add(new Vector3D(winPos[0], height - winPos[1], winPos[2]));
        });
        return imagePoints;
}

My academic advisor has pointed out , that this points of an object, which are causing a wrong  resulting rectangle are laying behind the camera object...

Maybe when i remove wrong points, and with the rest i can determin the rectangle ?! Have to try , or do you now an better approche ?

best wishes
reisman