最近做验证码识别,原本用MATLAB已经实现的整个识别模型,不过代码要部署在Linux服务器上还是需要用另外的语言实现,于是决定用Python + OpenCV来实现。

bwlabel函数的作用是检测二值图像中连通域的个数及为每个连通域标记后的矩阵。

关于连通域检测算法我是参考的http://blog.sina.com.cn/s/blog_ad81d4310102vmll.html 这篇文章中的基于行程的标记 方法,以及传统的Two-Pass方法。

传统的Two-pass方法中关于连通域标记的规则如下:

1.逐行扫描图像上的点,检查每个点是否是前景点,如果不是,继续扫描;

2.检查该前景点的左边的点和上边的点

如果有一个为前景点,则为当前扫描点标记和此点相同编号;

如果两个都是前景点,则选择标号小的,为当前扫描点标记编号;这里注意如果两个都是前景点且标号不同,需要把标号小的点设为标号大的点的父节点,以方便第二遍扫描的时候用并查集算法(参考 利用不相交集实现等价元素的聚类 )合并;

如果都不是,则赋值目前标号label,label++(label初始值为零);

3.再次扫描图像,利用并查集算法合并联通的不同的label的区域。

第一二步就是一个二重循环遍历矩阵,对矩阵中每个元素的上邻元素和左邻元素进行判断来标记该元素,并扩充等价对列表。这两步都比较好理解。

经过标记后会得到一个标记后的矩阵和一个等价对列表。最后一步是将等价值列表合并成具有相同标记的标记集合,比如[(1,2),(1,5),(2,3),(4,6),(7,8)],那么需要把这幅等价值表转换成[(1,2,3,5),(4,6),(7,8)]这三个区域,最后通过这个新的表去重新遍历标记后的矩阵,将其他标记值修改为最小的标记值,这样最后就能得到一个标记了的连通域矩阵。

下面在仿照上面博客中的对等价值的处理。这篇博客中是用 C++ 来实现广度优先搜索,由于其中用到指针去改变栈的大小,这样能实现循环的时候边界长度随着栈的大小变化而动态的变化。

在java中这样在循环中动态改变列表的值数量是会报异常的,python中这样做的时候循环的边界大小不会随着列表的大小改变而改变。

参照博客中的算法,思路如下:

每个元素看做是无向图中的点,等价对看作是一条连通路径,所以先用等价对列表初始化一个连通矩阵 data。
创建一个列表 labelFlag 标记每个点是否被访问了。
对labelFlag进行遍历,如果labelFlag[i] == 0就表示i点没有被访问,!= 0就表示该点已经被访问了,则跳过该点继续遍历下一个点。
如果临时列表tempList为空,且遇到labelFlag[i]没有被访问,则说明需要创建一个新的连通域了。
如果tempList不为空,则将tempList列表的最后一个元素出栈得到元素index,然后判断index是否已经被访问了,如果没有被访问则继续对index为起点的路径访问;
如果index所指的行的元素不为0且不为 0 的元素所在的列对应的labelFlag[j]没有被访问,就把j压入tempList列表,并把j标记压入到连通集合中。

经过上面的遍历就能获得结果。

为了解决这个问题,我的代码实现如下:

import numpy as np

data = [(1, 2), (2, 4), (1, 5), (3, 6), (7, 8)]
maxLabel = np.max(data)
eqTab = np.zeros((maxLabel, maxLabel)) for left, right in data:
eqTab[left - 1, right - 1] = 1
eqTab[right - 1, left - 1] = 1 labelFlag = np.zeros(maxLabel) tempList = [1]
eqList = []
data_result = [] for i in xrange(maxLabel):
if labelFlag[i]:
continue
eqList = [i + 1]
tempList = [i + 1]
for k in xrange(maxLabel):
if not tempList:
break
index = tempList.pop()
for j in xrange(maxLabel):
if eqTab[index - 1, j] and not labelFlag[j]:
tempList.append(j + 1)
eqList.append(j + 1) labelFlag[index - 1] = 1 data_result.append(eqList) print data_result

输出结果为:[[1, 2, 5, 4], [3, 6], [7, 8]]

这个实现算法比较直白,完全是按照算法思路来写的程序,没有进一步考虑过优化什么的,读者可以自己琢磨琢磨。

等我把整个bwlabel算法写完再附上完整的源码。

