区域填充:扫描线种子填充算法应用(类似魔术棒功能)

/* < 扫描线种子填充算法 >
 *  
 * 算法的基本过程如下:
 *  当给定种子点(x, y)时,
 *  首先分别向左和向右两个方向填充种子点所在扫描线上的位于给定区域的一个区段,
 *  同时记下这个区段的范围[xLeft, xRight],
 *  然后确定与这一区段相连通的上、下两条扫描线上位于给定区域内的区段,
 *  并依次保存下来。反复这个过程,直到填充结束。
 *  
 * 四个步骤实现算法:
 *  (1) 初始化一个空的栈用于存放种子点,将种子点(x, y)入栈;
 *  (2) 判断栈是否为空,如果栈为空则结束算法,否则取出栈顶元素作为当前扫描线的种子点(x, y),y是当前的扫描线;
 *  (3) 从种子点(x, y)出发,沿当前扫描线向左、右两个方向填充,直到边界。分别标记区段的左、右端点坐标为xLeft和xRight;
 *  (4) 分别检查与当前扫描线相邻的y - 1和y + 1两条扫描线在区间[xLeft, xRight]中的像素,
 *      从xLeft开始向xRight方向搜索,若存在非边界且未填充的像素点,则找出这些相邻的像素点中最右边的一个,并将其作为种子点压入栈中,
 *      然后返回第(2)步;
 * 
 */

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;

namespace MagicWandTool
{
    class MagicWandTool
    {
        #region Private Field
        private int _iThresholdValue = 0;                                                       //临界值大小([0,255])
        private int _iImageWidth = 0;                                                           //原始图像的宽度
        private int _iImageHeight = 0;                                                          //原始图像的高度
        private IntPtr _ptrSourcePoint = IntPtr.Zero;                                           //初始点指针
        private IntPtr _ptrImageStartPoint = IntPtr.Zero;                                       //初始点指针
        private Dictionary<string, Point> _dicScannedSeed = new Dictionary<string, Point>();    //已经扫描过的种子点记录(用字典,是因为在要将某个种子点加入栈的时候,要判断这个种子点是否已经扫描过,在判断的时候,字典的速度比较快)
        private Dictionary<string, Point> _dicBorderRegion = new Dictionary<string, Point>();   //所有边界点集合(用Dictionary可以方便的覆盖相同点,而不用比较,而如果用List,在List中查找元素是否存在效率很低)
        private Stack<Point> _stackSeed = new Stack<Point>();                                   //保存种子点的栈

        #endregion

        #region Constructor
        public MagicWandTool()
        {
            this._stackSeed = new Stack<Point>();
            this._dicBorderRegion = new Dictionary<string, Point>();
            this._dicScannedSeed = new Dictionary<string, Point>(); 
        }

        #endregion

        #region Methods

        #region Public Methods
        public Point[] GetSelectRange(Image sourceImage,Point sourcePoint,int iThrehslodValue)
        {
            List<Point> listRange = new List<Point>();

            try
            {
                #region 初始化各种变量

                Bitmap sourceBitmap = new Bitmap(sourceImage);
                this._iThresholdValue = iThrehslodValue;
                this._iImageHeight = sourceBitmap.Height;
                this._iImageWidth = sourceBitmap.Width;
                BitmapData sourceBitmapData = sourceBitmap.LockBits(new Rectangle(0, 0, this._iImageWidth, this._iImageHeight), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
                
                unsafe
                {
                    this._ptrImageSt
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值