4

私のプロジェクトは、OpenCV ライブラリを使用して Android で葉を認識することです。ORB 検出を使用して画像のキーポイントを取得し、ORB 記述子を使用してキーポイントの機能を取得しています。これは私が使用するコードです:

bmp=BitmapFactory.decodeResource(getResources(),R.drawable.t1);
Utils.bitmapToMat(bmp, mat);
FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB);
detector.detect(mat, keypoints);
DescriptorExtractor extractor = DescriptorExtractor.create(DescriptorExtractor.ORB);
extractor.compute(mat, keypoints, features);

ソース: http://answers.opencv.org/question/6260/orb-features/

しかし、同じ画像を入力するたびに、その画像のキーポイントは常に異なります。キーポイントの機能が常に異なる場合、データベースに保存できますか? それとも、特徴データを保存するために画像を保存する必要がありますか? それがデータベースに保存できる場合、どうすればそれを行うことができますか??

4

4 に答える 4

6

私の意見では、キーポイントを格納する最も一般的な方法は、最初にキーポイントを JSON のようなデータ交換形式に変換することです。

その変換を行うことができた後は、それを保存するための多くの柔軟性があります。JSON は簡単に文字列に変換したり、ネットワーク接続を介して送信したりできます。

OpenCV C++を使用すると、データを YAML として保存できますが、Android ではまだ利用できません。

Java で JSON を解析するには、この使いやすいライブラリ Google GSONを使用できます。

そして、これがまさにそれを行う最初の試みです:

 public static String keypointsToJson(MatOfKeyPoint mat){
    if(mat!=null && !mat.empty()){          
        Gson gson = new Gson();

        JsonArray jsonArr = new JsonArray();            

        KeyPoint[] array = mat.toArray();
        for(int i=0; i<array.length; i++){
            KeyPoint kp = array[i];

            JsonObject obj = new JsonObject();

            obj.addProperty("class_id", kp.class_id); 
            obj.addProperty("x",        kp.pt.x);
            obj.addProperty("y",        kp.pt.y);
            obj.addProperty("size",     kp.size);
            obj.addProperty("angle",    kp.angle);                          
            obj.addProperty("octave",   kp.octave);
            obj.addProperty("response", kp.response);

            jsonArr.add(obj);               
        }

        String json = gson.toJson(jsonArr);         

        return json;
    }
    return "{}";
}

public static MatOfKeyPoint keypointsFromJson(String json){
    MatOfKeyPoint result = new MatOfKeyPoint();

    JsonParser parser = new JsonParser();
    JsonArray jsonArr = parser.parse(json).getAsJsonArray();        

    int size = jsonArr.size();

    KeyPoint[] kpArray = new KeyPoint[size];

    for(int i=0; i<size; i++){
        KeyPoint kp = new KeyPoint(); 

        JsonObject obj = (JsonObject) jsonArr.get(i);

        Point point = new Point( 
                obj.get("x").getAsDouble(), 
                obj.get("y").getAsDouble() 
        );          

        kp.pt       = point;
        kp.class_id = obj.get("class_id").getAsInt();
        kp.size     =     obj.get("size").getAsFloat();
        kp.angle    =    obj.get("angle").getAsFloat();
        kp.octave   =   obj.get("octave").getAsInt();
        kp.response = obj.get("response").getAsFloat();

        kpArray[i] = kp;
    }

    result.fromArray(kpArray);

    return result;
}
于 2014-02-19T00:01:57.103 に答える
1

タイミングを実行したことはありませんが、XML や JSON などの形式を使用すると、プリミティブを使用するよりも多くのスペースとコンピューティング リソースが必要になると思います。

以下は、Android 環境で MatOfKeyPoint を SQLite データベースに保存および取得するために使用できるコードです。これはOpenCV 2.4.11を使用しているため、SIFTが利用可能です。

このアプリケーションを実行すると、キーポイントが追加されたテスト イメージ (提供して drawable フォルダーに入れる必要があります) が表示されます。

