我是OpenCv和StackOverflow的新手,对
Android编程几乎不熟悉所以请原谅我,如果我的问题很愚蠢.
我试图将从相机获取的图像与某些图像文件进行匹配,以查看哪个图像文件与相机图像更相似.所以我使用DescriptorExtractor.compute获取文件图像的关键点和带有SURF的摄像机图像(我也尝试过SIFT)以匹配它们但是…应用于文件图像的方法总是返回一个空的关键点列表,而如果我在相机图像上使用它,我总是得到一个非空列表(平均一百个点).让我最困惑的是,即使使用相同的图像,首先从相机加载,然后从文件,我得到这种行为.
你能帮我弄清楚我做错了什么吗?这是一些测试代码(仅适用于文件部分,但我使用相同的方法getKp来从相机中提取关键点).
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); 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; } }
非常感谢你.
麦酒
解决方法
经过几个小时的研究和头痛;-)我发现了问题.来自摄像机和文件的图像都可以存储在位图对象中,但它们的配置(Bitmap.Config)是不同的:ARGB_8888用于摄像机图像,RGB_565用于文件图像.使用Bitmap.copy方法将文件映像中的位图配置更改为ARGB_8888是解决方案.
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; }
希望这可以帮助任何遇到同样问题的人.