【OpenCVSharp】多⽬标模板匹配MatchTemplate
建⽴测试程序
通过NuGet⼯具为⼯程添加OpenCvSharp3-AnyCPU:
⼯具–NuGet包管理器—管理解决⽅案的NuGet程序包
测试程序
打开位于\bin\Debug\netcoreapp2.1和dill⽂件同⽬录下的lenna.jpg。
先添加引⽤:using OpenCvSharp;
static void Main(string[] args)
{
Mat src =new Mat("lenna.jpg", ImreadModes.Grayscale);//⼩写的scale,不然报错
Mat dst =new Mat();
Mat dst1 =new Mat();
Cv2.Canny(src, dst,50,200);
Cv2.Add(src, dst, dst1);
using(new Window("src image", src))
using(new Window("dst image", dst))
using(new Window("dst1 image", dst1))
{
Cv2.WaitKey();
}
}
测试成功之后进⾏函数理解和⾯向搜索引擎的编程
关于OpenCv的模板匹配函数matchTemplate,这些地⽅都讲得都⽐较清楚,但我第⼀天看,还没没看到在C#上实现的,所以只能⼀步步写,函数定义,模仿,解决报错。
友情链接:
C#模板匹配代码
static void Main(string[] args)
{
//模板图⽚
Mat temp =new Mat("temp.jpg",ImreadModes.AnyColor);
//被匹配图
Mat wafer =new Mat("wafer.jpg", ImreadModes.AnyColor);
//匹配结果
Mat result=new Mat();
//模板匹配
Cv2.MatchTemplate(wafer,temp,result,TemplateMatchModes.CCoeffNormed);//最好匹配为1,值越⼩匹配越差//数组位置下x,y
Point minLoc =new Point(0,0);
Point maxLoc =new Point(0,0);
Point matchLoc =new Point(0,0);
Cv2.MinMaxLoc(result,out minLoc,out maxLoc);
matchLoc = maxLoc;
Mat mask = wafer.Clone();
//画框显⽰
Cv2.Rectangle(mask, matchLoc,new Point(matchLoc.X + temp.Cols, matchLoc.Y + temp.Rows),Scalar.Green,2);
//新建窗体显⽰图⽚
using(new Window("temp image", temp))
using(new Window("wafer image", wafer))
using(new Window("mask image", mask))
{
Cv2.WaitKey();
}
}
结果
详解和补习
Point是个结构体,Point newPoint=new Point(int x,int y);,⽤于得到位置。
Cv2.Rectangle():对⾓线画框,起点和终点,都⽤Point,线宽
Cv2.Rectangle(img,(x1, y1),(x2, y2),(255,0,0),2)//
x1,y1 ------
||
||
||
--------x2,y2
重载是怎么回事呢?overload是重载,⼀般是⽤于在⼀个类内实现若⼲重载的⽅法,这些⽅法的名称相同⽽参数形式不同。
根据⼀定度量值画框标识出多个匹配结果
我们知道保存结果的矩阵是result,查矩阵中在某⼀范围坐标,就可以标识出多个结果。参数说明:
把result打印出来如下图,CV_32FC1就代表数据是32位单通道浮点数
通过At函数可以获取某坐标的值
//
// 摘要:
//    Returns a value to the specified array element.
//
// 参数:
//  i0:
//    Index along the dimension 0
//
//  i1:
//    Index along the dimension 1
//
// 类型参数:
//  T:
/
/
// 返回结果:
//    A value to the specified array element.
public T At<T>(int i0,int i1)where T :struct;
通过Set函数可以设置某坐标的值
//
// 摘要:
//    Set a value to the specified array element.
//
// 参数:
//  i0:
/
/    Index along the dimension 0
//
//  i1:
rectangle函数opencv//    Index along the dimension 1
//
//  value:
//
// 类型参数:
//  T:
public void Set<T>(int i0,int i1, T value)where T :struct;
注意⾏和列的区分,matchLoc是和习惯相反的。Y是⾏坐标,X是列坐标
那么我们就可以通过遍历⼀遍result⾥⾯每个坐标点的值,如果⼤于阈值,那么就进⾏画框显⽰。⼀般还要先经过归⼀化。还有看到⼀个⼈是每次都把最⼤值设为0,再⽤⼀次MinMaxLoc查。
我们还可以画出坐标
void cv::putText(
cv::Mat& img,// 待绘制的图像
const string& text,// 待绘制的⽂字
cv::Point origin,// ⽂本框的左下⾓
int fontFace,// 字体 (如cv::FONT_HERSHEY_PLAIN)
double fontScale,// 尺⼨因⼦,值越⼤⽂字越⼤
cv::Scalar color,// 线条的颜⾊(RGB)
int thickness =1,// 线条宽度
int lineType =8,// 线型(4邻域或8邻域,默认8邻域)
bool bottomLeftOrigin =false// true='origin at lower left'
);
static void Main(string[] args)
{
//读取图⽚
Mat temp =new Mat("temp.jpg",ImreadModes.AnyColor);//模板图⽚
//Cv2.ImWrite("temp_write.jpg",temp);//写⼊图⽚
Mat wafer =new Mat("wafer.jpg", ImreadModes.AnyColor);//被匹配图
Mat result=new Mat();//匹配结果
//模板匹配
Cv2.MatchTemplate(wafer,temp,result,TemplateMatchModes.CCoeffNormed);//最好匹配为1,值越⼩匹配越差
Double minVul;
Double maxVul;
Point minLoc =new Point(0,0);
Point maxLoc =new Point(0,0);
Point matchLoc =new Point(0,0);
Cv2.Normalize(result, result,0,1,NormTypes.MinMax,-1);//归⼀化
Cv2.MinMaxLoc(result,out minVul,out maxVul,out minLoc,out maxLoc);//查极值
matchLoc = maxLoc;//最⼤值坐标
//result.Set(matchLoc.Y, matchLoc.X, 0);//改变最⼤值为最⼩值
Mat mask = wafer.Clone();//复制整个矩阵
//画框显⽰
Cv2.Rectangle(mask, matchLoc,new Point(matchLoc.X + temp.Cols, matchLoc.Y + temp.Rows),Scalar.Green,2);
Console.WriteLine("最⼤值:{0},X:{1},Y:{2}", maxVul, matchLoc.Y, matchLoc.X);
Console.WriteLine("At获取最⼤值(Y,X):{0}", result.At<float>(matchLoc.Y, matchLoc.X));
Console.WriteLine("result的类型:{0}", result.GetType());
//循环查画框显⽰
Double threshold =0.91;
Mat maskMulti = wafer.Clone();//复制整个矩阵
for(int i=1; i<result.Rows; i++)//⾏遍历
{
for(int j =1; j < result.Cols; j++)//列遍历
{
// Console.WriteLine("({0},{1}):{2}",i,j, result.At<float>(j, i));
if(result.At<float>(i, j)> threshold)
{
Cv2.Rectangle(maskMulti,new Point(j, i),new Point(j + temp.Cols, i + temp.Rows), Scalar.Green,2);
//画出坐标
string axis ='('+ Convert.ToString(i)+','+ Convert.ToString(j)+')';
Cv2.PutText(maskMulti, axis,new Point(j, i), HersheyFonts.HersheyPlain,1, Scalar.Red,1, LineTypes.Link4);
}
}
}
//新建窗体显⽰图⽚
using(new Window("temp image", temp))
using(new Window("wafer image", wafer))
using(new Window("mask image", mask))
using(new Window("maskMulti image", maskMulti))
{
Cv2.WaitKey();
}
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。