Как получить границы объекта, используя его возможности?

Я пытаюсь сделать приложение для Android, которое обнаруживает известные объекты. Я использую boofCV для достижения этой цели. Я сохранил изображение объекта в ресурсах приложения, во время выполнения я определяю функции с помощью Fast Hessian и описываю его с помощью SURF. Затем по каналу камеры, когда я получаю кадр, я определяю функции в кадре с помощью Fast Hessian и описываю его с помощью SURF. Когда у меня есть возможности как исходного объекта, так и текущего кадра, я связываю их и получаю совпадения. Теперь я могу рисовать спички. Но то, что я хочу сделать, это использовать совпадения, которые я хочу, чтобы получить границы обнаруженного объекта. Чтобы сделать это, я начал следовать этому примеру. Хотя это пример сшивания изображений, но эта концепция может применяться для обнаружения границ известного объекта.

Я успешно реализовал этот пример. Проблема в том, что линии действительно рисуются, но линии - это просто прямые линии, в некоторых кадрах рисуется только одна прямая, прямоугольник не рисуется.

Вот мой код:

public class HomographyProcessing2<Desc extends TupleDesc> extends VideoRenderProcessing<ImageFloat32> {


DetectDescribePoint<ImageFloat32,Desc> detDesc;
AssociateDescription<Desc> associate;

FastQueue<Desc> listSrc;
FastQueue<Desc> listDst;
FastQueue<Point2D_F64> locationSrc = new FastQueue<Point2D_F64>(Point2D_F64.class,true);
FastQueue<Point2D_F64> locationDst = new FastQueue<Point2D_F64>(Point2D_F64.class,true);

// output image which is displayed by the GUI
private Bitmap outputGUI;
// storage used during image convert
private byte[] storage;
// output image which is modified by processing thread
private Bitmap output;

List<Point2D_F64> pointsSrc = new ArrayList<Point2D_F64>();
List<Point2D_F64> pointsDst = new ArrayList<Point2D_F64>();

private ImageFloat32 object;
private ImageFloat32 frame;


Paint paint = new Paint();
ModelManager<Homography2D_F64> manager = new ModelManagerHomography2D_F64();
GenerateHomographyLinear modelFitter = new GenerateHomographyLinear(true);
DistanceHomographySq distance = new DistanceHomographySq();
ModelMatcher<Homography2D_F64,AssociatedPair> modelMatcher = new Ransac<Homography2D_F64,AssociatedPair>(123,manager,modelFitter,distance,60,9);

Homography2D_F64 homography2D_f64 = null;

public HomographyProcessing2(Context context, int width, int height) {
    super(ImageType.single(ImageFloat32.class));

    Log.e("LEARN", String.valueOf(modelFitter.getMinimumPoints()));
    detDesc = CreateDetectorDescriptor.create(CreateDetectorDescriptor.DETECT_FH, CreateDetectorDescriptor.DESC_SURF, ImageFloat32.class);
    listSrc = UtilFeature.createQueue(detDesc, 100);
    listDst = UtilFeature.createQueue(detDesc,100);
    ScoreAssociation score = FactoryAssociation.scoreEuclidean(detDesc.getDescriptionType(),true);
    associate = FactoryAssociation.greedy(score,Double.MAX_VALUE,true);

    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.camera_image);
    object = new ImageFloat32(bitmap.getWidth(),bitmap.getHeight());
    byte[] storage = null;
    ConvertBitmap.declareStorage(bitmap, storage);
    ConvertBitmap.bitmapToGray(bitmap,object,storage);

    detDesc.detect(object);
    describeImage(listSrc, locationSrc);
    associate.setSource(listSrc);

    output = Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888 );
    outputGUI = Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888 );
    paint.setColor(Color.BLUE);
    paint.setTextSize(20);

}


    /**
 * Using abstracted code, find a transform which minimizes the difference between corresponding features
 * in both images.  This code is completely model independent and is the core algorithms.
 */
