2013-07-10 113 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