通用技术 图片部分匹配技术之 openCV 与 javaCV

vigossjjj · 2014年09月16日 · 最后由 孟德功 回复于 2017年09月29日 · 5435 次阅读
本帖已被设为精华帖!

由于之前工作需要研究了图片比对技术,实践过 python 的 PIL 感觉达不到我的测试需要,之后研究 opencv 与 javacv(javaCV 整合了很多图像影音处理的 jar,并且 windows、linux、Mac 都兼容),opencv 与 javacv 的安装大家直接 google 自行解决吧,话不多说直接上代码。

java(javaCV) 版图片部分匹配代码:

TemplateMatch 工具类:

package com.javacv.test;

import static com.googlecode.javacv.cpp.opencv_core.cvCreateImage;
import static com.googlecode.javacv.cpp.opencv_core.cvMinMaxLoc;
import static com.googlecode.javacv.cpp.opencv_core.cvReleaseImage;
import static com.googlecode.javacv.cpp.opencv_highgui.cvLoadImage;
import static com.googlecode.javacv.cpp.opencv_imgproc.CV_TM_CCORR_NORMED;
import static com.googlecode.javacv.cpp.opencv_imgproc.cvMatchTemplate;
import com.googlecode.javacv.cpp.opencv_core;
import com.googlecode.javacv.cpp.opencv_core.IplImage;

public class TemplateMatch {

    private opencv_core.IplImage image;

    public void load(String filename) {
        image = cvLoadImage(filename); 
    }

    public boolean matchTemplate(IplImage source) {
        boolean matchRes;
        IplImage result = cvCreateImage(opencv_core.cvSize(
                source.width() - this.image.width() + 1,
                source.height() - this.image.height() + 1),
                opencv_core.IPL_DEPTH_32F, 1);

        opencv_core.cvZero(result);
        cvMatchTemplate(source, this.image, result, CV_TM_CCORR_NORMED);
        opencv_core.CvPoint maxLoc = new opencv_core.CvPoint();
        opencv_core.CvPoint minLoc = new opencv_core.CvPoint();
        double[] minVal = new double[2];
        double[] maxVal = new double[2];

        cvMinMaxLoc(result, minVal, maxVal, minLoc, maxLoc, null);
        matchRes = maxVal[0] > 0.99f ? true : false;
        cvReleaseImage(result);
        return matchRes;
    }
}

JavaCVTest 测试类:

package com.javacv.test;

import static com.googlecode.javacv.cpp.opencv_highgui.cvLoadImage;
public class JavaCVTest {

    public static void main(String[] args) {
        System.out.println("START...");
        TemplateMatch tm = new TemplateMatch();//实例化TemplateMatch对象
        tm.load("data/585.png");//加载带比对图片,注此图片必须小于源图
        boolean result = tm.matchTemplate(cvLoadImage("data/58home.png"));//校验585.png是否包含于原图58home.png
        if (result){//打印匹配结果,boolean
            System.out.println("match");
        }else{
            System.out.println("un-match");
        }
        System.out.println("END...");
    }
}

python(opencv) 版图片部分匹配代码:

#coding=utf-8
import cv2  
import numpy as np   

class imgMatcher:

    def __init__(self,sourceimg):
        self.sourceimg = sourceimg

    def find(self,templateimg,threshold=0.8):
        image = cv2.imread(self.sourceimg)  
        template = cv2.imread(templateimg)  
        result = cv2.matchTemplate(image,template,cv2.cv.CV_TM_CCOEFF_NORMED) 
        similarity = cv2.minMaxLoc(result)[1]
        if similarity < threshold:
            return similarity
        else:
            return np.unravel_index(result.argmax(),result.shape)


if __name__=="__main__":
    matcher = imgMatcher("58home.png")
    for img in ['581.png','582.png','583.png','584.png','585.png','586.png','587.png','588.png','589.png','5810.png']:
        print img,matcher.find(img)

58home.png:
585.png:

目前我运用图片匹配技术在脚本开发过中,为了丰富验证方式,以及正在开发一个脚本录制工具,基于坐标点击 + 图片验证点插入。希望大家一起探讨运用图片匹配技术,如何更好的开展无线 UI 兼容测试。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 11 条回复 时间 点赞

不错,学习了

收藏了,很有用

赞,这个匹配速度如何?

也考虑过用图像去做一些事,但是因为 UI 的改动频繁,而且受数据的影响,如果维护一个 base line 的成本也比较高,所以在收益上还是值得考虑的

#4 楼 @zhangzhao_lenovo 嗖嗖的。。。试试不就得了。。。我基于这个做了 android 自动化测试录制工具,匹配图片时效率还可以

手机分辨率适配是个问题啊,不同分辨率适配工作量也不小

cvMinMaxLoc 这个方法能不能提供一下, 邮箱:363758100@qq.com

@vigossjjj 大神你有 cvMinMaxLoc 这个方法么,有的话辛苦提供下,邮箱:363758100@qq.com

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册