public static<T extends ImageSingleBand, FD extends TupleDesc> Homography2D_F64
computeTransform( T imageA , T imageB ,
                  DetectDescribePoint<T,FD> detDesc ,
                  AssociateDescription<FD> associate ,
                  ModelMatcher<Homography2D_F64,AssociatedPair> modelMatcher )
{
    // get the length of the description
    List<Point2D_F64> pointsA = new ArrayList<Point2D_F64>();
    FastQueue<FD> descA = UtilFeature.createQueue(detDesc, 100);
    List<Point2D_F64> pointsB = new ArrayList<Point2D_F64>();
    FastQueue<FD> descB = UtilFeature.createQueue(detDesc,100);



    // extract feature locations and descriptions from each image
    describeImage(imageA, detDesc, pointsA, descA);
    describeImage(imageB, detDesc, pointsB, descB);

    // Associate features between the two images
    associate.setSource(descA);
    associate.setDestination(descB);
    associate.associate();

    // create a list of AssociatedPairs that tell the model matcher how a feature moved
    FastQueue<AssociatedIndex> matches = associate.getMatches();
    List<AssociatedPair> pairs = new ArrayList<AssociatedPair>();

    for( int i = 0; i < matches.size(); i++ ) {
        AssociatedIndex match = matches.get(i);

        Point2D_F64 a = pointsA.get(match.src);
        Point2D_F64 b = pointsB.get(match.dst);

        pairs.add( new AssociatedPair(a,b,false));
    }

    // find the best fit model to describe the change between these images
    if( !modelMatcher.process(pairs) )
        throw new RuntimeException("Model Matcher failed!");

    // return the found image transform
    return modelMatcher.getModelParameters().copy();
}

/**
 * Detects features inside the two images and computes descriptions at those points.
 */
private static <T extends ImageSingleBand, FD extends TupleDesc>
void describeImage(T image,
                   DetectDescribePoint<T,FD> detDesc,
                   List<Point2D_F64> points,
                   FastQueue<FD> listDescs) {
    detDesc.detect(image);

    listDescs.reset();
    for( int i = 0; i < detDesc.getNumberOfFeatures(); i++ ) {
        points.add( detDesc.getLocation(i).copy() );
        listDescs.grow().setTo(detDesc.getDescription(i));
    }
}


private static Point2D_I32 renderPoint( int x0 , int y0 , Homography2D_F64 fromBtoWork )
{
    Point2D_F64 result = new Point2D_F64();
    HomographyPointOps_F64.transform(fromBtoWork, new Point2D_F64(x0, y0), result);
    return new Point2D_I32((int)result.x,(int)result.y);
}

@Override
protected void process(ImageFloat32 imageFloat32) {
    detDesc.detect(imageFloat32);
    describeImage(listDst,locationDst);
    associate.setDestination(listDst);
    associate.associate();
    synchronized (new Object()) {
        //ConvertBitmap.declareStorage(gray ,storage);
        ConvertBitmap.grayToBitmap(imageFloat32, output, storage);
        outputGUI = output;
    }
    synchronized (new Object())
    {
        pointsSrc.clear();
        pointsDst.clear();

        FastQueue<AssociatedIndex> matches = associate.getMatches();
        List<AssociatedPair> pairs = new ArrayList<AssociatedPair>();

        for( int i = 0; i < matches.size(); i++ ) {
            AssociatedIndex match = matches.get(i);

            Point2D_F64 a = locationSrc.get(match.src);
            Point2D_F64 b = locationDst.get(match.dst);

            pairs.add( new AssociatedPair(a,b,false));
            pointsDst.add(locationDst.get(match.dst));
        }



        if(pairs.size() >= 4) {
            // find the best fit model to describe the change between these images
            if (!modelMatcher.process(pairs))
                throw new RuntimeException("Model Matcher failed!");

            // return the found image transform
            homography2D_f64 = modelMatcher.getModelParameters().copy();
        }
        }


}

