关于图像分割Snake算法(c#)的一些不解之惑,望大神指点

我手头有一个别人的代码,是winform程序,其中包含了两个类,分别是FormSnake.cs和SnakeSharp.cs在FormSnake类中的鼠标事件里,用了一个动态数组presetContour来记录鼠标每次每次停留位置的坐标,在SnakeSarp中也定义一个数组snakePoints,我的问题是:presetContour里面是肯定有数据的,而snakePoints是怎么得到这些数据的。我把两个类的代码都放上来,请明白的前辈指点一下。

+++++++++++FrmSnake.cs++++++++++++++
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace SnakeSharp
{
public partial class FormSnake : Form
{
public FormSnake()
{
InitializeComponent();
}
Graphics graphics = null;
Image curImage = null;
Bitmap oriImage = null;
Point imageOrignal = new Point(0, 0);
List presetContour = null;
SnakeSharp snakeSharp = null;

    private void panelBMP_Paint(object sender, PaintEventArgs e)
    {
        try
        {
            SplitterPanel pnl = sender as SplitterPanel;
            if (pnl == null)
            {
                return;
            }
            if (curImage == null)
            {
                return;
            }
            e.Graphics.DrawImage(curImage, imageOrignal);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    private void FormSnake_Load(object sender, EventArgs e)
    {
        buttonClear.Enabled = false;
        buttonSetContour.Enabled = false;
        buttonStart.Enabled = false;
        //buttonStop.Enabled = false;
        //buttonStep.Enabled = false;
    }

    private void buttonClear_Click(object sender, EventArgs e)
    {
        curImage = null;
        buttonClear.Enabled = true;
        buttonSetContour.Enabled = true;
        buttonStart.Enabled = true;
        //buttonStop.Enabled = false;
        //buttonStep.Enabled = false;
       // buttonLoadImage.Enabled = true;
        imageOrignal = new Point(0, 0);                                                                         
        presetContour = null;
        mainContainer.Panel1.Refresh();
    }
    bool isDrawingContour = false;
    bool isMouseDown = false;
    private void buttonSetContour_Click(object sender, EventArgs e)
    {
        isDrawingContour = true;
        buttonSetContour.Enabled = true;
        buttonStart.Enabled = true;
        presetContour = new List<Point>();
        snakeSharp = SnakeSharp.FromImage(oriImage);

        curImage = new Bitmap(snakeSharp.CachedImage);
        mainContainer.Panel1.Refresh();
    }
    private void splitContainer1_Panel1_MouseDown(object sender, MouseEventArgs e)
    {
        if (!isDrawingContour)
        {
            return;
        }
        else
        {
            isMouseDown = true;
        }
    }

    private void splitContainer1_Panel1_MouseUp(object sender, MouseEventArgs e)
    {

        if (isMouseDown)
        {

            isDrawingContour = false;
            isMouseDown = false;
            buttonSetContour.Enabled = true;
            buttonStart.Enabled = true;
            //buttonStep.Enabled = true; 
            graphics = Graphics.FromImage(curImage);
            Pen p = new Pen(Color.Green);
            if (presetContour.Count > 1)
            {
                graphics.DrawLine(p, presetContour[0], presetContour[presetContour.Count - 1]);
            }
            graphics.Save();
            mainContainer.Panel1.Refresh();
            textBoxInfo.AppendText("\r\n边界设定完毕,共设定" + presetContour.Count + "个点。");
            if (snakeSharp != null)
            {
                snakeSharp.SetCurcePoints(presetContour);
            }
        }
    }
    long mouseTick = 0;
    private void splitContainer1_Panel1_MouseMove(object sender, MouseEventArgs e)
    {

        if (isMouseDown && isDrawingContour)
        {
            long ticks = DateTime.Now.Ticks;

            if ((ticks - mouseTick) < 100 * 10000)
            {
                return;
            }

            mouseTick = ticks;
            Rectangle imageRec = new Rectangle(imageOrignal, curImage.Size);
            if (imageRec.Contains(e.Location))
            {
                Point pt = new Point(e.Location.X - imageOrignal.X, e.Location.Y - imageRec.Y);
                presetContour.Add(pt);

                graphics = Graphics.FromImage(curImage);
                Pen p = new Pen(Color.Green);
                graphics.DrawRectangle(p, pt.X-1, pt.Y-1, 3, 3);
                if (presetContour.Count > 1)
                {
                    graphics.DrawLine(p, presetContour[presetContour.Count - 2], presetContour[presetContour.Count - 1]);
                }
                graphics.Save();
                mainContainer.Panel1.Refresh();
            }
        }
    }

    private void buttonStart_Click(object sender, EventArgs e)
    {
        buttonStart.Enabled = false;
        buttonSetContour.Enabled = false;
        buttonClear.Enabled = false;
        //buttonStop.Enabled = true;
        //buttonStep.Enabled = false;
        isRunning = true;
        try
        {
           // snakeSharp.CurvatureThreshold = double.Parse(textBoxCurvatureThreshold.Text);
           // snakeSharp.GradientThreshold = byte.Parse(textBoxGradientThreshold.Text);
           // snakeSharp.PointsMovedThreshold = Int32.Parse(textBoxPtsmovedThreshold.Text);
           // snakeSharp.WillRemoveDead = checkBoxRemoveDeadpoint.Checked;
            backgroundWorker.RunWorkerAsync();//当执行BackgroundWorker.RunWorkerAsync方法时会触发DoWork该事件,并且传递DoWorkEventArgs参数
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    //private void buttonStop_Click(object sender, EventArgs e)
    //{

    //    backgroundWorker.CancelAsync();
  //  }

   // private void buttonStep_Click(object sender, EventArgs e)//单步运行
    //{
      //  try
        //{
          //  int steps = (int)numericSteps.Value;
            //snakeSharp.CurvatureThreshold = double.Parse(textBoxCurvatureThreshold.Text);
            //snakeSharp.GradientThreshold = byte.Parse(textBoxGradientThreshold.Text);
            //snakeSharp.PointsMovedThreshold = Int32.Parse(textBoxPtsmovedThreshold.Text);
            //snakeSharp.WillRemoveDead = checkBoxRemoveDeadpoint.Checked;
            //int ptsMoved = 0;
            //while (steps > 0)
            //{
              //  ptsMoved = snakeSharp.RunSnake();
                //textBoxInfo.AppendText("\r\n移动了" + ptsMoved + "个点。");
                //steps--;
            //}
            //curImage = new Bitmap(snakeSharp.CachedImage);
            //graphics = Graphics.FromImage(curImage);
            //Pen p = new Pen(Color.Green);


            //if (snakeSharp.SnakePoints.Length > 0)
            //{
              //  CurvePoint[] snakePoints = snakeSharp.SnakePoints;
               // foreach (CurvePoint pt in snakePoints)
                //{
                  //  graphics.DrawRectangle(p, pt.X-1, pt.Y-1, 3, 3);

                //}
               // for (int i = 0; i < snakePoints.Length; i++)
                //{
                  //  graphics.DrawLine(p, snakePoints[i].Pos, snakePoints[(i + 1)%snakePoints.Length].Pos);
                //}
            //}
            //graphics.Save();
            //mainContainer.Panel1.Refresh();
        //}
        //catch (Exception ex)
        //{
          //  MessageBox.Show(ex.Message);
        //}
    //}

    public bool isRunning { get; set; }

    private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker bgWorker = sender as BackgroundWorker;
        if (bgWorker == null)
        {
            return;
        }
        int ptsMoved = 0;
        while (!bgWorker.CancellationPending)
        {
            long ticks = DateTime.Now.Ticks;
            long currentTicks = DateTime.Now.Ticks;
            long interval = 500 * 10000;
            do
            {
                ptsMoved = snakeSharp.RunSnake();

                currentTicks = DateTime.Now.Ticks;
            } while (currentTicks - ticks < interval && ptsMoved > snakeSharp.PointsMovedThreshold);
            WorkState state = new WorkState();
            state.Points = new List<CurvePoint>();
            foreach (CurvePoint pt in snakeSharp.SnakePoints)
            {
                state.Points.Add(pt);
            }
            bgWorker.ReportProgress(10, state);//触发ProgressChanged事件

            if (ptsMoved <= snakeSharp.PointsMovedThreshold)
            {
                return;
            }
        }
    }

    private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        BackgroundWorker bgWorker = sender as BackgroundWorker;
        if (bgWorker == null)
        {
            return;
        }
        WorkState state = e.UserState as WorkState;
        if (state == null)
        {
            return;
        }
        curImage = new Bitmap(snakeSharp.CachedImage);
        graphics = Graphics.FromImage(curImage);
        Pen p = new Pen(Color.Green);
        if (state.Points.Count > 0)
        {

            foreach (CurvePoint pt in state.Points)
            {
                graphics.DrawRectangle(p, pt.X-1, pt.Y-1, 3, 3);
            }
            for (int i = 0; i < state.Points.Count ; i++)
            {
                graphics.DrawLine(p, state.Points[i].Pos, state.Points[(i + 1)%state.Points.Count].Pos);
            }
        }
        graphics.Save();
        mainContainer.Panel1.Refresh();
    }

    private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        //buttonStop.Enabled = false;
        buttonStart.Enabled = true;
        buttonSetContour.Enabled = true;
        buttonClear.Enabled = true;
        //buttonStep.Enabled = true;
        isRunning = false;
        textBoxInfo.AppendText("\r\n异步处理完毕");
    }

    private void textBoxPtsmovedThreshold_KeyPress(object sender, KeyPressEventArgs e)
    {
        int key = e.KeyChar;
        if ((key < 0x30 || key > 0x39) &&
            key != 0x08 /*&&  key != 46*/)
        {
            e.Handled = true;
        }
    }

    private void textBoxCurvatureThreshold_KeyPress(object sender, KeyPressEventArgs e)
    {
        int key = e.KeyChar;
        e.Handled = false;
        if ((key < 0x30 || key > 0x39) &&
            key != 0x08 && key != 46)
        {
            e.Handled = true;
            return;
        }
        if (key != 46)
        {
            return;
        }
     //   if (textBoxCurvatureThreshold.Text.Length <= 0)
      //  {
     //       e.Handled = true;
       //     return;
    //    }
      //  else
      //  {
          //  float f = 0.0f;
           // String newStr = textBoxCurvatureThreshold.Text + e.KeyChar;
           // bool b = float.TryParse(newStr, out f);
          //  e.Handled = !b;
      //  }
    }

    private void textBoxCurvatureThreshold_KeyUp(object sender, KeyEventArgs e)
    {

    }

    private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)//复选框
    {
        //获取被选项目
        MyComboItem item = comboBox1.SelectedItem as MyComboItem;
        //执行操作

        if (comboBox1.SelectedItem.ToString() == "导入图片")
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.DefaultExt = ".bmp";
            ofd.Filter = "Image Files(*.bmp,*.jpg,*.png)|*.bmp;*.jpg;*.png||";
            if (DialogResult.OK != ofd.ShowDialog(this))
            {
                return;
            }
            Image tmpImage = Image.FromFile(ofd.FileName);
            textBoxInfo.AppendText("\r\n图片加载成功(" + ofd.FileName + ")");
            textBoxInfo.AppendText("\r\n图片大小:" + tmpImage.Width.ToString() + "X" + tmpImage.Height.ToString());
            Size clientSize = mainContainer.Panel1.ClientSize;
            Size newImageSize = new Size(tmpImage.Width, tmpImage.Height);
            if (tmpImage.Width > clientSize.Width || tmpImage.Height > clientSize.Height)
            {
                double rImage = tmpImage.Width * 1.0 / tmpImage.Height;
                double rWnd = clientSize.Width * 1.0 / clientSize.Height;
                if (rImage < rWnd) // image more high
                {
                    newImageSize.Height = clientSize.Height;
                    newImageSize.Width = (int)(newImageSize.Height * rImage);
                }
                else //image is more wide
                {

                    newImageSize.Width = clientSize.Width;
                    newImageSize.Height = (int)(newImageSize.Width / rImage);
                }
            }

            textBoxInfo.AppendText("\r\n调整图片大小为:" + newImageSize.Width + "X" + newImageSize.Height);
            oriImage = new Bitmap(tmpImage, newImageSize);
            snakeSharp = SnakeSharp.FromImage(oriImage);
            Bitmap bmpTmp = new Bitmap(newImageSize.Width, newImageSize.Height);
            for (int i = 0; i < newImageSize.Height; i++)
            {
                for (int j = 0; j < newImageSize.Width; j++)
                {
                    int val = (int)snakeSharp.ImageData[j, i];
                    if (val > 255) val = 255;
                    if (val < 0) val = 0;
                    bmpTmp.SetPixel(j, i, Color.FromArgb(val, val, val));
                }
            }
            curImage = new Bitmap(bmpTmp, newImageSize);
            imageOrignal = new Point((clientSize.Width - curImage.Width) / 2, (clientSize.Height - curImage.Height) / 2);

            mainContainer.Panel1.Refresh();
            buttonClear.Enabled = true;
            //buttonLoadImage.Enabled = true;
            buttonSetContour.Enabled = true;
        }
        else
        {
            ChildForm1 cf = new ChildForm1();
            cf.Show();
        }
    }
}
public class WorkState
{
    List<CurvePoint> points;
    public List<CurvePoint> Points
    {
        get { return points; }
        set { points = value; }
    }
}

}

