函数
在opencv中有模板匹配的方法, Imgproc.matchTemplate(src, template, result, Imgproc.TM_CCOEFF);
这个方法输入的参数分别是:
src 标识输入的原图
template标识模板图片
result 匹配的结果
Imgproc.TM_CCOEFF 标识匹配的方法
例子:
String filename = "D:\\svnp\\MyYan\\res\\drawable\\lena.png";
Mat src = Imgcodecs.imread(filename);
Mat dst = new Mat();
Mat dst1 = new Mat();
Mat dst2 = new Mat();
Rect rect=new Rect(new Point(200,200),new Point(300,300));
Mat template=new Mat(src, rect);
Imgcodecs.imwrite("D:\\svnp\\MyYan\\res\\drawable\\lena2.png", template);
Mat result=new Mat();
int method=Imgproc.TM_CCOEFF;
Imgproc.matchTemplate(src, template, result, Imgproc.TM_CCOEFF);
Core.MinMaxLocResult result_m = Core.minMaxLoc(result);//取最大值和最小值
Point maxloc = result_m.maxLoc;
Point minloc = result_m.minLoc;
//获取坐标
Point p1 ;
//如果是平方不同或者归一化平方不同,那么就取最小值
p1 = (method == Imgproc.TM_SQDIFF || method == Imgproc.TM_SQDIFF_NORMED) ? minloc : maxloc;
Point p2 = new Point(p1.x+template.cols(),p1.y+template.rows());
//绘制
Imgproc.rectangle(src,p1,p2,new Scalar(0,0,255));
HighGui.imshow("原图",src);
HighGui.imshow("模板",template);
HighGui.waitKey(10);
分析
上面我们通过一个简单的例子来演示了 matchTemplate
里面的method 可以选的项目有这些:
// C++: enum TemplateMatchModes
public static final int
TM_SQDIFF = 0,
TM_SQDIFF_NORMED = 1,
TM_CCORR = 2,
TM_CCORR_NORMED = 3,
TM_CCOEFF = 4,
TM_CCOEFF_NORMED = 5;
- TM_SQDIFF = 0: 平方不同
- TM_SQDIFF_NORMED = 1:归一化平方不同
- TM_CCORR = 2:相关性
- TM_CCORR_NORMED = 3:归一化相关性
- TM_CCOEFF = 4:相关因子
- TM_CCOEFF_NORMED = 5:归一化相关因子
上面我们用的是相关因子,我们用相关因子归一
两种方法之间看不出来什么区别
不管那么多了,只要记住这个函数是模板匹配就行了
如果原图灰度化了能匹配吗:
如果原图进行了灰度化,那么模板也要进行灰度化,否则会出现下面的问题
Exception in thread "main" CvException [org.opencv.core.CvException: cv::Exception: OpenCV(4.4.0) D:\opencv\opencv-4.4.0\modules\imgproc\src\templmatch.cpp:1163: error: (-215:Assertion failed) (depth == CV_8U || depth == CV_32F) && type == _templ.type() && _img.dims() <= 2 in function 'cv::matchTemplate'
]
at org.opencv.imgproc.Imgproc.matchTemplate_1(Native Method)
at org.opencv.imgproc.Imgproc.matchTemplate(Imgproc.java:7523)
at org.opencv.test.MatTestWdg.main(MatTestWdg.java:54)
角点检测
效果:
代码:
String filename = "D:\\svnp\\MyYan\\res\\drawable\\lena.png";
Mat src = Imgcodecs.imread(filename);
Mat dst = new Mat();
Mat dst1 = new Mat();
Mat dst2 = new Mat();
Mat gray=new Mat();
Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);
Imgproc.threshold(gray, dst2,160 ,255,Imgproc.THRESH_TRIANGLE);
Imgproc.cornerHarris(dst2, dst, 2, 3, 0.04);
System.out.println(dst.cols()+"***********"+dst.rows());
//绘制角点
float[] floats = new float[dst.cols()];
for (int i = 0; i < dst.rows() ; i++) {
dst.get(i,0,floats);
for (int j = 0; j < floats.length; j++) {
if (floats[j] > 0.01){//越接近于角点数值越大
System.out.println(floats[j] );
Imgproc.circle(src,new Point(j,i),5,new Scalar(255,0,255));
}
}
}
HighGui.imshow("原图",src);
HighGui.imshow("灰度化",gray);
HighGui.imshow("阀值化",dst2);
HighGui.waitKey(0);
Imgproc.cornerHarris(src, dst2, blockSize, ksize, k);
src 输入图像
dst2 检测结果 不可以显示
blockSize:根据特征向量计算矩阵M的大小,常见取值为2
ksize:Sobel算子梯度计算 一般取值3
k:系数大小,取值范围为0.02-0.04
图片上绘制文字
中文文字目前java的没找到相关的接口 ,如果各位大佬实现了中文字符的putText希望能评论一下
Imgproc.putText(src, "helloWorld", new Point(src.rows()/3,src.cols()/3),Imgproc.FONT_HERSHEY_SIMPLEX, 2, new Scalar(0.9));
Imgproc.putText(img, text, org, fontFace, fontScale, color);
img 标识图片
text 标识输入的文本
org 文本写入点的位置
fontface 字体类型
fontScale字体大小
color 字体的颜色
上面是对Opencv java的一个简单的应用,写到这个地方感觉感触很多,学习opencv,我们像是在学习一个工具,这个工具可以帮助我们做一些图像处理,无论我们在这个工具上做出什么样的花样,但是工具的本质并没有变化,而且我们的性质也没有变化,我们程序员不是创造者,而是一个工具使用者,我总是想摆脱这样的困境,但是发现自己的脑力不够用,我总希望自己能够做出点不同的的东西,但是发现自己不过是一个工具的使用者,但是真正的创造者在工具的后面,他们给出什么样子的功能我们才可以使用什么样子的功能,我们改如何改变这样的困局,是否真的是我们需要把基础打好,慢慢的提高自己的地基,就像是金字塔,我们什么时候能走到顶峰,下面是一片海洋。。。。
希望对你有所帮助,希望不做工具人