假设是单像素线白色用1(对应RGB(255,0,0))表示,背景用0(对应RBG(0,0,0))表示。

考虑3种类型的边界 水平方向  0->1  1->0   类似垂直方向也是0->1  1->0

如果是单像素,如果水平检测时 发现 0->1 或1->0变动,那么都将 mapX[i,j] 设置成1,注意是白色像素对应的位置

类似的处理也针对垂直方向mapY[i,j]

如果以个mapY[i,j] 与mapX[i,j] 同时标记成了1,那么意味着这个像素是斜方向,那么按sqrt(2)来记录。

注意一:以直角三角型为例,构成边的线段粗细大于1个像素,那么求出的结果是翻倍的,因为边界出现了2次。

注意二:以直角三角型为例,如果直角三角型内部是填充成白色的(前景色1),那么求出的结果是一样的,因为边界只出现一次。

完整代码如下,需要传入二值图片。

     /// <summary>
/// 二值图片前景是白背景是黑
/// 测试白像素的边长
/// 正负 pi/4 ,3pi/4 计1.414
/// 其余按1计
/// </summary>
/// <param name="bm"></param>
public static double? SegmentLen(Bitmap bm)
{ var map = new byte[bm.Width, bm.Height];
var mapX = new byte[bm.Width, bm.Height];
var mapY = new byte[bm.Width, bm.Height]; for (int i = ; i < bm.Width; i++)
{
for (int j = ; j < bm.Height; j++)
{
var c = bm.GetPixel(i, j);
if (c.R == )
{
map[i, j] = ; }
else
{
map[i, j] = ; }
mapX[i, j] = ;
mapY[i, j] = ;
}
}
//水平边界检测
for (int i = ; i < bm.Width - ; i++)
{ for (int j = ; j < bm.Height - ; j++)
{
if (map[i, j] == && map[i, j - ] == ) mapX[i, j] = ;
if (map[i, j] == && map[i, j - ] == ) mapX[i, j - ] = ; }
}
//垂直边界检测
for (int i = ; i < bm.Width - ; i++)
{ for (int j = ; j < bm.Height - ; j++)
{
if (map[i, j] == && map[i - , j] == ) mapY[i, j] = ;
if (map[i, j] == && map[i - , j] == ) mapY[i - , j] = ; }
}
var len = 0.0d;
for (int i = ; i < bm.Width; i++)
{ for (int j = ; j < bm.Height; j++)
{ if (mapY[i, j] == && mapX[i, j] == )
{
len += 1.414;
}
else if (mapX[i, j] == || mapY[i, j] == )
{
len += ;
}
}
}
return len; }

类似的调用代码

var filename = @"C:\t2\z4_3.jpg";
pictureBox1.ImageLocation = filename;
var tImg = new Bitmap(filename);

tImg = GenBinaryImgByThreshold(tImg, 80);
tImg = BorderCheck.FullScanBoundrExtract(tImg);
var len = BorderCheck.SegmentLen(tImg);
Console.WriteLine(len);
ShowImg(tImg);

        public Bitmap GenBinaryImgByThreshold(Bitmap bm, int threshold)
{
Color white = Color.FromArgb(, , );
Color black = Color.FromArgb(, , );
Color c = new Color();
int r;
Bitmap box1 = new Bitmap(bm.Width, bm.Height);
for (int i = ; i < bm.Width; i++)
{
for (int j = ; j < bm.Height; j++)
{
c = bm.GetPixel(i, j);
r = (c.R + c.G + c.B) / ;
if (r > threshold)
{
box1.SetPixel(i, j, black);
}
else
{
box1.SetPixel(i, j, white);
}
}
}
return box1;
}

上文涉及到的边界抽取函数:

        /// <summary>
/// 黑白图片全图检测边界抽取
/// </summary>
public static Bitmap FullScanBoundrExtract(Bitmap bm)
{
var box1 = new Bitmap(bm);//输入使用bm.Width,bm.Height,保留的点是透明的。
var b = Color.FromArgb(,, , );
var w = Color.FromArgb(,, , );
var map = new Int16[bm.Width, bm.Height];
var map2 = new Int16[bm.Width, bm.Height];
for (int i = ; i < bm.Width; i++)
{ for (int j = ; j < bm.Height; j++)
{
var c = bm.GetPixel(i, j);
if (c.R == )
{
map[i, j] = ;
}
else
{
map[i, j] = ;
box1.SetPixel(i, j, b);
}
//map2[i, j] = 0;
}
} for (int i = ; i < bm.Width - ; i++)
{ for (int j = ; j < bm.Height - ; j++)
{
if (map[i, j] == && map[i, j - ] == ) map2[i, j] = ;
if (map[i, j] == && map[i, j - ] == ) map2[i, j - ] = ; }
}
for (int i = ; i < bm.Width - ; i++)
{ for (int j = ; j < bm.Height - ; j++)
{
if (map[i, j] == && map[i - , j] == ) map2[i, j] = ;
if (map[i, j] == && map[i - , j] == ) map2[i - , j] = ; }
}
for (int i = ; i < bm.Width; i++)
{ for (int j = ; j < bm.Height; j++)
{
if (map2[i, j] == )
{ box1.SetPixel(i, j, b);
}
}
}
return box1;
}