+++++++++++++SnakeSharp.cs++++++++++++++++++++++
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;

namespace SnakeSharp
{
///
/// 梯度
///
public class Grad
{
public Grad()
{
ix = 0.0;
iy = 0.0;
g = 0.0;
}
public Grad(double i_x, double i_y)
{
ix = i_x;
iy = i_y;
g = Math.Sqrt(ix * ix + iy * iy);
}
double ix = 0.0;
public double Ix
{
get { return ix; }
set { ix = value; }
}
double iy = 0.0;
public double Iy
{
get { return iy; }
set { iy = value; }
}
double g = 0.0;
public double G
{
get { return g; }
set { g = value; }
}
}
///
/// 偏移量 用于表示像素的相对关系
///
public class Offset
{

    public Offset(int x, int y)
    {
        // TODO: Complete member initialization
        X = x;
        Y = y;
    }
    public Offset()
    {
        // TODO: Complete member initialization
        X = 0;
        Y = 0;
    }
    public int X { get; set; }
    public int Y { get; set; }
}
public class CurvePoint
{
    Point pos;
    public Point Pos
    {
        get { return pos; }
        set { pos = value; }
    }
    public int X
    {
        get { return pos.X; }
        set { pos.X = value; }
    }
    public int Y
    {
        get { return pos.Y; }
        set { pos.Y = value; }
    }
    double curvature;
    public double Curvature
    {
        get { return curvature; }
        set { curvature = value; }
    }
    double alpha;
    public double Alpha
    {
        get { return alpha; }
        set { alpha = value; }
    }
    double beta;
    public double Beta
    {
        get { return beta; }
        set { beta = value; }
    }
    double gama;
    public double Gama
    {
        get { return gama; }
        set { gama = value; }
    }
    public CurvePoint( Point pt)
    {
        pos = pt;
        alpha = 1.0;
        beta = 5.0;
        gama = 1.2;
        curvature = 0.0;
    }
    public CurvePoint()
    {
        pos = new Point(0,0);
        alpha = 1.0;
        beta = 5.0;
        gama = 1.2;
        curvature = 0.0;
    }
    public CurvePoint(Point pt,double a, double b,double r, double c)
    {
        pos = pt;
        alpha = a;
        beta = b;
        gama = r;
        curvature = c;
    }
}
/// <summary>
/// 
/// </summary>
public class SnakeSharp
{
    private static SnakeSharp _instance = null;
    /// <summary>
    /// 图像高度
    /// </summary>
    int lHeight;
    public int Height
    {
        get { return lHeight; }
        set { lHeight = value; }
    }
    int lWidth;
    /// <summary>
    /// 图像宽度
    /// </summary>
    public int Width
    {
        get { return lWidth; }
        set { lWidth = value; }
    }
    double[,] imageData = null;

