opencv实现分水岭,金字塔,均值漂移算法进行分割

更新时间:2024-04-17 00:14:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

using System;

using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text;

using System.Windows.Forms; using System.Diagnostics;

using System.Runtime.InteropServices; using Emgu.CV;

using Emgu.CV.CvEnum; using Emgu.CV.Structure; using Emgu.CV.UI;

namespace ImageProcessLearn

{

public partial class FormImageSegment : Form {

//成员变量

private string sourceImageFileName = \;//源图像文件名 private Image imageSource = null; //源图像

private Image imageSourceClone = null; //源图像的克隆 private Image imageMarkers = null; //标记图像

private double xScale = 1d; //原始图像与PictureBox在x轴方向上的缩放

private double yScale = 1d; //原始图像与PictureBox在y轴方向上的缩放

private Point previousMouseLocation = new Point(-1, -1); //上次绘制线条时,鼠标所处的位置 private const int LineWidth = 5; //绘制线条的宽度

private int drawCount = 1; //用户绘制的线条数目,用于指定线条的颜色

public FormImageSegment() {

InitializeComponent(); }

//窗体加载时

private void FormImageSegment_Load(object sender, EventArgs e) {

//设置提示

toolTip.SetToolTip(rbWatershed, \可以在源图像上用鼠标绘制大致分割区域线条,该线条用于分水岭算法\);

toolTip.SetToolTip(txtPSLevel, \金字塔层数跟图像尺寸有关,该值只能是图像尺寸被2整除的次数,否则将得出错误结果\);

toolTip.SetToolTip(txtPSThreshold1, \建立连接的错误阀值\);

toolTip.SetToolTip(txtPSThreshold2, \分割簇的错误阀值\);

toolTip.SetToolTip(txtPMSFSpatialRadius, \空间窗的半径\); toolTip.SetToolTip(txtPMSFColorRadius, \色彩窗的半径\);

toolTip.SetToolTip(btnClearMarkers, \清除绘制在源图像上,用于分水岭算法的大致分割区域线条\); //加载图像 LoadImage(); }

//当窗体关闭时,释放资源

private void FormImageSegment_FormClosing(object sender, FormClosingEventArgs e) {

if (imageSource != null) imageSource.Dispose();

if (imageSourceClone != null) imageSourceClone.Dispose(); if (imageMarkers != null) imageMarkers.Dispose(); }

//加载源图像

private void btnLoadImage_Click(object sender, EventArgs e) {

OpenFileDialog ofd = new OpenFileDialog(); ofd.CheckFileExists = true; ofd.DefaultExt = \;

ofd.Filter = \图片文件|*.jpg;*.png;*.bmp|所有文件|*.*\; if (ofd.ShowDialog(this) == DialogResult.OK) {

if (ofd.FileName != \) {

sourceImageFileName = ofd.FileName; LoadImage(); } }

ofd.Dispose(); }

//清除分割线条

private void btnClearMarkers_Click(object sender, EventArgs e) {

if (imageSourceClone != null)

imageSourceClone.Dispose();

imageSourceClone = imageSource.Copy(); pbSource.Image = imageSourceClone.Bitmap;

imageMarkers.SetZero();

drawCount = 1; }

//当鼠标按下并在源图像上移动时,在源图像上绘制分割线条

private void pbSource_MouseMove(object sender, MouseEventArgs e) {

//如果按下了左键

if (e.Button == MouseButtons.Left) {

if (previousMouseLocation.X >= 0 && previousMouseLocation.Y >= 0) {

Point p1 = new Point((int)(previousMouseLocation.X (int)(previousMouseLocation.Y * yScale));

*

xScale),

Point p2 = new Point((int)(e.Location.X * xScale), (int)(e.Location.Y * yScale)); LineSegment2D ls = new LineSegment2D(p1, p2);

int thickness = (int)(LineWidth * xScale);

imageSourceClone.Draw(ls, new Bgr(255d, 255d, 255d), thickness); pbSource.Image = imageSourceClone.Bitmap;

imageMarkers.Draw(ls, new Gray(drawCount), thickness); }

previousMouseLocation = e.Location; } }

//当松开鼠标左键时,将绘图的前一位置设置为(-1,-1)

private void pbSource_MouseUp(object sender, MouseEventArgs e) {

previousMouseLocation = new Point(-1, -1); drawCount++; }

//加载源图像

private void LoadImage() {

if (imageSource != null) imageSource.Dispose();

imageSource = new Image(sourceImageFileName); if (imageSourceClone != null)

imageSourceClone.Dispose();

imageSourceClone = imageSource.Copy(); pbSource.Image = imageSourceClone.Bitmap; if (imageMarkers != null) imageMarkers.Dispose();

imageMarkers = new Image(imageSource.Size); imageMarkers.SetZero();

xScale = 1d * imageSource.Width / pbSource.Width; yScale = 1d * imageSource.Height / pbSource.Height; drawCount = 1; }

//分割图像

private void btnImageSegment_Click(object sender, EventArgs e) {

if (rbWatershed.Checked)

txtResult.Text += Watershed(); else if (rbPrySegmentation.Checked)

txtResult.Text += PrySegmentation(); else if (rbPryMeanShiftFiltering.Checked)

txtResult.Text += PryMeanShiftFiltering(); }

///

/// 分水岭算法图像分割 ///

/// 返回用时 private string Watershed() {

//分水岭算法分割

Image imageMarkers2 = imageMarkers.Copy(); Stopwatch sw = new Stopwatch();

sw.Start();

CvInvoke.cvWatershed(imageSource.Ptr, imageMarkers2.Ptr); sw.Stop();

//将分割的结果转换到256级灰度图像

pbResult.Image = imageMarkers2.Bitmap;

imageMarkers2.Dispose();

return string.Format(\分水岭图像分割,用时:sw.Elapsed.TotalMilliseconds); }

///

/// 金字塔分割算法

///

///

private string PrySegmentation() {

//准备参数

毫秒。\\r\\n\, {0:F05} Image imageDest = new Image(imageSource.Size); MemStorage storage = new MemStorage(); IntPtr ptrComp = IntPtr.Zero;

int level = int.Parse(txtPSLevel.Text);

double threshold1 = double.Parse(txtPSThreshold1.Text); double threshold2 = double.Parse(txtPSThreshold2.Text); //金字塔分割

Stopwatch sw = new Stopwatch(); sw.Start();

level, threshold1, threshold2); sw.Stop();

//显示结果

pbResult.Image = imageDest.Bitmap; //释放资源

imageDest.Dispose();

CvInvoke.cvPyrSegmentation(imageSource.Ptr, imageDest.Ptr, storage.Ptr, out ptrComp,

storage.Dispose(); return string.Format(\金字塔分割,用时:{0:F05}毫秒。\\r\\n\, sw.Elapsed.TotalMilliseconds); }

///

/// 均值漂移分割算法 ///

///

private string PryMeanShiftFiltering() {

//准备参数

Image imageDest = new Image(imageSource.Size); double spatialRadius = double.Parse(txtPMSFSpatialRadius.Text); double colorRadius = double.Parse(txtPMSFColorRadius.Text); int maxLevel = int.Parse(txtPMSFNaxLevel.Text); int maxIter = int.Parse(txtPMSFMaxIter.Text);

double epsilon = double.Parse(txtPMSFEpsilon.Text);

MCvTermCriteria termcrit = new MCvTermCriteria(maxIter, epsilon); //均值漂移分割

Stopwatch sw = new Stopwatch(); sw.Start();

OpenCvInvoke.cvPyrMeanShiftFiltering(imageSource.Ptr, imageDest.Ptr, spatialRadius, colorRadius, maxLevel, termcrit); sw.Stop(); //显示结果

pbResult.Image = imageDest.Bitmap; //释放资源

imageDest.Dispose();

return string.Format(\均sw.Elapsed.TotalMilliseconds); }

///

值漂移分割,用时:{0:F05}毫秒。\\r\\n\,

/// 当改变金字塔分割的参数“金字塔层数”时,对参数进行校验 ///

///

private void txtPSLevel_TextChanged(object sender, EventArgs e) {

int level = int.Parse(txtPSLevel.Text);

if (level < 1 || imageSource.Width % (int)(Math.Pow(2, level - 1)) != 0 || imageSource.Height % (int)(Math.Pow(2, level - 1)) != 0)

MessageBox.Show(this, \注意:您输入的金字塔层数不符合要求,计算结果可能会无效。\, \金字塔层数错误\);

}

///

/// 当改变均值漂移分割的参数“金字塔层数”时,对参数进行校验 ///

///

private void txtPMSFNaxLevel_TextChanged(object sender, EventArgs e) {

int maxLevel = int.Parse(txtPMSFNaxLevel.Text); if (maxLevel < 0 || maxLevel > 8)

MessageBox.Show(this, \注意:均值漂移分割的金字塔层数只能在0至8之间。\, \金字塔层数错误\);

} } }

return string.Format(\均sw.Elapsed.TotalMilliseconds); }

///

值漂移分割,用时:{0:F05}毫秒。\\r\\n\,

/// 当改变金字塔分割的参数“金字塔层数”时,对参数进行校验 ///

///

private void txtPSLevel_TextChanged(object sender, EventArgs e) {

int level = int.Parse(txtPSLevel.Text);

if (level < 1 || imageSource.Width % (int)(Math.Pow(2, level - 1)) != 0 || imageSource.Height % (int)(Math.Pow(2, level - 1)) != 0)

MessageBox.Show(this, \注意:您输入的金字塔层数不符合要求,计算结果可能会无效。\, \金字塔层数错误\);

}

///

/// 当改变均值漂移分割的参数“金字塔层数”时,对参数进行校验 ///

///

private void txtPMSFNaxLevel_TextChanged(object sender, EventArgs e) {

int maxLevel = int.Parse(txtPMSFNaxLevel.Text); if (maxLevel < 0 || maxLevel > 8)

MessageBox.Show(this, \注意:均值漂移分割的金字塔层数只能在0至8之间。\, \金字塔层数错误\);

} } }

本文来源:https://www.bwwdw.com/article/oimp.html

Top