Python实现MATLAB中的 bwlabel函数的更多相关文章

  1. python实现类似于Matlab中的magic函数

    参考这篇文章的代码封装了一个类似Matlab中的magic函数,用来生成魔方矩阵. #!/usr/bin/env python # -*- coding: utf-8 -*- import numpy ...

  2. matlab中的eval函数使用

    matlab中的eval函数使用 在matlab的命令行窗口中输入help eval命令回车就可以看到eval函数的官方解释,大概的意思就是执行matlab中的表达式,计算expression表示的代 ...

  3. Matlab中的eig函数和Opecv中eigen()函数的区别

    奇异值分解的理论参见下面的链接 http://www.cnblogs.com/pinard/p/6251584.html https://blog.csdn.net/shenziheng1/artic ...

  4. Matlab中的fread函数

    Matlab中fread函数用法    "fread"以二进制形式,从文件读出数据. 语法1:[a,count]=fread(fid,size,precision) 语法2:[a, ...

  5. matlab中的sub2ind函数

    在matlab中,矩阵的存储是按列优先,sub2ind函数将矩阵中指定元素的行列下标转换成存储的序号,即线性索引号.下面,我们举例子进行说明. 1 建立一个3*4*2的矩阵 rng(0,'twiste ...

  6. matlab中CRC的函数使用

    先学习一下matlab中CRC函数. 语法如下: h = crc.generator(‘Polynomial', polynomial, ‘param1', val1, etc.) 再看一个例子就比较 ...

  7. matlab中help所有函数功能的英文翻译

    doc funname 在帮助浏览器中打开帮助文档 help funname 在命令窗口打开帮助文档 helpbrowser 直接打开帮助浏览器 lookfor funname 搜索某个关键字相关函数 ...

  8. python开发_python中的range()函数

    python中的range()函数的功能hen强大,所以我觉得很有必要和大家分享一下 就好像其API中所描述的: If you do need to iterate over a sequence o ...

  9. Python连载43-current中的map函数、xml文件

    一.current中的map函数 1.map(fn,*iterable,timeout=None) (1)跟map函数相类似(2)函数需要异步执行(3)timeout代表超时时间 (4)map和sub ...

随机推荐

  1. React——嵌入已有项目 && jsx

    Add React to a Website React has been designed from the start for gradual adoption, and you can use ...

  2. 阶段5 3.微服务项目【学成在线】_day17 用户认证 Zuul_11-前端显示当前用户-前端请求jwt

    前端代码 sessionStorage也是key/value的格式 页头显示当前用户 查询jwt nginx里面的配置 测试 开启认证服务 进行登陆 跳转到首页就应该立即请求查询. 跳转到首页 coo ...

  3. Spring声明式事务如何选择代理方式?

    Spring声明式事务如何选择代理方式   解决方法: 1.基于注解方法: <tx:annotation-driven transaction-manager="txManager&q ...

  4. Js 实现局部打印功能

    1.当前页面 var bodyHtml = window.document.body.innerHTML; window.document.body.innerHTML = printHtml;//p ...

  5. 使用json_encode编码中文返回null的解决方案

    在gbk的程序中,直接使用json_encode编码包含中文字符的数组,将会返回null. 解决方法: 1.把程序文件编码改为utf8 2.使用mb_convert_encoding把编码转换为utf ...

  6. 偶尔在网上看到的,相对比较好的c#端订单号生成规则

    偶尔在网上看到的,相对比较好的c#端订单号生成规则 public class BillNumberBuilder{     private static object locker = new obj ...

  7. 无缝轮播 css3

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. Docker 跨主机网络 overlay(十六)

    目录 一.跨主机网络概述 二.准备 overlay 环境 1.环境描述 2.创建 consul 3.修改 docker 配置文件 4.准备就绪 三.创建 overlay 网络 1.在 host1 中创 ...

  9. Python爬虫入门教程之BeautifulSoup

    模块安装 pip3 install beautifulsoup4 模块导入 from bs4 import BeautifulSoup 示例html内容 RPC是一种比较流行的RPC通信框架,由谷歌公 ...

  10. linux shell中的EOF

    关键词:EOF 在平时的运维工作中,我们经常会碰到这样一个场景:执行脚本的时候,需要往一个文件里自动输入N行内容.如果是少数的几行内容,还可以用echo追加方式,但如果是很多行,那么单纯用echo追加 ...