このメソッドは、型siftTest()を計算することから始まります。このコードは、そのオブジェクトの基になるデータをデータベースに保存し、そのデータを読み取り、新しいオブジェクトを作成します。その内容が元の画像に適用され、結果が表示されます。keyPointsMatOfKeyPointkeyPointsFromDb

public class MainActivity extends AppCompatActivity {
    static {
        System.loadLibrary("native-lib");
        System.loadLibrary("opencv_java");
        System.loadLibrary("nonfree");

    }
    private ImageView imageView;
    private Bitmap inputImage; // make bitmap from image resource
    private FeatureDetector detector = FeatureDetector.create(FeatureDetector.SIFT);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        inputImage = BitmapFactory.decodeResource(getResources(), R.drawable.test);
        imageView = (ImageView) this.findViewById(R.id.imageView);
        siftTest();
    }

    public void siftTest() {
        Mat rgba = new Mat();
        Utils.bitmapToMat(inputImage, rgba);
        MatOfKeyPoint keyPoints = new MatOfKeyPoint();
        Imgproc.cvtColor(rgba, rgba, Imgproc.COLOR_RGBA2GRAY);
        detector.detect(rgba, keyPoints);

        // Save to database
        MatchingDatabaseAdapter.addKeypoints(keyPoints, getApplicationContext());

        // Opens database cursor
        MatchingDatabaseAdapter.getAllRecordsCursor(getApplicationContext()); 

        // Gets the first item in the database (as an example... you could loop through many/all)
        MatOfKeyPoint keyPointsFromDb = MatchingDatabaseAdapter.getKeypointsFromNextCursorPosition();

        // Closes database
        MatchingDatabaseAdapter.closeDb(); 

        Features2d.drawKeypoints(rgba, keyPointsFromDb, rgba);
        Utils.matToBitmap(rgba, inputImage);
        imageView.setImageBitmap(inputImage);

    }
}

データベースに必要なバイト配列への変換に関連する詳細を含むデータベース コードを次に示します。データベースの使用に関連するすべてを含めたわけではありません。これは実際には別のトピックだからです。

public class MatchingDatabaseAdapter {
    ...
    ...
    ...

    public static void addKeypoints(MatOfKeyPoint keyPoints, Context context) {
        float[] data = new float[(int)keyPoints.total() * keyPoints.channels()]; // make a spot to save the data
        keyPoints.get(0,0,data); // load the data;
        ByteBuffer buffer = ByteBuffer.allocate(data.length * 4);
        for (int i = 0; i < data.length; i++){
            buffer.putFloat(data[i]);
        }
        byte[] byteArray = buffer.array();
        addBlob(byteArray, keyPoints.rows(), keyPoints.cols(), keyPoints.type(), context);
    }

    public static void addBlob(byte[] blob, int rows, int columns, int mattype, Context context) throws SQLException {
        if (mDb == null) mDb = openDb(context);
        ContentValues contentValues = new ContentValues();
        contentValues.put(DatabaseHelper.BLOB_FIELD_NAME, blob);
        contentValues.put(DatabaseHelper.ROWS_FIELD_NAME, rows);
        contentValues.put(DatabaseHelper.COLUMNS_FIELD_NAME, columns);
        contentValues.put(DatabaseHelper.MATTYPE_FIELD_NAME, mattype);
        long x = mDb.insert(DatabaseHelper.TABLE_NAME, null, contentValues);
        Log.v(TAG, "insert said " + x + " and blob was " + blob.length + " long.");
        closeDb();
    }

    public static Cursor getAllRecordsCursor(Context context) {
        if (mDb == null || !mDb.isOpen()) mDb = openDb(context);
        mCursor = mDb.query(DatabaseHelper.TABLE_NAME, null, null, null, null,null, null);
        boolean hasRecords = mCursor.moveToFirst();
        Log.v(TAG, "MatchingDatabaseAdapter.getAllRecordsCursor() cursor created. " + mCursor + " and " + (hasRecords?"has records":"has NO RECORDS"));
        return mCursor;
    }

