二值图像距离变换研究

Trent1985
博客专家认证
2014-01-12 10:21:58
最近本人对二值图像距离变换进行了总结,包括欧式距离变换,非欧式距离变换(Chessboard距离变换,Cityblock距离变换,Chamfer距离变换),参考相关论文的快速算法,写了demo,特跟大家分享一下,喜欢数字图像处理的朋友们可以多多指教!
具体研究分析见博客http://blog.csdn.net/trent1985/article/details/18081761
完整Demo+快速算法相关论文+实验结果下载地址http://download.csdn.net/detail/trent1985/6841125
1,实验结果:



2,不同算法性能分析:


3,主要C#代码:

/// <summary>
/// Chamfer distance transform(using two 3*3 windows:forward window434 300 000;backward window 000 003 434).
/// </summary>
/// <param name="src">The source image.</param>
/// <returns>The result image.</returns>
public Bitmap ChamferDistancetransfrom(Bitmap src)
{
int w = src.Width;
int h = src.Height;
double p0 = 0, p1 = 0, p2 = 0, p3 = 0, p4 = 0, p5 = 0, p6 = 0, p7 = 0, p8 = 0, min = 0;
int mMax = 0, mMin = 255;
System.Drawing.Imaging.BitmapData srcData = src.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
unsafe
{
byte* p = (byte*)srcData.Scan0.ToPointer();
int stride = srcData.Stride;
byte* pTemp;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
if (x > 0 && x < w - 1 && y > 0 && y < h - 1)
{
p0 = (p + x * 3 + y * stride)[0];
if (p0 != 0)
{
pTemp = p + (x - 1) * 3 + (y - 1) * stride;
p2 = pTemp[0] + 4;
pTemp = p + x * 3 + (y - 1) * stride;
p3 = pTemp[0] + 3;
pTemp = p + (x + 1) * 3 + (y - 1) * stride;
p4 = pTemp[0] + 4;
pTemp = p + (x - 1) * 3 + y * stride;
p1 = pTemp[0] + 3;
min = GetMin(p0, p1, p2, p3, p4);
pTemp = p + x * 3 + y * stride;
pTemp[0] = (byte)Math.Min(min, 255);
pTemp[1] = (byte)Math.Min(min, 255);
pTemp[2] = (byte)Math.Min(min, 255);
}
}
else
{
pTemp = p + x * 3 + y * stride;
pTemp[0] = 0;
pTemp[1] = 0;
pTemp[2] = 0;
}

}

}
for (int y = h - 1; y > 0; y--)
{
for (int x = w - 1; x > 0; x--)
{
if (x > 0 && x < w - 1 && y > 0 && y < h - 1)
{
p0 = (p + x * 3 + y * stride)[0];
if (p0 != 0)
{
pTemp = p + (x + 1) * 3 + y * stride;
p5 = pTemp[0] + 3;
pTemp = p + (x + 1) * 3 + (y + 1) * stride;
p6 = pTemp[0] + 4;
pTemp = p + x * 3 + (y + 1) * stride;
p7 = pTemp[0] + 3;
pTemp = p + (x - 1) * 3 + (y + 1) * stride;
p8 = pTemp[0] + 4;
min = GetMin(p0, p5, p6, p7, p8);
pTemp = p + x * 3 + y * stride;
pTemp[0] = (byte)Math.Min(min, 255);
pTemp[1] = (byte)Math.Min(min, 255);
pTemp[2] = (byte)Math.Min(min, 255);
mMax = (int)Math.Max(min, mMax);
}
}
else
{
pTemp = p + x * 3 + y * stride;
pTemp[0] = 0;
pTemp[1] = 0;
pTemp[2] = 0;
}

}

}
mMin = 0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
pTemp = p + x * 3 + y * stride;
if (pTemp[0] != 0)
{
int temp = pTemp[0];
pTemp[0] = (byte)((temp - mMin) * 255 / (mMax - mMin));
pTemp[1] = (byte)((temp - mMin) * 255 / (mMax - mMin));
pTemp[2] = (byte)((temp - mMin) * 255 / (mMax - mMin));
}
}

}
src.UnlockBits(srcData);
return src;
}
}
...全文
1165 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
木木木木丫 2015-06-25
  • 打赏
  • 举报
回复
嗯哪 怪我我论文看少了,这篇论文就是4和3:Hierarchical Chamfer Matching: A Parametric Edge Matching Algorithm
Trent1985 2015-06-18
  • 打赏
  • 举报
