使用相机进行opencv4android模板匹配

时间:2015-03-16 07:58:14

标签: android image-processing camera opencv4android

我已下载并成功运行opencv4android sdk中提供的示例。

能够简单地显示相机框架而无需任何处理,

 public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
     return inputFrame.rgba();
 }

希望使用某些预定义的图像模板处理实时框架以识别该模板。我已经从this post参考并进行了相应的实施。但我只是黑屏。

private Mat mCameraMat = new Mat();
private Mat mTemplateMat;

 public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
    mCameraMat = inputFrame.rgba();
    initialize();

     int match_method = Imgproc.TM_SQDIFF;

        // Create the result matrix
        int result_cols = mCameraMat.cols() - mTemplateMat.cols() + 1;
        int result_rows = mCameraMat.rows() - mTemplateMat.rows() + 1;
        Log.d(TAG, " mCameraMat cols "+mCameraMat.cols());
        Log.d(TAG, " mCameraMat rows "+mCameraMat.rows());
        Log.d(TAG, " mTemplateMat cols "+mTemplateMat.cols());
        Log.d(TAG, " mTemplateMat rows "+mTemplateMat.rows());

       Mat result = new Mat(result_rows, result_cols, CvType.CV_32F);

        // Do the Matching and Normalize
        Imgproc.matchTemplate(mCameraMat, mTemplateMat, 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;
        }

        Rect roi = new Rect((int) matchLoc.x, (int) matchLoc.y, mTemplateMat.cols(), mTemplateMat.rows());
        Core.rectangle(mCameraMat, new Point(roi.x, roi.y), new Point(roi.width - 2, roi.height - 2), new Scalar(255, 0, 0, 255), 2);           
 return result;
}

public void initialize(){

    try {
        if (mCameraMat.empty())
            return;
        if(mTemplateMat == null){
            Mat temp = Utils.loadResource(Tutorial1Activity.this, R.drawable.icon);
            mTemplateMat = new Mat(temp.size(), CvType.CV_32F);
            Imgproc.cvtColor(temp, mTemplateMat, Imgproc.COLOR_BGR2RGBA);
            Log.d(TAG, "initialize mTemplateMat cols "+mTemplateMat.cols());
            Log.d(TAG, "initialize mTemplateMat rows "+mTemplateMat.rows());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

注意:

我的最终目标是识别来自现场摄像头的扑克牌。请建议最佳方法。我应该使用图像模板还是其他任何东西来加快速度?

这就是我想识别来自现场摄像机的多张卡片的方式:

结果应该是:♠A♠K♠Q♠J♠10当相机预览如下所示

enter image description here

1 个答案:

答案 0 :(得分:0)

模板匹配不太可能是最好的方法。

  1. 尝试aSIFT进行仿射不变的SIFT匹配或正常的SIFT(存在OpenCV实现)。然而, 因为它们是用C ++编写的,所以你可能希望使用JNI在Android设备上从Java调用它。这可能是从4个符号中检测卡片套装的最佳方法。
  2. 检测和识别卡片上的数字/字母表的另一个选项是使用文本检测器,如MSER,然后在MSER过滤器指示的感兴趣区域上使用文本识别器。
  3. 在任何情况下,您都不可能从图像中显示的图像中获得最佳效果。使用第一种方法,您可以获得完整正面,直立图像的可接受性能。