实施GOTO声明

时间:2016-08-21 21:45:15

标签: c# image-processing

对于我的离线签名验证项目,我使用欧拉数作为拓扑特征。

我浏览了这个link,我发现了一个伪代码,我的c#实现如下:

public void eulers(bool[][] t)
{
    int w2 = 0;
    int wc = 0;
    int eulers_number = 0;
    int x = 2;
    int y = 2;

    while (y <= t.Length)
    {
        while (x <= t.Length)
        {
            bool p1 = t[x][y];
            bool p2 = t[x - 1][y];
            bool p3 = t[x][y - 1];
            bool p4 = t[x - 1][y - 1];
            if (p4 == true)
            {
                x++;
            }
            else if (p2 == false)
            {
            labelA:
                if (p3 == true)
                {
                    x = x + 2;
                }
                else if (p1 == false)
                {
                    x++;
                    if (x <= t.Length)
                    {
                        goto labelA;
                        break;
                    }
                }
                else
                {
                    w2++;
                    x++;
                    if (x <= t.Length)
                    {
                        goto labelB;
                        break;
                    }

                }
            }
            else
            {
            labelB:
                if (p3 == true)
                {
                    wc++;
                    x = x + 2;
                }
                else if (p1 == false)
                {
                    x++;
                    if (x <= t.Length)
                    {
                        goto labelA;
                        break;
                    }
                }
                else
                {
                    x++;
                    if (x <= t.Length)
                    {
                        goto labelB;
                        break;
                    }
                }
            }
        }
        eulers_number = w2 - wc;
        MessageBox.Show(eulers_number.ToString());
    }

在编译时,labelAlabelB超出了范围。我知道不可能以这种风格使用,所以我试图修改代码,但我被困在这里。如何使此代码正常工作?

1 个答案:

答案 0 :(得分:0)

以下是我认为您尝试翻译论文的伪代码的工作版本:

static int eulers(bool[,] pixel)
{
    int w2 = 0;
    int wc = 0;
    int x = 1;
    int y = 1;
    int M = pixel.GetLength(0), N = pixel.GetLength(1);

    while (y < N)
    {
        while (x < M)
        {
            if (pixel[x - 1, y - 1])
            {
                x++;
            }
            else
            {
                bool labelA = !pixel[x - 1, y];

                while (true)
                {
                    if (pixel[x, y - 1])
                    {
                        if (!labelA)
                        {
                            wc++;
                        }
                        x = x + 2;
                    }
                    else if (!pixel[x, y])
                    {
                        x++;
                        if (x < N)
                        {
                            labelA = true;
                            continue;
                        }
                    }
                    else
                    {
                        if (labelA)
                        {
                            w2++;
                        }
                        x++;
                        if (x < N)
                        {
                            labelA = false;
                            continue;
                        }
                    }
                    break;
                }
            }
        }

        y++;
    }

    return w2 - wc;
}

在解决goto语句方面,我通过创建一个小型状态机(具有单个切换状态,由labelA变量表示)并使用while来删除它们而是循环以允许执行流程返回到块的开头。此步骤的一个重要部分是认识到labelA:labelB:代码块几乎完全相同,但wcw2变量是否已更新为那个有效的迭代只是一个循环。

现在,那就是说,你的代码还有其他几个关键缺陷:

  • 对于xy值,伪代码假设像素坐标值范围从1到M,1到N,包括在内。但是C#数组是从0开始的,因此需要相应地调整xy值。它们需要从1开始而不是2开始,并且不需要允许它们达到M和N,而是限制为小于这些值。
  • 您的代码使用"jagged array"。这本身并不是错误的,除了您也无法正确确定Y坐标的实际边界,而是使用与X坐标相同的值(即您使用t.Length而不是t[x].Length) 。对于这种类型的算法,锯齿状数组效率低下并且难以使用,因此我继续将其更改为普通的二维数组。
  • 在您的代码中,您将当前变量中当前xy值的四个像素的值存储起来。但是,更改x值后,您无法更新这些值。因此,goto实现的循环的后续迭代将使用错误的像素值。我删除了局部变量,并将代码更改为只需在需要时使用当前xy值直接检索像素值。实际上,在这个版本的代码中,每个特定的像素在代码中只有一个位置被检索到,因此局部变量无论如何都不会添加任何东西,即使以这种方式存储值是正确的。
  • 离开内部循环后,您未能增加y值。

我还清理了一些代码,删除了多余的break语句(在goto语句之后删除了它们),删除了bool比较,而不是仅使用{直接{1}}表达式值,并更改方法以返回最终值而不是尝试显示它(调用者可以这样做......像这样的数学助手函数也不应该负责提供用户交互)。

如果没有您的样本数据和预期输出,我无法确认翻译是否正确。我可以保证的是,这个版本比你开始时更接近纸张的正确翻译,当然是有效的,可编译的C#代码。 :)