@Override
protected void render(Canvas canvas, double v) {
    synchronized (new Object())
    {
        canvas.drawBitmap(outputGUI, 0, 0, null);
        frame = ConvertBitmap.bitmapToGray(outputGUI,frame,storage);
        if(homography2D_f64 != null)
        {
            // Convert into a BoofCV color format
            MultiSpectral<ImageFloat32> colorA = new MultiSpectral<ImageFloat32>(ImageFloat32.class,3);
            MultiSpectral<ImageFloat32> colorB = new MultiSpectral<ImageFloat32>(ImageFloat32.class,3);
            colorB.setBands(new ImageFloat32[]{frame,frame,frame});
            colorA.setBands(new ImageFloat32[]{object,object,object});
            MultiSpectral<ImageFloat32> work = new MultiSpectral<ImageFloat32>(ImageFloat32.class,outputWidth,outputHeight,3);

            Homography2D_F64 fromAToWork = new Homography2D_F64(0.5,0,colorA.width/4,0,scale,colorA.height/4,0,0,1);
            Homography2D_F64 fromWorkToA = fromAToWork.invert(null);

            // Used to render the results onto an image
            PixelTransformHomography_F32 model = new PixelTransformHomography_F32();
            ImageDistort<MultiSpectral<ImageFloat32>,MultiSpectral<ImageFloat32>> distort =
                    DistortSupport.createDistortMS(ImageFloat32.class, model, new ImplBilinearPixel_F32(), false, null);


            // Render first image
            model.set(fromWorkToA);
            distort.apply(colorA,work);

            // Render second image
            Homography2D_F64 fromWorkToB = fromWorkToA.concat(homography2D_f64,null);
            model.set(fromWorkToB);
            distort.apply(colorB,work);

            Homography2D_F64 fromBtoWork = fromWorkToB.invert(null);
            Point2D_I32 corners[] = new Point2D_I32[4];
            corners[0] = renderPoint (0,0,fromBtoWork);
            corners[1] = renderPoint(object.width,0,fromBtoWork);
            corners[2] = renderPoint(object.width,object.height,fromBtoWork);
            corners[3] = renderPoint(0,object.height,fromBtoWork);

            paint.setColor(Color.GREEN);
            paint.setStrokeWidth(5);
            canvas.drawLine(corners[0].x,corners[0].y,corners[1].x,corners[1].y,paint);
            canvas.drawLine(corners[1].x,corners[1].y,corners[2].x,corners[2].y,paint);
            canvas.drawLine(corners[2].x,corners[2].y,corners[3].x,corners[3].y,paint);
            canvas.drawLine(corners[3].x,corners[3].y,corners[0].x,corners[0].y,paint);
        }
        else {

            for (int i = 0; i < pointsDst.size(); i++) {
                Point2D_F64 point2D_f64 = pointsDst.get(i);
                canvas.drawCircle(Float.parseFloat(String.valueOf(point2D_f64.getX())), Float.parseFloat(String.valueOf(point2D_f64.getY())), 2, paint);
            }
        }
    }
}


private void describeImage(FastQueue<Desc> listDesc, FastQueue<Point2D_F64> listLoc) {
    listDesc.reset();
    listLoc.reset();
    int N = detDesc.getNumberOfFeatures();
    for( int i = 0; i < N; i++ ) {
        listLoc.grow().set(detDesc.getLocation(i));
        listDesc.grow().setTo(detDesc.getDescription(i));
    }
}

}

Я не совсем понимаю, как работает гомография, и я думаю, что это может быть проблемой.

Пожалуйста, помогите мне исправить это или предоставьте какой-либо лучший способ определения границ объекта на основе его особенностей.

Спасибо!

1 ответ

Решение

Попробуйте этот пример, это поможет вам. http://boofcv.org/index.php?title=Example_Detect_Lines

Другие вопросы по тегам