修改框架(未完全完成)实现单个相机分开绑定算法
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user