回复
引用 13 楼 kylwin1214 的回复:
你好,为什么模板值是4和3呢?我看的原版论文是3和2啊。论文截图: 参考论文:parametric correspondence and chamfer matching two new techniques for image matching 请指教
4和3更常用,效果更逼近一些!
木木木木丫 2015-06-17
  • 打赏
  • 举报
回复
谢谢大神的代码,不错哦
木木木木丫 2015-06-17
  • 打赏
  • 举报
回复
你好,为什么模板值是4和3呢?我看的原版论文是3和2啊。论文截图: 参考论文:parametric correspondence and chamfer matching two new techniques for image matching
请指教
Trent1985 2014-01-19
  • 打赏
  • 举报
回复
dylike 2014-01-18
  • 打赏
  • 举报
回复
Conmajia 2014-01-18
  • 打赏
  • 举报
回复
脑力劳动者真好。。搬砖的苦力表示很羡慕。。
卧_槽 2014-01-18
  • 打赏
  • 举报
回复
引用 10 楼 conmajia 的回复:
脑力劳动者真好。。搬砖的苦力表示很羡慕。。
+1
Trent1985 2014-01-15
  • 打赏
  • 举报
回复
引用 7 楼 laviewpbt 的回复:
楼主呢这个分析了这个呢,我在一年前搞过,不过我提取说在这里啊,关注这个的人估计不多。楼主希望此贴有人气的愿望 可能和我每次发帖时的情况一样,最终总会落空的。 二值图像的各种距离(实际应用主要是欧几里得距离,EDM)的计算,其实能解决很多问题,她把原始图的坐标信息和颜色信息结合了起来,对于图像的分割和识别有着重要的桥梁作用,比如可以对EDM图进行分水岭算法等。 比如下面这些效果都是EDM的功能。 Java版本的开源软件 ImageJ 有edm方法的源代码参考。 在google上搜索这本书 The Image Processing Handbook 6th Edition,翻到500-550左右你会看到很多关于这方面的资料。
呵呵,我只是顺便做个总结,其实是做别的事情,用到这个,就在总结一下!
laviewpbt 2014-01-15
  • 打赏
  • 举报
回复
楼主呢这个分析了这个呢,我在一年前搞过,不过我提取说在这里啊,关注这个的人估计不多。楼主希望此贴有人气的愿望 可能和我每次发帖时的情况一样,最终总会落空的。
二值图像的各种距离(实际应用主要是欧几里得距离,EDM)的计算,其实能解决很多问题,她把原始图的坐标信息和颜色信息结合了起来,对于图像的分割和识别有着重要的桥梁作用,比如可以对EDM图进行分水岭算法等。
比如下面这些效果都是EDM的功能。

Java版本的开源软件 ImageJ 有edm方法的源代码参考。

在google上搜索这本书 The Image Processing Handbook 6th Edition,翻到500-550左右你会看到很多关于这方面的资料。



智商余额不足 2014-01-15
  • 打赏
  • 举报
回复
顶一下,感谢分享
网络菜鸟00 2014-01-13
  • 打赏
  • 举报
回复
感谢分享!!
Trent1985 2014-01-13
  • 打赏
  • 举报
回复
3楼的留言被删除了,自己顶一下!
Trent1985 2014-01-12
  • 打赏
  • 举报
回复
 private double GetDistance(int x, int y, int dx, int dy, int mode)
        {
            double result = 0;
            switch (mode)
            {
                case 1:
                    result = EuclideanDistance(x, y, dx, dy);
                    break;
                case 2:
                    result = CityblockDistance(x, y, dx, dy);
                    break;
                case 3:
                    result = ChessboardDistance(x, y, dx, dy);
                    break;
            }
            return result;
        }
        private double EuclideanDistance(int x, int y, int dx, int dy)
        {
            return Math.Sqrt((x - dx) * (x - dx) + (y - dy) * (y - dy));
        }
        private double CityblockDistance(int x, int y, int dx, int dy)
        {
            return Math.Abs(x - dx) + Math.Abs(y - dy);
        }
        private double ChessboardDistance(int x, int y, int dx, int dy)
        {
            return Math.Max(Math.Abs(x - dx), Math.Abs(y - dy));
        }
        private double GetMin(double a, double b, double c, double d, double e)
        {
            return Math.Min(Math.Min(Math.Min(a, b), Math.Min(c, d)), e);
        }
Trent1985 2014-01-12
  • 打赏
  • 举报