黑白二值图像周长测量--C#实现的更多相关文章

  1. [ZZ] Shadow Map

    Shadow Map 如何能够高效的产生更接近真实的阴影一直是视频游戏的一个很有挑战的工作,本文介绍目前所为人熟知的两种阴影技术之一的ShadowMap(阴影图)技术.     ShadowMap技术 ...

  2. matlab中图像显示函数

    image函数是显示图像的最基本的方法.该函数还产生了图像对象的句柄,并允许对对象的属性进行设置. imagesc函数也具有image的功能,所不同的是imagesc函数还自动将输入数据比例化,以全色 ...

  3. ArcGIS API for JavaScript介绍

    ArcGIS API for JavaScript中的类是按照模块组织的,主要包含esri.esri/geometry.esri/renderers.esri/symbols.esri/symbols ...

  4. matlab图像基础知识

    1.MATLAB支持的几种图像文件格式: ⑴JPEG(Joint Photogyaphic Expeyts Group):一种称为联合图像专家组的图像压缩格式. ⑵BMP(Windows Bitmap ...

  5. GIS应用及OpenGIS介绍

    转自:http://blog.csdn.net/cdl2008sky/article/details/7266680 GIS的三大应用第一类是政府应用,“电子政务” 是当今政府加强信息化建设的新方向, ...

  6. MATLAB图像处理基础

    MATLAB图像处理基础 2.2.1 图像文件格式及图像类型 1.MATLAB支持的几种图像文件格式: ⑴JPEG(Joint Photogyaphic Expeyts Group):一种称为联合图像 ...

  7. Android仿微信图片上传,可以选择多张图片,缩放预览,拍照上传等

    仿照微信,朋友圈分享图片功能 .可以进行图片的多张选择,拍照添加图片,以及进行图片的预览,预览时可以进行缩放,并且可以删除选中状态的图片 .很不错的源码,大家有需要可以下载看看 . 微信 微信 微信 ...

  8. Hough transform(霍夫变换)

    主要内容: 1.Hough变换的算法思想 2.直线检测 3.圆.椭圆检测 4.程序实现 一.Hough变换简介 Hough变换是图像处理中从图像中识别几何形状的基本方法之一.Hough变换的基本原理在 ...

  9. 深度解读 AlphaGo 算法原理

    http://blog.csdn.net/songrotek/article/details/51065143 http://blog.csdn.net/dinosoft/article/detail ...

随机推荐

  1. 安卓操作系统版本(Version)与应用程序编程接口等级(Application Programming Interface Level)对照表

    Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑. 使用Android API,可以在Java环境开发App,编译.打包后可在Android系统 ...

  2. 【mysql】主从同步,事务等概念

    问题: mysql用binary log来保证主从同步的可靠性和安全性,在mysql中,主从同步是异步线程和异步任务来保证的. (在这点上,其它存储引擎有另外的选项,比如mongoDB和Elastic ...

  3. scrapy的调试和环境安装技巧

    1,先在settings中把ROBOTSTXT_OBEY = False 在主目录下面新建main文件 __autor__ = 'zhouli' __date__ = '2018/11/3 22:39 ...

  4. java常量类编译问题

    常量类编译后并不在.class文件中呈现,取而代之的是各个具体的常量.例如: 编译前:(Constant.OPTIONSRADIO常量值为1) 编译后: 应用场景 1,项目编译后发布项目前可以删除常量 ...

  5. AngularJS——第3章 指令

    第3章 指令 所谓指令就是AngularJS自定义的HTML属性或标签,这些指令都是以ng-做为前缀的,例如ng-app.ng-controller.ng-repeat等. 3.1 内置指令 ng-a ...

  6. tar.gz和.rpm包的区别与使用(转)

    一.Linux软件的二进制分发 Linux软件的二进制分发是指事先已经编译好二进制形式的软件包的发布形式,其优点是安装使用容易,缺点则是缺乏灵活性,如果该软件包是为特定的硬件/操作系统平台编译的,那它 ...

  7. linux命令学习之:touch

    touch命令有两个功能:一是用于把已存在文件的时间标签更新为系统当前的时间(默认方式),它们的数据将原封不动地保留下来:二是用来创建新的空文件. 语法 touch(选项)(参数) 选项 -a:或-- ...

  8. android的四种线程池

    使用线程池的好处: 首先通过线程池中线程的重用,减少创建和销毁线程的性能开销.其次,能控制线程池中的并发数,否则会因为大量的线程争夺CPU资源造成阻塞.最后,线程池能够对线程进行管理,比如使用Sche ...

  9. java.security.InvalidKeyException: Illegal key size 解决办法

    下载对应的文件并替换到指定目录 Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6 Jav ...

  10. jquery Jquery 遍历 获取设置 效果

    speed: slow fast 毫秒 隐藏 显示 $(selector).hide(speed,callback) 隐藏. $(selector).show(speed,callback) 显示 $ ...