2011-11-10 13 views
6

Soy nuevo en OpenCv y StackOverflow, y casi nuevo en la programación de Android, así que discúlpeme si mi pregunta es estúpida.OpenCv en Android: detección de punto clave en imágenes desde el archivo

Estoy tratando de hacer coincidir una imagen adquirida de la cámara con algunos archivos de imagen, para ver qué archivo de imagen es más similar a la imagen de la cámara. Así que uso DescriptorExtractor.compute para obtener los puntos clave de la imagen del archivo y la imagen de la cámara con SURF (también intenté SIFT) para hacer coincidirlos, pero ... el método aplicado a la imagen del archivo siempre devuelve una lista de puntos clave vacía, mientras si lo uso en la imagen de la cámara, siempre obtengo una lista no vacía (un centenar de puntos en promedio). Lo que más me desconcierta es que incluso usando la misma imagen, cargada desde la cámara primero, y luego desde el archivo, obtengo este comportamiento.

¿Podría por favor ayudarme a descubrir qué estoy haciendo mal? Aquí hay un código de prueba (solo para la parte del archivo, pero utilizo el mismo método getKp para extraer los puntos clave de la cámara también).

public class HelloOpenCvActivity extends Activity { 
    private static final int FILE_REQUEST = 400; 
    /** Called when the activity is first created. */ 

    ImageView img; 
    TextView txt; 
    Bitmap logo; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     img = (ImageView) findViewById(R.id.image); 
     txt = (TextView) findViewById(R.id.kp); 

     img.setOnClickListener(new OnClickListener() { 

      public void onClick(View v) { 
       chooseFile();    
      } 
     }); 
    } 

    private void chooseFile(){ 
     Intent fileIntent = new Intent(Intent.ACTION_GET_CONTENT); 
     fileIntent.addCategory(Intent.CATEGORY_OPENABLE); 
     fileIntent.setType("image/*"); 
     startActivityForResult(Intent.createChooser(fileIntent,"prova"), FILE_REQUEST); 
    } 

    /*Quando ho il risultato della chiamata al file explorer, viene invocata questa callback */ 
    @Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     if (requestCode == FILE_REQUEST) { 
      // obtain the filename 
      Uri uri = data.getData(); 
      String filePath = null; 
      if (uri != null) { 
       if (uri.toString().startsWith("file:")) { 
        filePath = uri.getPath(); 
       } else { // uri.startsWith("content:") 
        Cursor c = getContentResolver().query(uri, null, null, null, null); 
        if (c != null && c.moveToFirst()) { 
         int id = c.getColumnIndex(Images.Media.DATA); 
         if (id != -1) { 
          filePath = c.getString(id); 
         } 
        } 
       } 
      } 
      if (filePath != null) { 
       logo = BitmapFactory.decodeFile(filePath); 
       img.setImageBitmap(logo); 
       txt.setText(""+getKp(logo).size()); 
      } 
     } 
    } 

    private List<KeyPoint> getKp(Bitmap bm){ 
     Mat image = Utils.bitmapToMat(bm); 

     List<KeyPoint> kp = new ArrayList<KeyPoint>(); 
     FeatureDetector fd = FeatureDetector.create(FeatureDetector.SURF); 
     fd.detect(image, kp); 


     return kp; 
    } 

} 

Muchas gracias.

Ale

Respuesta

12

Después de horas de investigación y dolor de cabeza ;-) he encontrado el problema. Las imágenes de la cámara y el archivo pueden almacenarse en objetos de mapa de bits, pero su configuración (Bitmap.Config) es diferente: ARGB_8888 para las imágenes de la cámara y RGB_565 para las del archivo. Cambiar la configuración del mapa de bits en imágenes de archivo a ARGB_8888 con el método Bitmap.copy es la solución.

private List<KeyPoint> getKp(Bitmap bm){ 
    //scale bitmap (otherwise the program crashes due to memory lack) 
    int MAX_DIM = 300; 
    int w, h;  
    if (bm.getWidth() >= bm.getHeight()){ 
     w = MAX_DIM; 
     h = bm.getHeight()*MAX_DIM/bm.getWidth(); 
    } 
    else{ 
     h = MAX_DIM; 
     w = bm.getWidth()*MAX_DIM/bm.getHeight(); 
    } 
    bm = Bitmap.createScaledBitmap(bm, w, h, false); 

    //change bitmap config <- THAT'S THE POINT! 
    Bitmap img = bm.copy(Bitmap.Config.ARGB_8888, false);   

    Mat image = Utils.bitmapToMat(img); 

    List<KeyPoint> kp = new ArrayList<KeyPoint>(); 
    FeatureDetector fd = FeatureDetector.create(FeatureDetector.SURF); 
    fd.detect(image, kp); 

    return kp; 
} 

Espero que esto pueda ayudar a cualquiera que se encuentre con el mismo problema. :-)

+0

¡Funciona como un encanto, listo! –

Cuestiones relacionadas