    /// <summary>
    /// 图像数据,灰度值
    /// </summary>
    public double[,] ImageData
    {
        get { return imageData; }
        set { imageData = value; }
    }
    bool willRemoveDead = false;
    public bool WillRemoveDead
    {
        get { return willRemoveDead; }
        set { willRemoveDead = value; }
    }
    /// <summary>
    /// 每点的梯度值
    /// </summary>
    Grad[,] gradient = null;
    public Grad[,] GradientMatrix
    {
        get { return gradient; }
        set { gradient = value; }
    }
    CurvePoint[] snakePoints;
    public CurvePoint[] SnakePoints
    {
        get { return snakePoints; }
        set { snakePoints = value; }
    }
    //定义参数

// double[] alpha = null;
// double[] beta = null;
// double[] gamma = null;
// double[] curvature = null;
double threshold_curvature = 0.2;//曲率阈值
public double CurvatureThreshold
{
get { return threshold_curvature; }
set { threshold_curvature = value; }
}
byte threshold_grad = 100;//梯度阈值
public byte GradientThreshold
{
get { return threshold_grad; }
set { threshold_grad = value; }
}
int pointsMovedThreshold = 10;
public int PointsMovedThreshold
{
get { return pointsMovedThreshold; }
set { pointsMovedThreshold = value; }
}
public int SnakePointsCount
{
get { return snakePoints.Length; }
}
Bitmap cachedImage;
public System.Drawing.Bitmap CachedImage
{
get { return cachedImage; }
set { cachedImage = value; }
}
public void SetCurcePoints(List pos)
{

        //定义参数
        snakePoints = new CurvePoint[pos.Count];
        for (int i = 0; i < pos.Count;i++ )
        {
            snakePoints[i] = new CurvePoint(pos[i]);
        }

        threshold_curvature = 0.2;//曲率阈值
        threshold_grad = 100;//梯度阈值
        pointsMovedThreshold = SnakePointsCount / 10;

    }
    public static SnakeSharp FromImage(String imageFile)
    {
        throw new  NotImplementedException();

    }
    SnakeSharp()
    {

    }

