我手头有一个别人的代码,是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滤波后为粗略边缘
}
}
程序太长了。。。。关键的问题是,在前一个类中用鼠标事件来记录初始轮廓中各点的坐标,这样很好理解,但是为什么在后一个类中也能得到同样的数据呢?