回复
主要代码补充:
/// <summary>
        /// Distance transform for binary image.
        /// </summary>
        /// <param name="src">The source image.</param>
        /// <param name="distanceMode">One parameter to choose the mode of distance transform from 1 to 3, 1 means Euclidean Distance, 2 means CityBlock Distance, 3 means ChessBoard Distance.</param>
        /// <returns>The result image.</returns>
        public Bitmap DistanceTransformer(Bitmap src, int distanceMode)
        {
            int w = src.Width;
            int h = src.Height;
            double p0 = 0, p1 = 0, p2 = 0, p3 = 0, p4 = 0, p5 = 0, p6 = 0, p7 = 0, p8 = 0, min = 0;
            int mMax = 0, mMin = 255;
            System.Drawing.Imaging.BitmapData srcData = src.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            unsafe
            {
                byte* p = (byte*)srcData.Scan0.ToPointer();
                int stride = srcData.Stride;
                byte* pTemp;
                for (int y = 0; y < h; y++)
                {
                    for (int x = 0; x < w; x++)
                    {
                        if (x > 0 && x < w - 1 && y > 0 && y < h - 1)
                        {
                            p0 = (p + x * 3 + y * stride)[0];
                            if (p0 != 0)
                            {
                                pTemp = p + (x - 1) * 3 + (y - 1) * stride;
                                p2 = pTemp[0] + GetDistance(x, y, x - 1, y - 1, distanceMode);
                                pTemp = p + x * 3 + (y - 1) * stride;
                                p3 = pTemp[0] + GetDistance(x, y, x, y - 1, distanceMode);
                                pTemp = p + (x + 1) * 3 + (y - 1) * stride;
                                p4 = pTemp[0] + GetDistance(x, y, x + 1, y - 1, distanceMode);
                                pTemp = p + (x - 1) * 3 + y * stride;
                                p1 = pTemp[0] + GetDistance(x, y, x - 1, y, distanceMode);
                                min = GetMin(p0, p1, p2, p3, p4);
                                pTemp = p + x * 3 + y * stride;
                                pTemp[0] = (byte)Math.Min(min, 255);
                                pTemp[1] = (byte)Math.Min(min, 255);
                                pTemp[2] = (byte)Math.Min(min, 255);
                            }
                        }
                        else
                        {
                            pTemp = p + x * 3 + y * stride;
                            pTemp[0] = 0;
                            pTemp[1] = 0;
                            pTemp[2] = 0;
                        }

                    }

                }
                for (int y = h - 1; y > 0; y--)
                {
                    for (int x = w - 1; x > 0; x--)
                    {
                        if (x > 0 && x < w - 1 && y > 0 && y < h - 1)
                        {
                            p0 = (p + x * 3 + y * stride)[0];
                            if (p0 != 0)
                            {
                                pTemp = p + (x + 1) * 3 + y * stride;
                                p5 = pTemp[0] + GetDistance(x, y, x + 1, y, distanceMode);
                                pTemp = p + (x + 1) * 3 + (y + 1) * stride;
                                p6 = pTemp[0] + GetDistance(x, y, x + 1, y + 1, distanceMode);
                                pTemp = p + x * 3 + (y + 1) * stride;
                                p7 = pTemp[0] + GetDistance(x, y, x, y + 1, distanceMode);
                                pTemp = p + (x - 1) * 3 + (y + 1) * stride;
                                p8 = pTemp[0] + GetDistance(x, y, x - 1, y + 1, distanceMode);
                                min = GetMin(p0, p5, p6, p7, p8);
                                pTemp = p + x * 3 + y * stride;
                                pTemp[0] = (byte)Math.Min(min, 255);
                                pTemp[1] = (byte)Math.Min(min, 255);
                                pTemp[2] = (byte)Math.Min(min, 255);
                                mMax = (int)Math.Max(min, mMax);
                            }
                        }
                        else
                        {
                            pTemp = p + x * 3 + y * stride;
                            pTemp[0] = 0;
                            pTemp[1] = 0;
                            pTemp[2] = 0;
                        }

                    }

                }
                mMin = 0;
                for (int y = 0; y < h; y++)
                {
                    for (int x = 0; x < w; x++)
                    {
                        pTemp = p + x * 3 + y * stride;
                        if (pTemp[0] != 0)
                        {
                            int temp = pTemp[0];
                            pTemp[0] = (byte)((temp - mMin) * 255 / (mMax - mMin));
                            pTemp[1] = (byte)((temp - mMin) * 255 / (mMax - mMin));
                            pTemp[2] = (byte)((temp - mMin) * 255 / (mMax - mMin));
                        }
                    }

                }
                src.UnlockBits(srcData);
                return src;
            }
        }

110,571

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