You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现仅在旋转雷达扇形覆盖时将差异像素标为黄色?

实现多普勒雷达扫过式差异像素标记(C# WinForms)

要实现雷达扇形扫过才标记差异像素的效果,核心思路是先预存所有差异像素的坐标,再在雷达旋转的每一帧中,仅标记当前扇形覆盖范围内的差异像素,具体修改步骤如下:

1. 预存差异像素坐标,避免一次性标记

修改CalcDifference方法,不再直接给像素上色,而是把差异像素的坐标存入集合,后续按需处理:

// 全局集合,存储所有差异像素的坐标
private List<Point> _differencePixels = new List<Point>();

private void CalcDifference(Bitmap prevFrame, Bitmap currFrame)
{
    _differencePixels.Clear();
    // 遍历所有像素,筛选差异点
    for (int y = 0; y < prevFrame.Height; y++)
    {
        for (int x = 0; x < prevFrame.Width; x++)
        {
            Color prevColor = prevFrame.GetPixel(x, y);
            Color currColor = currFrame.GetPixel(x, y);
            // 自定义差异判断阈值,可根据实际需求调整
            bool hasDifference = Math.Abs(prevColor.R - currColor.R) > 30 ||
                                 Math.Abs(prevColor.G - currColor.G) > 30 ||
                                 Math.Abs(prevColor.B - currColor.B) > 30;
            
            if (hasDifference)
            {
                _differencePixels.Add(new Point(x, y));
            }
        }
    }
}

2. 实现雷达扇形的角度判断逻辑

添加跟踪雷达旋转状态的字段,以及判断像素是否在当前扇形内的方法:

// 雷达中心(取PictureBox控件中心)
private Point _radarCenter;
// 当前扇形的起始角度(弧度,0为正右方向,顺时针递增)
private double _currentStartAngle;
// 扇形的角度宽度(示例为60度,转成弧度)
private double _sectorWidth = Math.PI / 3;

// 在Form_Load或构造函数中初始化中心坐标
private void Form1_Load(object sender, EventArgs e)
{
    _radarCenter = new Point(pictureBox1.Width / 2, pictureBox1.Height / 2);
}

// 判断指定像素是否在当前雷达扇形范围内
private bool IsPixelInSector(Point pixel)
{
    // 计算像素相对于雷达中心的向量角度
    double dx = pixel.X - _radarCenter.X;
    double dy = pixel.Y - _radarCenter.Y;
    double pixelAngle = Math.Atan2(dy, dx);
    
    // 将角度转换为[0, 2π]范围
    if (pixelAngle < 0)
        pixelAngle += 2 * Math.PI;
    
    // 计算扇形结束角度,处理跨360度的情况
    double sectorEndAngle = _currentStartAngle + _sectorWidth;
    if (sectorEndAngle > 2 * Math.PI)
        sectorEndAngle -= 2 * Math.PI;
    
    // 判断角度是否在扇形区间内
    if (_currentStartAngle <= sectorEndAngle)
    {
        return pixelAngle >= _currentStartAngle && pixelAngle <= sectorEndAngle;
    }
    else
    {
        // 扇形跨过0度(360度)的特殊情况
        return pixelAngle >= _currentStartAngle || pixelAngle <= sectorEndAngle;
    }
}

3. 动态更新雷达角度,按需标记差异像素

用定时器控制雷达旋转,在重绘时仅标记当前扇形内的差异像素:

// 控制雷达旋转的定时器
private Timer _radarRotateTimer;

// 在构造函数或Form_Load中初始化定时器
private void Form1_Load(object sender, EventArgs e)
{
    _radarRotateTimer = new Timer();
    _radarRotateTimer.Interval = 50; // 每50ms刷新一次,控制旋转速度
    _radarRotateTimer.Tick += RadarRotateTimer_Tick;
    _radarRotateTimer.Start();
    
    // 初始化雷达中心
    _radarCenter = new Point(pictureBox1.Width / 2, pictureBox1.Height / 2);
}

// 定时器事件:更新雷达角度并触发重绘
private void RadarRotateTimer_Tick(object sender, EventArgs e)
{
    // 每次增加0.05弧度(约2.86度),控制旋转速度
    _currentStartAngle += 0.05;
    if (_currentStartAngle >= 2 * Math.PI)
        _currentStartAngle -= 2 * Math.PI;
    
    // 触发PictureBox重绘
    pictureBox1.Invalidate();
}

// PictureBox的Paint事件:绘制雷达扇形+标记差异像素
private void PictureBox1_Paint(object sender, PaintEventArgs e)
{
    // 先绘制当前雷达背景帧(替换成你的实际帧对象)
    e.Graphics.DrawImage(currFrame, 0, 0);
    
    // 绘制半透明的雷达扇形
    using (Brush sectorBrush = new SolidBrush(Color.FromArgb(100, Color.DodgerBlue)))
    {
        e.Graphics.FillPie(sectorBrush,
            _radarCenter.X - pictureBox1.Width / 2,
            _radarCenter.Y - pictureBox1.Height / 2,
            pictureBox1.Width, pictureBox1.Height,
            (float)(_currentStartAngle * 180 / Math.PI), // 转成角度
            (float)(_sectorWidth * 180 / Math.PI));
    }
    
    // 仅标记当前扇形内的差异像素为黄色
    foreach (Point pixel in _differencePixels)
    {
        if (IsPixelInSector(pixel))
        {
            e.Graphics.FillRectangle(Brushes.Yellow, pixel.X, pixel.Y, 1, 1);
        }
    }
}

4. 调整差异计算的触发时机

删掉构造函数中对CalcDifference的调用,改成在新帧到来时触发(比如你获取雷达新帧的定时器事件中):

// 示例:获取新雷达帧的定时器
private void FrameUpdateTimer_Tick(object sender, EventArgs e)
{
    Bitmap prevFrame = currFrame;
    currFrame = GetNewRadarFrame(); // 替换成你获取新帧的实际方法
    
    if (prevFrame != null)
    {
        CalcDifference(prevFrame, currFrame);
    }
}

内容的提问来源于stack exchange,提问作者Daniel Lip

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 12:20:40