    private void removeInvalidPoints()
    {
        List<CurvePoint> ptIndex = new List<CurvePoint>();
        for (int i = 0; i < SnakePoints.Length;i++ )
        {
            CurvePoint pt = SnakePoints[i];
            if (pt.Pos.X < 0 || pt.Pos.X >= Width || pt.Pos.Y < 0 || pt.Pos.Y >= Height)
            {
                continue;
            }
            ptIndex.Add(pt);
        }
        snakePoints = new CurvePoint[ptIndex.Count];
        Array.Copy(ptIndex.ToArray(), snakePoints, ptIndex.Count);
    }
    public static SnakeSharp FromImage(Image image)
    {
        try
        {
            _instance = new SnakeSharp();
            Bitmap oriImage = new Bitmap(image);
            _instance.Initialize(oriImage);
        }
        catch (Exception)
        {
            throw;
        }
        return _instance;

    }
    void Initialize(Bitmap oriImage)
    {
        try
        {

            Height = oriImage.Height;
            Width = oriImage.Width;
            ImageData = new double[_instance.Width , _instance.Height];
            Color pixColor = Color.FromArgb(0);
            for (int y = 0; y < Height; y++)
            {
                for (int x = 0; x < Width; x++)
                {
                    pixColor = oriImage.GetPixel(x, y);
                    ImageData[x,y] = pixColor.R * 0.3 + pixColor.G * 0.59 + pixColor.B * 0.11;
                }
            }

            Gauss();
            Gradient();
            cachedImage = new Bitmap(Width, Height);
            for (int iy = 0; iy < Height; iy++)
            {
                for (int jx = 0; jx < Width; jx++)
                {
                    int val = (int)ImageData[jx, iy];
                    if (val > 255) val = 255;
                    if (val < 0) val = 0;
                    cachedImage.SetPixel(jx, iy, Color.FromArgb(val, val, val));
                }
            }

        }
        catch (Exception)
        {

            throw;
        }
    }