     public static MatOfKeyPoint getKeypointsFromNextCursorPosition() {
        MatOfKeyPoint keyPoints = null;
        if (mCursor != null) {
            Log.v(TAG, "mCursor has " + mCursor.getCount());
            mCursor.moveToFirst();
            int rows = mCursor.getInt(DatabaseHelper.ROWS_FIELD_POSITION);
            int columns = mCursor.getInt(DatabaseHelper.COLUMNS_FIELD_POSITION);
            int mattype = mCursor.getInt(DatabaseHelper.MATTYPE_FIELD_POSITION);
            keyPoints = new MatOfKeyPoint();
            keyPoints.create(rows, columns, mattype);
            byte[] blob = mCursor.getBlob(DatabaseHelper.BLOB_FIELD_POSITION);
            ByteBuffer buffer = ByteBuffer.wrap(blob);
            FloatBuffer floatBuffer = buffer.asFloatBuffer();
            float[] floatArray = new float[floatBuffer.limit()];
            floatBuffer.get(floatArray);
            keyPoints.put(0, 0, floatArray);
        }
        return keyPoints;
    }

    // INNER CLASS DatabaseHelper
    static class DatabaseHelper extends SQLiteOpenHelper {
        private static DatabaseHelper mDatabaseHelper;
        private static final String DB_NAME = "blobDb";
        private static final String TABLE_NAME = "blobTable";
        private static final String ROWS_FIELD_NAME = "rowsField";
        public static final int ROWS_FIELD_POSITION = 1;
        private static final String COLUMNS_FIELD_NAME = "columnsField";
        public static final int COLUMNS_FIELD_POSITION = 2;
        private static final String MATTYPE_FIELD_NAME = "mattypeField";
        public static final int MATTYPE_FIELD_POSITION = 3;
        private static final String BLOB_FIELD_NAME = "blobField";
        private static final int BLOB_FIELD_POSITION = 4;

        private static final java.lang.String CREATE_TABLE_SQL =
                "CREATE TABLE " + TABLE_NAME + " ("
                        + "_id INTEGER PRIMARY KEY AUTOINCREMENT, "
                        + ROWS_FIELD_NAME + " INTEGER, "
                        + COLUMNS_FIELD_NAME + " INTEGER, "
                        + MATTYPE_FIELD_NAME + " INTEGER, "
                        + BLOB_FIELD_NAME + " BLOB"
                        + ");";

        private DatabaseHelper(Context context) {
            super(context, DB_NAME, null, DB_VERSION);
            mDatabaseHelper = this;
        }

        static synchronized DatabaseHelper getInstance(Context context) {
            if (mDatabaseHelper == null) {
                mDatabaseHelper = new DatabaseHelper(context.getApplicationContext());
            }
            return mDatabaseHelper;
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            Log.v(TAG, "Creating table: " + CREATE_TABLE_SQL);
            db.execSQL(CREATE_TABLE_SQL);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            Log.v(TAG, "onUpgrade() from " + oldVersion + " to " + newVersion);
            Log.v(TAG, "ALL DATA BEING REMOVED FROM THE DATABASE!!");
            db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME + ";");
            onCreate(db);
        }
    }
}

完全なサンプル プロジェクトが実行され、サーフィンのキー ポイントが表示されます。そのため、キーポイントをデータベースに保存する場合は、このコードで目的の場所に移動できます。

于 2017-05-20T18:27:26.067 に答える
0

最近、人間のジェスチャー認識に関するプロジェクトを完了しました。しかし、openCv の svm を使用しました。各画像の通知キーポイント番号は、その顕著な点です(openCv定義による)。認識、つまり「予測」のために、マットであるキーポイントの機能 (キーポイント プロパティ) を保存する必要があります。SURF を使用し、キーポイントごとに 64 個の特徴を計算しました。お役に立てば幸いです。

于 2015-07-01T06:23:03.493 に答える