假设是单像素线白色用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. PHP面向对象之类的自动加载

    类的自动加载 含义: 当某行代码需要一个类的时候,php的内部机制可以做到“自动加载该类文件”,以满足该行需要一个类的这种需求. 什么时候需要一个类? 1,new一个对象的时候: 2,使用一个类的静态 ...

  2. pa sslvpn使用手册

    1.浏览器输入https://x.x.x.x 根据电脑操作系统及位数选择下载 2.安装 直接“下一步”,到  输入IP地址x.x.x.x 点击连接会有证书错误提示 此时点击显示证书→本地计算机→安装到 ...

  3. 使用SqlBulkCopy批量插入数据,测试20万条用时5秒

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

  4. xml转Map,对象,Map转xml,inputs tram 转xml 字符串的工具类方法

    众所周知,大家在微信开发工程中,由于微信开发文档中,对于消息的接收发送都是基础xml数据的(太坑了),所以我们需要对XML进行解析转换: 1.我们先引入所需要的依赖 dom4j (解析xml的),xs ...

  5. 线特征---LBD算法(三)

    上一节主要是介绍LSD算法理论,这节主要是介绍LBD算法. 参考文章:An efficient and robust line segment matching approach based on L ...

  6. c#编写windows服务在开机是OnStart启动超时

    1.编写服务对应的config文件, 比如我的服务叫ModbusAgent.exe,对应的文件叫ModbusAgent.exe.config 文件内容: <?xml version=" ...

  7. nvl 与 nvl2

    NVL函数 Oracle/PLSQL中的一个函数. 格式为: NVL( string1, replace_with) 功能:如果string1为NULL,则NVL函数返回replace_with的值, ...

  8. UVA 11235 (RMQ) 频繁出现的数值

    题目大意是给出一个非降序排列的数组,然后n个询问,每次询问一个区间内出现次数最多的数的次数. 首先要弄清楚题目的是一个非降序的数组,那么说明相等的数都会在一起,类似于11223334569这样的,那么 ...

  9. usr/include/c++/6.4.1/bits/stl_relops.:67: Parse error at "std"

    问题描述: 1.编译某qt工程的32位架构二进制包时,出现了上面错误,具体错误信息如下 qmake-qt5 -o ProductLicense/Makefile ProductLicense/Prod ...

  10. python爬虫_简单使用百度OCR解析验证码

    百度技术文档 首先要注册百度云账号: 在首页,找到图像识别,创建应用,选择相应的功能,创建 安装接口模块: pip install baidu-aip 简单识别一: 简单图形验证码: 图片: from ...