1/模板匹配方法
///
/// 多角度模板匹配方法
///
/// 待匹配图像
/// 模板图像
/// 起始角度
/// 角度范围
/// 角度步长
/// 金字塔层级
/// 得分阈值
///
private ResultPoint CircleMatchNcc(Mat srcImage, Mat modelImage, double angleStart, double angleRange, double angleStep, int numLevels, double thresScore,int nccMethod)
{
double step = angleRange / ((angleRange / angleStep) / 100);
double start = angleStart;
double range = angleRange;
//定义图片匹配所需要的参数
int resultCols = srcImage.Cols - modelImage.Cols + 1;
int resultRows = srcImage.Rows - modelImage.Cols + 1;
Mat result = new Mat(resultCols, resultRows, MatType.CV_8U);
Mat src = new Mat();
Mat model = new Mat();
srcImage.CopyTo(src);
modelImage.CopyTo(model);
//对模板图像和待检测图像分别进行图像金字塔下采样
for (int i = 0; i < numLevels; i++)
{
Cv2.PyrDown(src, src, new Size(src.Cols / 2, src.Rows / 2));
Cv2.PyrDown(model, model, new Size(model.Cols / 2, model.Rows / 2));
}
TemplateMatchModes matchMode = TemplateMatchModes.CCoeffNormed;
switch (nccMethod)
{
case 0:
matchMode = TemplateMatchModes.SqDiff;
break;
case 1:
matchMode = TemplateMatchModes.SqDiffNormed;
break;
case 2:
matchMode = TemplateMatchModes.CCorr;
break;
case 3:
matchMode = TemplateMatchModes.CCorrNormed;
break;
case 4:
matchMode = TemplateMatchModes.CCoeff;
break;
case 5:
matchMode = TemplateMatchModes.CCoeffNormed;
break;
}
//在没有旋转的情况下进行第一次匹配
Cv2.MatchTemplate(src, model, result, matchMode);
Cv2.MinMaxLoc(result, out double minVal, out double maxVal, out Point minLoc, out Point maxLoc, new Mat());
Point location = maxLoc;
double temp = maxVal;
double angle = 0;
Mat newImg;
//以最佳匹配点左右十倍角度步长进行循环匹配,直到角度步长小于参数角度步长
if (nccMethod == 0 || nccMethod == 1)
{
do
{
for (int i = 0; i <= (int)range / step; i++)
{
newImg = ImageRotate(model, start + step * i);
Cv2.MatchTemplate(src, newImg, result, matchMode);
Cv2.MinMaxLoc(result, out double minval, out double maxval, out Point minloc, out Point maxloc, new Mat());
if (maxval < temp)
{
location = maxloc;
temp = maxval;
angle = start + step * i;
}
}
range = step * 2;
start = angle - step;
step = step / 10;
} while (step > angleStep);
return new ResultPoint(location.X * Math.Pow(2, numLevels) + modelImage.Width / 2, location.Y * Math.Pow(2, numLevels) + modelImage.Height / 2, -angle, temp);
}
else
{
do
{
for (int i = 0; i <= (int)range / step; i++)
{
newImg = ImageRotate(model, start + step * i);
Cv2.MatchTemplate(src, newImg, result, matchMode);
Cv2.MinMaxLoc(result, out double minval, out double maxval, out Point minloc, out Point maxloc, new Mat());
if (maxval > temp)
{
location = maxloc;
temp = maxval;
angle = start + step * i;
}
}
range = step * 2;
start = angle - step;
step = step / 10;
} while (step > angleStep);
if (temp > thresScore)
{
return new ResultPoint(location.X * Math.Pow(2, numLevels), location.Y * Math.Pow(2, numLevels), -angle, temp);
}
}
return new ResultPoint();
}
2/其他准备
public ResultPoint(double x, double y, double t, double score)
{
X = (int)x;
Y = (int)y;
T = t;
Score = score;
}
///
/// 图像旋转
///
/// 输入图像
/// 旋转的角度
/// 旋转后图像
static Mat ImageRotate(Mat image, double angle)
{
Mat newImg = new Mat();
Point2f pt = new Point2f((float)image.Cols / 2, (float)image.Rows / 2);
Mat r = Cv2.GetRotationMatrix2D(pt, angle, 1.0);
Cv2.WarpAffine(image, newImg, r, image.Size());
return newImg;
}
///
/// 金字塔下采样
///
/// 输入图像
/// 下采样完图像
private Mat ImagePyrDown(Mat image)
{
for (int i = 0; i < MyConfig.NumLevels; i++)
{
Cv2.PyrDown(image, image, new Size(image.Cols / 2, image.Rows / 2));
}
return image;
}