2013-07-10 95 views
0

我正在尝试使用Java中的OpenCV库进行模板匹配。我试图利用一个代码,我发现here做这项工作。OpenCV Android模板匹配致命异常

当我执行的应用程序,我得到FATAL EXCEPTION

07-10 20:24:28.456: E/cv::error()(8608): OpenCV Error: Assertion failed (corrsize.height <= img.rows + templ.rows - 1 && corrsize.width <= img.cols + templ.cols - 1) in void cv::crossCorr(const cv::Mat&, const cv::Mat&, cv::Mat&, cv::Size, int, cv::Point, double, int), file /home/reports/ci/slave_desktop/50-SDK/opencv/modules/imgproc/src/templmatch.cpp, line 70 

&

07-10 20:55:15.706: E/AndroidRuntime(9622): FATAL EXCEPTION: main 
07-10 20:55:15.706: E/AndroidRuntime(9622): CvException [org.opencv.core.CvException: /home/reports/ci/slave_desktop/50-SDK/opencv/modules/imgproc/src/templmatch.cpp:70: error: (-215) corrsize.height <= img.rows + templ.rows - 1 && corrsize.width <= img.cols + templ.cols - 1 in function void cv::crossCorr(const cv::Mat&, const cv::Mat&, cv::Mat&, cv::Size, int, cv::Point, double, int) 

我相信,这一定有什么做的文件的大小,但也有作为应执行(main image, small image, image to write to)

我使用.BMP文件作为输入:

bmp1.bmp - size 1280x960 - main image 
bmp2.bmp - size 168x63 - template image 
bmp3.bmp - size 1280x960 - (blank .bmp file to write the result) size 1280x960 

作为一个更新,我曾尝试将我的图片给单通道8位巴纽的指示在OpenCV的文档here但仍然没有喜悦...

Start.java代码:

package com.example.matchtemplate; 

import org.opencv.android.BaseLoaderCallback; 
import org.opencv.android.LoaderCallbackInterface; 
import org.opencv.android.OpenCVLoader; 
import org.opencv.core.Core; 
import org.opencv.core.Core.MinMaxLocResult; 
import org.opencv.core.CvType; 
import org.opencv.core.Mat; 
import org.opencv.core.Point; 
import org.opencv.core.Scalar; 
import org.opencv.highgui.Highgui; 
import org.opencv.imgproc.Imgproc; 

import android.os.Bundle; 
import android.app.Activity; 
import android.util.Log; 
import android.view.Menu; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.ImageView; 

public class Start extends Activity { 

    Button button; 
    ImageView imageview; 

    protected static final String TAG = null; 
    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) { 
     @Override 
     public void onManagerConnected(int status) { 
      switch (status) { 
       case LoaderCallbackInterface.SUCCESS: 
       { 
        Log.i(TAG, "OpenCV loaded successfully"); 

       } break; 
       default: 
       { 
        super.onManagerConnected(status); 
       } break; 
      } 
     } 
    }; 

    @Override 
    public void onResume() 
    { 
     super.onResume(); 
     OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_6, this, mLoaderCallback); 

    } 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_start); 
     addListenerOnButton(); 
    } 

    public void addListenerOnButton() { 

     imageview = (ImageView) findViewById(R.id.imageView1); 

     button = (Button) findViewById(R.id.button1); 
     button.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View arg0) { 


       matchTemplate("bmp1.bmp", "bmp2.bmp", "bmp3.bmp", Imgproc.TM_CCOEFF); 
       imageview.setImageResource(R.drawable.bmp3); 
      } 

     }); 

    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.start, menu); 
     return true; 
    } 

    public void matchTemplate(String inFile, String templateFile, String outFile, int match_method) { 
     System.out.println("\nRunning Template Matching"); 

     Mat img = Highgui.imread(inFile); 
     Mat templ = Highgui.imread(templateFile); 

     ///Create the result matrix 
     int result_cols = img.cols() - templ.cols() + 1; 
     int result_rows = img.rows() - templ.rows() + 1; 
     Mat result = new Mat(result_rows, result_cols, CvType.CV_32FC1); 

     ///Do the Matching and Normalize 
     Imgproc.matchTemplate(img, templ, result, match_method); 
     Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat()); 

     ///Localizing the best match with minMaxLoc 
     MinMaxLocResult mmr = Core.minMaxLoc(result); 

     Point matchLoc; 
     if (match_method == Imgproc.TM_SQDIFF || match_method == Imgproc.TM_SQDIFF_NORMED) { 
      matchLoc = mmr.minLoc; 
     } else { 
      matchLoc = mmr.maxLoc; 
     } 

     ///Show me what you got 
     Core.rectangle(img, matchLoc, new Point(matchLoc.x + templ.cols(), 
       matchLoc.y + templ.rows()), new Scalar(0, 255, 0)); 

     // Save the visualized detection. 
     System.out.println("Writing "+ outFile); 
     Highgui.imwrite(outFile, img); 


} 

} 
+0

如果您声明'Mat result = new Mat()',那么问题是否消失?此外,作为一种性能改进,您不需要对结果进行归一化。 'MinMaxLoc'应找到没有标准化的相同位置。 – Aurelius

+0

不,问题依然存在,程序仍然报告相同的两个错误。并感谢您的提示! – jaspernorth

回答

0

有许多是造成应用失败最predo原因最小程度上你是如何与图像资源进行交互的,即你没有正确指向文件并试图写入只读区域。

最好在设备上(外部介质上)创建一个文件夹,并从/向/从那里读取/写入文件。

// the following creates/inits the folder to be working in 
// For your case, create the folder manually and drop the image files into it 
// This code just validates the folder exists 
public void initDir() { 
    if (android.os.Environment.getExternalStorageState().equals(
      android.os.Environment.MEDIA_MOUNTED)) { 
     cacheDir = new File(android.os.Environment.getExternalStorageDirectory(),"LazyList"); 
     if (!cacheDir.exists()) { 
      cacheDir.mkdirs(); 
     } 
    } 
} 

public String getFileAbsPath(String fileName) { 
    File f = new File(cacheDir, fileName); 
    return f.getAbsolutePath(); 
} 


// there is also a few modifications to this code 
// added another image resource, which will be used to set the new image 
public void addListenerOnButton() { 

     imageView = (ImageView) findViewById(R.id.imageView1); 
     img2 = (ImageView) findViewById(R.id.imageView2); 

     button = (Button) findViewById(R.id.button1); 
     button.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View arg0) { 
       String infile = getFileAbsPath("img1.png"); 
       String tp = getFileAbsPath("tp.png"); 
       String outFile = getFileAbsPath("img2.png"); 

       try { 
        matchTemplate(infile, tp, outFile, Imgproc.TM_CCOEFF); 
        Bitmap bm = BitmapFactory.decodeFile(outFile); 
        img2.setImageBitmap(bm); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      }  
     }); 
    } 

也不要忘记启用写入权限清单文件 <uses-permission android:name= "android.permission.WRITE_EXTERNAL_STORAGE"/>

你可以从这里下载我的示例应用程序进行测试和遍历代码(注:我甩了,我用的图像文件在资产文件夹)

https://bitbucket.org/kwamena/opencv-try

+0

谢谢!我试图执行你的应用程序,但它会抛出一个错误,因为你的应用程序针对的是API 17,而我的应用程序是11.我试图在Project-> Properties中更改它,但没有奏效。另外,你的意思是我可以在实际的手机上创建一个目录来读取/写入图像吗? – jaspernorth