    /// <summary>
    /// Snake轮廓检测主要算法
    /// </summary>

    public int RunSnake()//梯度幅度//梯度阈值
    {
        int i, m, n;
        double max_curvature = -100000000.0;
        double avg_distance = 0;
        int ptsMoved = 0;

        //统计输入点的平均距离
        for (i = 0; i < SnakePointsCount; i++)
        {
            Point p_1 = new Point(SnakePoints[i].Pos.X, SnakePoints[i].Pos.Y);
            Point p_2 = new Point(SnakePoints[(i + 1) % SnakePointsCount].Pos.X,
                SnakePoints[(i + 1) % SnakePointsCount].Pos.Y);
            avg_distance += Math.Sqrt((double)((p_1.X - p_2.X) * (p_1.X - p_2.X) + (p_1.Y - p_2.Y) * (p_1.Y - p_2.Y)));//距离总和
        }
        avg_distance = avg_distance / SnakePointsCount;//平均距离

        //==========================================================================================
        //根据曲率能量改变Snake轮廓上的点
        for (i = 0; i < SnakePointsCount; i++)
        {
            //统计Snake曲线上某点3邻域内能量,将Snake曲线上相应点移动到能量最小的点
            Point p = new Point();
            Point min_point = new Point();
            double max_curvature33, max_continuity33, max_internal33, min_internal33, min_energy33, energy33;
            double[,] curvatures = new double[3, 3];
            double[,] continuities = new double[3, 3];
            double[,] internal_energies = new double[3, 3];
            max_curvature33 = max_continuity33 = max_internal33 = -1000000000000.0;//随便设置一个极小数,便于更新数据
            min_internal33 = 1000000000000.0;//随便设置一个极大初值,便于更新最小内部能量
            //in the 3×3 template
            for (m = -1; m <= 1; m++)
            {
                p.Y = SnakePoints[i].Pos.Y + m;
                if (p.Y < 0)
                    p.Y = 0;
                if (p.Y >= Height)//if exceed the image range 
                    p.Y = Height - 1;

                for (n = -1; n <= 1; n++)
                {
                    p.X = SnakePoints[i].Pos.X + n;
                    if (p.X < 0)//判断是否超出图像的范围
                        p.X = 0;
                    if (p.X >= Width)
                        p.X = Width - 1;

                    Point p_1 = new Point(SnakePoints[(i - 1 + SnakePointsCount) % SnakePointsCount].Pos.X,
                        SnakePoints[(i - 1 + SnakePointsCount) % SnakePointsCount].Pos.Y);
                    Point p_2 = new Point(SnakePoints[(i + 1) % SnakePointsCount].Pos.X,
                        SnakePoints[(i + 1) % SnakePointsCount].Pos.Y);

                    curvatures[m + 1, n + 1] = (p_1.X + p_2.X - 2 * p.X) * (p_1.X + p_2.X - 2 * p.X) + //二阶导数,计算曲率项能量,cause problem near
                                            (p_1.Y + p_2.Y - 2 * p.Y) * (p_1.Y + p_2.Y - 2 * p.Y);

                    continuities[m + 1, n + 1] = Math.Pow(avg_distance - Math.Sqrt((double)((p.X - p_1.X) * (p.X - p_1.X) + (p.Y - p_1.Y) * (p.Y - p_1.Y))), 2);//一阶导数,式子中第一项,控制图像边缘
                    internal_energies[m + 1, n + 1] = gradient[p.X,p.Y].G;//(double)GradMagnitude[p.X + p.Y * Width];//该点梯度,
                    max_curvature33 = Math.Max(max_curvature33, curvatures[m + 1, n + 1]);//最大曲率
                    max_continuity33 = Math.Max(max_continuity33, continuities[m + 1, n + 1]);//最大连续性
                    max_internal33 = Math.Max(max_internal33, internal_energies[m + 1, n + 1]);//最大image force
                    min_internal33 = Math.Min(min_internal33, internal_energies[m + 1, n + 1]);//最小image force
                }
            }
            if (max_internal33 - min_internal33 < 3)
            {
                min_internal33 = max_internal33 - 3;
            }
            //归一化能量
            for (m = 0; m <= 2; m++)
            {
                for (n = 0; n <= 2; n++)
                {
                    curvatures[m, n] = curvatures[m, n] / max_curvature33;
                    continuities[m, n] = continuities[m, n] / max_continuity33;

                    internal_energies[m, n] = (internal_energies[m, n]-min_internal33) / (max_internal33 - min_internal33);
                }
            }

            //========================================================================================
            //计算三部分能量之和
            min_point.X = -1;
            min_point.Y = -1;
            min_energy33 = 1000000000000.0;//初始化一个最小能量值
            for (m = -1; m <= 1; m++)
            {
                for (n = -1; n <= 1; n++)
                {
                    energy33 = snakePoints[i].Alpha * continuities[m + 1, n + 1] +
                        snakePoints[i].Beta * curvatures[m + 1, n + 1] -
                        snakePoints[i].Gama * internal_energies[m + 1, n + 1];//三部分能量之和
                    if (energy33 < min_energy33 || (energy33 == min_energy33 && m == 0 && n == 0))
                    {
                        min_energy33 = energy33;
                        min_point.X = n;
                        min_point.Y = m;
                    }
                }
            }

            min_point.X = min_point.X + SnakePoints[i].Pos.X;
            min_point.Y = min_point.Y + SnakePoints[i].Pos.Y;
            //================================================================================================================
            //min_point与当前点以及它的前后两点不重合,更新当前点  


            if ((min_point.X != SnakePoints[i].Pos.X || min_point.Y != SnakePoints[i].Pos.Y) &&
                (min_point.X != SnakePoints[(i - 1 + SnakePointsCount) % SnakePointsCount].Pos.X || min_point.Y != SnakePoints[(i - 1 + SnakePointsCount) % SnakePointsCount].Pos.Y) &&
                (min_point.X != SnakePoints[(i + 1) % SnakePointsCount].Pos.X || min_point.Y != SnakePoints[(i + 1) % SnakePointsCount].Pos.Y))
            {
                SnakePoints[i].X = min_point.X;
                SnakePoints[i].Y = min_point.Y;
                ptsMoved++;
            }
            //==============================================================================================================
            // Process determines where to allow cornersin the next iteration,参考伪代码
            Point p1 = new Point(SnakePoints[(i - 1 + SnakePointsCount) % SnakePointsCount].X,
                SnakePoints[(i - 1 + SnakePointsCount) % SnakePointsCount].Y);
            Point p2 = new Point(SnakePoints[(i + 1 ) % SnakePointsCount].X,
                SnakePoints[(i + 1 ) % SnakePointsCount].Y);
            p.X = SnakePoints[i].X;
            p.Y = SnakePoints[i].Y;
            snakePoints[i].Curvature = (p1.X + p2.X - 2 * p.X) * (p1.X + p2.X - 2 * p.X) + //计算曲率项能量
                            (p1.Y + p2.Y - 2 * p.Y) * (p1.Y + p2.Y - 2 * p.Y);
            if (max_curvature < snakePoints[i].Curvature)
                max_curvature = snakePoints[i].Curvature;//更新最大曲率
            //=============================================================================================================
        }

        avg_distance = 0.0;

        //归一化各点曲率能量
        for (i = 0; i < SnakePointsCount; i++)
            snakePoints[i].Curvature = snakePoints[i].Curvature / max_curvature;

        for (i = 0; i < SnakePointsCount; i++)
        {
            Point p_1 = new Point(SnakePoints[i].X, SnakePoints[i].Y);
            Point p_2 = new Point(SnakePoints[(i - 1 + SnakePointsCount) % SnakePointsCount].X,
                SnakePoints[(i - 1 + SnakePointsCount) % SnakePointsCount].Y);
            avg_distance += Math.Sqrt((double)(p_1.X - p_2.X) * (p_1.X - p_2.X) + (p_1.Y - p_2.Y) * (p_1.Y - p_2.Y));
            //此处有改动
            if (snakePoints[i].Curvature > CurvatureThreshold &&
                snakePoints[i].Curvature > snakePoints[(i + 1) % SnakePointsCount].Curvature &&
                snakePoints[i].Curvature > snakePoints[(i - 1 + SnakePointsCount) % SnakePointsCount].Curvature
                /* && GradMagnitude[i] > GradientThreshold*/
                )
            {
                double gradientManitude = 0.0;
                if(SnakePoints[i].X>=0&&SnakePoints[i].X<Width && SnakePoints[i].Y>=0 && SnakePoints[i].Y<Height)
                {
                    gradientManitude = gradient[SnakePoints[i].X, SnakePoints[i].Y].G ;
                }
                if (gradientManitude > GradientThreshold)
                {
                    snakePoints[i].Beta = 0;//释放i点处的曲率
                }

            }

        }
        if (willRemoveDead)
        {
            removeInvalidPoints();
        }
        return ptsMoved;
    }
    /// <summary>
    /// 高斯滤波,平滑图像,选用5*5 大小模板
    /// </summary>
    void Gauss()
    {
        double[] lpSrc = new double[25];
        Offset offset;
        int y, x, k;
        double lp;
        double tt;

        for (y = 2; y < lHeight - 2; y++)
        {
            for (x = 2; x < lWidth - 2; x++)
            {
                for (k = 0; k < 25; k++)
                {
                    offset = nbrNodeOffset_Gauss5(k);//偏移量5*5 mask
                    //n = (i + offset.Y) * lWidth + j + offset.X;//在图像数据区中的位置
                    lpSrc[k] = ImageData[x + offset.X, y + offset.Y];//图像中相应位置的数据
                }
                //Sobel算子,5*5
                tt = lpSrc[0] + lpSrc[1] + lpSrc[2] * 2 + lpSrc[3] + lpSrc[4] +
                   lpSrc[5] + lpSrc[6] * 2 + lpSrc[7] * 4 + lpSrc[8] * 2 + lpSrc[9] +
                   lpSrc[10] * 2 + lpSrc[11] * 4 + lpSrc[12] * 8 + lpSrc[13] * 4 + lpSrc[14] * 2 +
                   lpSrc[15] + lpSrc[16] * 2 + lpSrc[17] * 4 + lpSrc[18] * 2 + lpSrc[19] +
                   lpSrc[20] + lpSrc[21] + lpSrc[22] * 2 + lpSrc[23] + lpSrc[24];

                lp = tt / 52;//权值归一化,normalization
                if (lp > 255) lp = 255;
                if (lp < 0) lp = 0;
                ImageData[x,y] = lp;//sobel滤波后为粗略边缘         
            }
        }

程序太长了。。。。关键的问题是,在前一个类中用鼠标事件来记录初始轮廓中各点的坐标,这样很好理解,但是为什么在后一个类中也能得到同样的数据呢?