【问题标题】:Is there a better way to handle image click regions?有没有更好的方法来处理图像点击区域?
【发布时间】:2017-01-10 18:33:02
【问题描述】:

我有一张图片,您点击了 2 个点,它会在每个点之间创建一条线。最后,该部门要求的是能够计算这些线条的长度以及这些线条出现的位置。他们目前正在使用纸/笔/尺子手工进行此操作。这是我正在使用的图像之一。

中间的那些裂缝被认为是“区域 7”。

所以我需要一种方法,除了保存我的 x 和 y 位置以便稍后测量线条之外,还将它们出现的位置添加到我的列表中。以下是我知道这样做的唯一方法,但事实证明它更加混乱。因为图片不是一个精确的正方形或矩形,所以有很多重叠区域和很多有空隙的区域,这些区域没有被很好地覆盖。

有没有更好的方法来做到这一点? (目前我只是使用一个消息框来显示我点击的位置,在我做对之前,我还没有对数据做任何事情。)

    if (e.Button.Equals(MouseButtons.Left))
    {
        Rectangle zone1 = new Rectangle(35, 30, 770, 30);
        if (zone1.Contains(e.Location))
        {
            MessageBox.Show("Zone1");                  
        }
        Rectangle zone2 = new Rectangle(890, 40, 330, 300);
        if (zone2.Contains(e.Location))
        {
            MessageBox.Show("Zone2");
        }
        Rectangle zone3 = new Rectangle(340, 340, 850, 60);
        if (zone3.Contains(e.Location))
        {
            MessageBox.Show("Zone3");
        }
        Rectangle zone4 = new Rectangle(100, 25, 75, 300);
        if (zone4.Contains(e.Location))
        {
            MessageBox.Show("Zone4");
        }
        //4-1 trying to cover areas missed in zone4
        Rectangle zone41 = new Rectangle(255, 270, 120, 240);
        if (zone41.Contains(e.Location))
        {
            MessageBox.Show("Zone4-1");
        }
        Rectangle zone5 = new Rectangle(310, 100, 180, 150);
        if (zone5.Contains(e.Location))
        {
            MessageBox.Show("Zone5");
        }
        //5-1 trying to cover areas missed in zone5
        Rectangle zone51 = new Rectangle(220, 80, 60, 45);
        if (zone51.Contains(e.Location))
        {
            MessageBox.Show("Zone5-1");
        }
        Rectangle zone6 = new Rectangle(635, 35, 250, 210);
        if (zone6.Contains(e.Location))
        {
            MessageBox.Show("Zone6");
        }
    }

【问题讨论】:

  • 图像是从您可以访问的矢量数据生成的,还是您本质上希望进行特征识别?如果是后者,这是一次性的事情,还是需要自动化?如果它是一次性的,您可以手动为每个区域生成图像(例如,为相应图像填充黑色的每个区域)并按像素测试用户单击的位置是否在该区域中。答案很大程度上取决于您的限制。
  • Re: 标题中包含“C#”,其实我还以为不被接受。但也许“规则”已经改变了。
  • “根据要求编辑此内容以在标题中包含 C#” - 这很奇怪,因为 general consensus is that tags should not be included in titles
  • 几年前绘制的图像(可能在 MS Paint 中)代表他们在熔炉中钎焊的部分。然后他们只是打印出大量的页面。没有正确钎焊在一起的零件上的任何“空隙”都会在纸上画一条线。所以每个人在他们上交的一天结束时可能有 10 多页。所以他们将在图像上创建这些行,提交到 SQL 服务器上的一个表,然后重置并为下一部分开始一个新图像。希望对大家有所帮助。
  • @adv12 我不知道,这是我帖子上的编辑请求,建议我进行更改。

标签: c# image picturebox


【解决方案1】:

我的建议是使用背景图片作为区域地图。该图像根本不会显示给用户。您加载一次并将其保存在内存中,但继续显示您的原始图像并像往常一样在其上绘制线条。然后,当用户单击您的图像时,您检查区域图的颜色以确定区域。

例如,假设我使用这两个图像作为我的显示和我的区域地图:

两个图像都在您的代码中加载,但只有显示地图显示给用户:

class MyForm
{
    Bitmap zoneDisplay;
    Bitmap zoneMap;

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        zoneDisplay = (Bitmap)Image.FromFile(@"c:\temp\zonedisp.png"); // replace with actual path to file
        zoneMap = (Bitmap)Image.FromFile(@"c:\temp\zonemap.png");

        // put the display image into the picturebox (or whatever control displays it)
        pictureBox.Image = zoneDisplay;
    }

然后,当用户点击您的图片时,只需检查区域图上的颜色即可:

private void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
    var color = _zoneMap.GetPixel(e.X, e.Y);
    if (color == Color.FromArgb(0, 0, 255))
        MessageBox.Show("Zone 1");
    else if (color == Color.FromArgb(255, 0, 0))
        MessageBox.Show("Zone 2");
    else if (color == Color.FromArgb(0, 255, 0))
        MessageBox.Show("Zone 3");
    // etc...
}

如果您的颜色略有偏差,那么您可能需要进行不太精确的比较。示例:

static int ColorDelta(Color c1, Color c2)
{
    return Math.Abs(c1.R - c2.R) + Math.Abs(c1.G - c2.G) - Math.Abs(c1.B - c2.B);
}

private void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
    var color = _zoneMap.GetPixel(e.X, e.Y);
    if (90 > ColorDelta(color, Color.FromArgb(0, 0, 255)))
        MessageBox.Show("Zone 1");
    else if (90 > ColorDelta(color, Color.FromArgb(255, 0, 0)))
        MessageBox.Show("Zone 2");
    else if (90 > ColorDelta(color, Color.FromArgb(0, 255, 0)))
        MessageBox.Show("Zone 3");
    // etc...
}

【讨论】:

  • 听起来不错。让我在我离开办公室的时间里稍微处理一下,我会回复的。
  • 哦,如果不是很明显,您应该使用无损图像格式,例如 BMP 或 PNG。不要将 JPG 用于您的区域地图,因为它会扭曲颜色。
  • 我正在使用 PNG。我打开了我的图像的 2 个副本。我使用简单的 RGB 颜色在油漆中手动为区域着色,(红色、绿色、蓝色..等)使用上面的代码将它们加载到鼠标中,但它似乎不起作用。只是在我的图像映射区域中着色不是正确的方法吗?我是这种方法的新手,但我看不出它在哪里比较这两张图片?
  • 听起来你做得对。也许你的 RGB 值有一点偏差?您是否使用 Paint 中的 Edit Colors 窗口仔细检查了确切的值?调用 GetPixel 时会得到什么颜色?
  • 看起来像红色例如在 Paint 中正确显示 0,0,255。好的,这就是我有点困惑的地方。我在GetPixel 上停下来,然后点击显示的图像,我知道隐藏地图上存在红色,这就是"{Name=ffed1c24, ARGB=(255, 237, 28, 36)}"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-01
  • 2013-01-01
  • 2012-02-01
  • 2013-11-09
  • 1970-01-01
相关资源
最近更新 更多