using CCDCount.MODEL.ShuLiModel;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CCDCount.DLL.Tools
{
public static class LineScanCameraCalibrator
{
///
/// 计算线阵相机X和Y方向的单像素精度
/// 线阵相机在X方向(像素方向)和Y方向(扫描方向)有不同的缩放系数
///
/// 已知物理距离的点对集合
/// 实际物理距离(单位:mm)
/// 包含X和Y方向单像素精度的结构体
public static PixelScale CalculateLineScanPixelScale(List knownPairs, double actualDistance)
{
if (knownPairs == null || knownPairs.Count == 0)
throw new ArgumentException("至少需要一个点对来进行校准");
List xScales = new List();
List yScales = new List();
foreach (var pair in knownPairs)
{
int deltaX = pair.Point2.X - pair.Point1.X;
int deltaY = pair.Point2.Y - pair.Point1.Y;
// 计算像素欧几里得距离
double pixelDistance = Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
if (pixelDistance == 0)
continue; // 避免除零错误
// 计算每像素的物理距离(缩放因子)
double scalePerPixel = actualDistance / pixelDistance;
// 对于线阵相机,我们需要根据X和Y方向的贡献来分解缩放因子
// X方向精度 = 总缩放因子 * |ΔX| / 像素距离
// Y方向精度 = 总缩放因子 * |ΔY| / 像素距离
if (Math.Abs(deltaX) > double.Epsilon)
{
double xScale = scalePerPixel * Math.Abs(deltaX) / pixelDistance;
xScales.Add(xScale);
}
if (Math.Abs(deltaY) > double.Epsilon)
{
double yScale = scalePerPixel * Math.Abs(deltaY) / pixelDistance;
yScales.Add(yScale);
}
}
// 计算平均值作为最终精度
double avgXScale = xScales.Count > 0 ? xScales.Average() : 1.0;
double avgYScale = yScales.Count > 0 ? yScales.Average() : 1.0;
return new PixelScale(avgXScale, avgYScale);
}
///
/// 使用更精确的方法计算线阵相机的像素精度
/// 分别处理纯X方向、纯Y方向和对角线方向的点对
///
/// 纯水平方向点对(Y坐标相同)
/// 纯垂直方向点对(X坐标相同)
/// 对角线方向点对
/// 实际物理距离(单位:mm)
/// 包含X和Y方向单像素精度的结构体
public static PixelScale CalculatePreciseLineScanPixelScale(
List horizontalPairs,
List verticalPairs,
List diagonalPairs,
double actualDistance)
{
double xScale = 1.0, yScale = 1.0;
// 优先使用纯水平方向点对计算X方向精度
if (horizontalPairs != null && horizontalPairs.Count > 0)
{
var xScales = new List();
foreach (var pair in horizontalPairs)
{
if (pair.Point1.Y != pair.Point2.Y) continue; // 确保是水平方向
int deltaX = pair.Point2.X - pair.Point1.X;
if (Math.Abs(deltaX) > 0)
{
xScales.Add(actualDistance / Math.Abs(deltaX));
}
}
if (xScales.Count > 0)
xScale = xScales.Average();
}
// 优先使用纯垂直方向点对计算Y方向精度
if (verticalPairs != null && verticalPairs.Count > 0)
{
var yScales = new List();
foreach (var pair in verticalPairs)
{
if (pair.Point1.X != pair.Point2.X) continue; // 确保是垂直方向
int deltaY = pair.Point2.Y - pair.Point1.Y;
if (Math.Abs(deltaY) > 0)
{
yScales.Add(actualDistance / Math.Abs(deltaY));
}
}
if (yScales.Count > 0)
yScale = yScales.Average();
}
// 如果缺少某个方向的纯方向点对,使用对角线点对进行补充
if (horizontalPairs == null || horizontalPairs.Count == 0)
{
// 从对角线点对中估算X方向精度
if (diagonalPairs != null && diagonalPairs.Count > 0)
{
var xScalesFromDiagonal = new List();
foreach (var pair in diagonalPairs)
{
int deltaX = pair.Point2.X - pair.Point1.X;
int deltaY = pair.Point2.Y - pair.Point1.Y;
double pixelDistance = Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
if (pixelDistance > 0)
{
double scalePerPixel = actualDistance / pixelDistance;
if (Math.Abs(deltaX) > double.Epsilon)
{
double xScaleFromDiagonal = scalePerPixel * Math.Abs(deltaX) / pixelDistance;
xScalesFromDiagonal.Add(xScaleFromDiagonal);
}
}
}
if (xScalesFromDiagonal.Count > 0 && xScale == 1.0) // 只在没有纯水平点对时更新
xScale = xScalesFromDiagonal.Average();
}
}
if (verticalPairs == null || verticalPairs.Count == 0)
{
// 从对角线点对中估算Y方向精度
if (diagonalPairs != null && diagonalPairs.Count > 0)
{
var yScalesFromDiagonal = new List();
foreach (var pair in diagonalPairs)
{
int deltaX = pair.Point2.X - pair.Point1.X;
int deltaY = pair.Point2.Y - pair.Point1.Y;
double pixelDistance = Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
if (pixelDistance > 0)
{
double scalePerPixel = actualDistance / pixelDistance;
if (Math.Abs(deltaY) > double.Epsilon)
{
double yScaleFromDiagonal = scalePerPixel * Math.Abs(deltaY) / pixelDistance;
yScalesFromDiagonal.Add(yScaleFromDiagonal);
}
}
}
if (yScalesFromDiagonal.Count > 0 && yScale == 1.0) // 只在没有纯垂直点对时更新
yScale = yScalesFromDiagonal.Average();
}
}
return new PixelScale(xScale, yScale);
}
///
/// 使用已知的像素精度计算两点间的物理距离
///
/// 第一个点
/// 第二个点
/// 像素精度
/// 物理距离(单位:mm)
public static double CalculatePhysicalDistance(Point point1, Point point2, PixelScale scale)
{
int deltaX = point2.X - point1.X;
int deltaY = point2.Y - point1.Y;
// 使用各自的像素精度计算X和Y方向的物理距离
double physicalDistanceX = Math.Abs(deltaX) * scale.XScale;
double physicalDistanceY = Math.Abs(deltaY) * scale.YScale;
// 使用勾股定理计算实际距离
return Math.Sqrt(
Math.Pow(physicalDistanceX, 2) +
Math.Pow(physicalDistanceY, 2)
);
}
///
/// 自动分类点对为水平、垂直和对角线方向
///
/// 所有点对
/// 输出:纯水平方向点对
/// 输出:纯垂直方向点对
/// 输出:对角线方向点对
public static void ClassifyPointPairs(
List allPairs,
out List horizontalPairs,
out List verticalPairs,
out List diagonalPairs)
{
horizontalPairs = new List();
verticalPairs = new List();
diagonalPairs = new List();
foreach (var pair in allPairs)
{
int deltaX = pair.Point2.X - pair.Point1.X;
int deltaY = pair.Point2.Y - pair.Point1.Y;
if (deltaY == 0 && Math.Abs(deltaX) > 0)
{
// 水平方向点对(Y坐标相同)
horizontalPairs.Add(pair);
}
else if (deltaX == 0 && Math.Abs(deltaY) > 0)
{
// 垂直方向点对(X坐标相同)
verticalPairs.Add(pair);
}
else
{
// 对角线方向点对
diagonalPairs.Add(pair);
}
}
}
}
///
/// 存储X和Y方向的像素精度
///
public struct PixelScale
{
public double XScale { get; set; } // X方向单像素精度 (mm/pixel)
public double YScale { get; set; } // Y方向单像素精度 (mm/pixel)
public PixelScale(double xScale, double yScale)
{
XScale = xScale;
YScale = yScale;
}
public override string ToString()
{
return $"XScale: {XScale:F6} mm/pixel, YScale: {YScale:F6} mm/pixel";
}
}
}