修改框架(未完全完成)实现单个相机分开绑定算法

This commit is contained in:
2025-10-20 17:47:48 +08:00
parent 31d9f8d6b6
commit 73249ee6c2
11 changed files with 1226 additions and 422 deletions

View File

@@ -158,6 +158,9 @@ namespace HalconTemplateMatch
{
private readonly List<HTuple> modelHandles = new List<HTuple>();
// 构造函数用于初始化
public LogoMatcher() { }
/// <summary>
/// 从指定目录加载所有 .shm 模板文件
/// </summary>
@@ -207,54 +210,231 @@ namespace HalconTemplateMatch
}
}
/// <summary>
/// 匹配并返回最高得分double返回
/// </summary>
public double FindLogo(Bitmap bmp)
// /// <summary>
// /// 匹配并返回最高得分double返回
// /// </summary>
// public double FindLogo(Bitmap bmp)
// {
// if (modelHandles.Count == 0)
// {
// Console.WriteLine("[警告] 尚未加载任何模板。");
// return -1;
// }
// // Bitmap 转 Halcon 对象
// HObject ho_TestImage;
// Bitmap2HObject(bmp, out ho_TestImage);
// HOperatorSet.Rgb1ToGray(ho_TestImage, out ho_TestImage);
// double bestScore = -1;
// foreach (var modelID in modelHandles)
// {
// try
// {
// HOperatorSet.FindScaledShapeModel(
// ho_TestImage,
// modelID,
// new HTuple(0).TupleRad(),
// new HTuple(360).TupleRad(),
// 0.8, 1.2,
// 0.5, 1, 0.5,
// "least_squares_high",
// 0, 0.9,
// out HTuple row, out HTuple col, out HTuple angle, out HTuple scale, out HTuple score
//);
// if (score.Length > 0 && score[0].D > bestScore)
// bestScore = score[0].D;
// }
// catch (HOperatorException ex)
// {
// Console.WriteLine($"[错误] 模板匹配失败: {ex.Message}");
// }
// }
// ho_TestImage.Dispose();
// return bestScore;
// }
public double FindLogo(Bitmap bmp, out Bitmap resultImage) // 返回结果图像
{
if (modelHandles.Count == 0)
{
Console.WriteLine("[警告] 尚未加载任何模板。");
resultImage = (Bitmap)bmp.Clone();
return -1;
}
// Bitmap 转 Halcon 对象
HObject ho_TestImage;
Bitmap2HObject(bmp, out ho_TestImage);
HOperatorSet.Rgb1ToGray(ho_TestImage, out ho_TestImage);
double bestScore = -1;
HTuple bestRow = new HTuple(), bestCol = new HTuple(), bestAngle = new HTuple(), bestScale = new HTuple();
int bestModelIndex = -1;
foreach (var modelID in modelHandles)
for (int i = 0; i < modelHandles.Count; i++)
{
var modelID = modelHandles[i];
try
{
HOperatorSet.FindScaledShapeModel(
ho_TestImage,
modelID,
new HTuple(0).TupleRad(),
new HTuple(360).TupleRad(),
0.8, 1.2,
0.5, 1, 0.5,
"least_squares_high",
0, 0.9,
out HTuple row, out HTuple col, out HTuple angle, out HTuple scale, out HTuple score
);
ho_TestImage,
modelID,
new HTuple(0).TupleRad(), new HTuple(360).TupleRad(),
0.8, 1.2,
0.5, 1, 0.5,
"least_squares_high",
0, 0.9,
out HTuple row, out HTuple col, out HTuple angle, out HTuple scale, out HTuple score
);
if (score.Length > 0 && score[0].D > bestScore)
{
bestScore = score[0].D;
bestRow = row;
bestCol = col;
bestAngle = angle;
bestScale = scale;
bestModelIndex = i;
}
}
catch (HOperatorException ex)
{
Console.WriteLine($"[错误] 模板匹配失败: {ex.Message}");
//Console.WriteLine($"[错误] 模板匹配失败: {ex.Message}"); // 避免过多日志
}
}
resultImage = DrawHalconResults(bmp, bestModelIndex >= 0 ? modelHandles[bestModelIndex] : new HTuple(), bestRow, bestCol, bestAngle, bestScale, bestScore);
ho_TestImage.Dispose();
return bestScore;
}
//private Bitmap DrawHalconResults(Bitmap originalBmp, HTuple modelID, HTuple row, HTuple col, HTuple angle, HTuple scale, double score)
//{
// Bitmap drawnBmp = (Bitmap)originalBmp.Clone();
// if (score <= 0 || modelID.Length == 0) return drawnBmp; // 未找到或分数过低不绘制
// using (Graphics g = Graphics.FromImage(drawnBmp))
// {
// Pen pen = (score > 0.7) ? new Pen(Color.Green, 3) : new Pen(Color.Orange, 3); // 可以根据分数改变颜色
// Font font = new Font("Arial", 12, FontStyle.Bold);
// Brush brush = (score > 0.7) ? new SolidBrush(Color.Green) : new SolidBrush(Color.Orange);
// // 获取匹配模板的轮廓
// HOperatorSet.GetShapeModelContours(out HObject modelContours, modelID, 1);
// // 转换到图像坐标
// HOperatorSet.AffineTransContourXld(modelContours, out HObject transformedContours,
// new HTuple(angle), new HTuple(scale), new HTuple(row), new HTuple(col),
// "fit_origin"); // 假设 FindScaledShapeModel 的 row/col 是中心
// // 绘制 XLD 轮廓
// HTuple numContours;
// HOperatorSet.CountObj(transformedContours, out numContours);
// for (int i = 1; i <= numContours; i++)
// {
// HOperatorSet.SelectObj(transformedContours, out HObject currentContour, i);
// HOperatorSet.GetContourXld(currentContour, out HTuple contourRow, out HTuple contourCol);
// if (contourRow.Length > 1)
// {
// Point[] points = new Point[contourRow.Length];
// for (int j = 0; j < contourRow.Length; j++)
// {
// points[j] = new Point((int)contourCol.DArr[j], (int)contourRow.DArr[j]);
// }
// g.DrawPolygon(pen, points);
// }
// currentContour.Dispose();
// }
// // 绘制得分
// if (row.Length > 0 && col.Length > 0)
// {
// g.DrawString($"Score: {score:F2}", font, brush, (float)col.D - 50, (float)row.D - 50);
// }
// modelContours.Dispose();
// transformedContours.Dispose();
// }
// return drawnBmp;
//}
private Bitmap DrawHalconResults(Bitmap originalBmp, HTuple modelID, HTuple row, HTuple col, HTuple angle, HTuple scale, double score)
{
// 克隆输入图像用于绘制
Bitmap drawnBmp = (Bitmap)originalBmp.Clone();
// 如果未找到匹配,不绘制任何内容
if (score <= 0 || modelID.Length == 0)
return drawnBmp;
using (Graphics g = Graphics.FromImage(drawnBmp))
{
// 绘制样式:高分绿色、低分橙色
Pen pen = (score > 0.7) ? new Pen(Color.Green, 3) : new Pen(Color.Orange, 3);
Font font = new Font("Arial", 12, FontStyle.Bold);
Brush brush = (score > 0.7) ? new SolidBrush(Color.Green) : new SolidBrush(Color.Orange);
// 1⃣ 获取模板的轮廓
HOperatorSet.GetShapeModelContours(out HObject modelContours, modelID, 1);
// 2⃣ 构建仿射变换矩阵
HTuple homMat2D;
HOperatorSet.HomMat2dIdentity(out homMat2D); // 初始化单位矩阵
HOperatorSet.HomMat2dScale(homMat2D, scale, scale, 0, 0, out homMat2D); // 缩放
HOperatorSet.HomMat2dRotate(homMat2D, angle, 0, 0, out homMat2D); // 旋转
HOperatorSet.HomMat2dTranslate(homMat2D, col, row, out homMat2D); // 平移
// 3⃣ 将轮廓按仿射矩阵变换
HOperatorSet.AffineTransContourXld(modelContours, out HObject transformedContours, homMat2D);
// 4⃣ 统计轮廓数量并逐一绘制
HOperatorSet.CountObj(transformedContours, out HTuple numContours);
for (int i = 1; i <= numContours; i++)
{
HOperatorSet.SelectObj(transformedContours, out HObject currentContour, i);
HOperatorSet.GetContourXld(currentContour, out HTuple contourRow, out HTuple contourCol);
if (contourRow.Length > 1)
{
Point[] points = new Point[contourRow.Length];
for (int j = 0; j < contourRow.Length; j++)
{
points[j] = new Point((int)contourCol[j].D, (int)contourRow[j].D);
}
g.DrawPolygon(pen, points);
}
currentContour.Dispose();
}
// 5⃣ 绘制得分文字
if (row.Length > 0 && col.Length > 0)
{
g.DrawString($"Score: {score:F2}", font, brush, (float)col.D - 50, (float)row.D - 50);
}
// 6⃣ 清理资源
modelContours.Dispose();
transformedContours.Dispose();
// 释放 GDI+ 对象
pen.Dispose();
font.Dispose();
brush.Dispose();
}
return drawnBmp;
}
/// <summary>
/// Bitmap 转 Halcon HObject
/// </summary>