当前位置: 首页 > 编程日记 > 正文

笔画宽度变化(C++和matlab算法)

最近一直在看工作方面的书籍,把论文的事情搁置了,之前承诺的贴代码的事一直拖。现在把代码整理发上来,只有核心部分的,都不是我写的,我是网上整理下载的,matlab代码的效果比较差。

全部文件网盘下载地址:http://pan.baidu.com/s/1qWwNMfM;

1.C++代码

下载地址:

需要先安装opencv和boost库。

boost库下载地址:http://www.boost.org/users/download/;

boost的安装:http://www.cnblogs.com/pangxiaodong/archive/2011/05/05/2037006.html;

装这个boost库,我只是把文件复制到vs安装目录的include文件夹下。

GitHub repository:https://github.com/aperrau/DetectText

2.matlab代码
function [ swtMap ] = swt( im, searchDirection )
%swt Preforms stoke width transform on input image
%   A novel image operator that seeks to find the value of stroke width
%   for each image pixel.  It's use is meant for the task of text
%   detection in natural images.
%
%   im = RGB input image of size m x n x 3
%   searchDirection = gradient direction is either 1 to detect dark text on light
%   background or -1 to detect light text on dark background.
%
%   swtMap = resulting mapping of stroke withs for image pixels% Convert image to gray scale
im = im2double(rgb2gray(im));
%figure, imshow(im), title('Black and White Image');% Find edges using canny edge dector
edgeMap = edge(im, 'canny');
%figure, imshow(edgeMap), title('Edges Using Canny');% Get all edge pixel postitions
[edgePointRows, edgePointCols] = find(edgeMap);% Find gradient horizontal and vertical gradient
sobelMask = fspecial('sobel');
dx = imfilter(im,sobelMask);
dy = imfilter(im,sobelMask');
%figure, imshow(dx, []), title('Horizontal Gradient Image');
%figure, imshow(dy, []), title('Vertical Gradient Image');% Initializing matrix of gradient direction
theta = zeros(size(edgeMap,1),size(edgeMap,2));% Calculating theta, gradient direction, for each pixel on the image.
% ***This can be optimized by using edgePointCols and edgePointRows
% instead.***
for i=1:size(edgeMap,1)for j=1:size(edgeMap,2)if edgeMap(i,j) == 1theta(i,j) = atan2(dy(i,j),dx(i,j));endend
end% Getting size of the image
[m,n] = size(edgeMap);% Initializing Stoke Width array with infinity
swtMap = zeros(m,n);
for i=1:mfor j=1:nswtMap(i,j) = inf;end
end% Set the maximum stroke width, this number is variable for now but must be
% made to be more dynamic in the future
maxStrokeWidth = 350;% Initialize container for all stoke points found
strokePointsX = zeros(size(edgePointCols));
strokePointsY = zeros(size(strokePointsX));
sizeOfStrokePoints = 0;% Iterate through all edge points and compute stoke widths
for i=1:size(edgePointRows)step = 1;initialX = edgePointRows(i);initialY = edgePointCols(i);isStroke = 0;initialTheta = theta(initialX,initialY);sizeOfRay = 0;pointOfRayX = zeros(maxStrokeWidth,1);pointOfRayY = zeros(maxStrokeWidth,1);% Record first point of the raypointOfRayX(sizeOfRay+1) = initialX;pointOfRayY(sizeOfRay+1) = initialY;% Increase the size of the raysizeOfRay = sizeOfRay + 1;% Follow the raywhile step < maxStrokeWidthnextX = round(initialX + cos(initialTheta) * searchDirection * step);nextY = round(initialY + sin(initialTheta) * searchDirection * step);step = step + 1;% Break loop if out of bounds.  For some reason this is really% slow.if nextX < 1 | nextY < 1 | nextX > m | nextY > nbreakend% Record next point of the raypointOfRayX(sizeOfRay+1) = nextX;pointOfRayY(sizeOfRay+1) = nextY;% Increase size of the raysizeOfRay = sizeOfRay + 1;% Another edge pixel has been foundif edgeMap(nextX,nextY)oppositeTheta = theta(nextX,nextY);% Gradient direction roughtly oppositeif abs(abs(initialTheta - oppositeTheta) - pi) < pi/2isStroke = 1;strokePointsX(sizeOfStrokePoints+1) = initialX;strokePointsY(sizeOfStrokePoints+1) = initialY;sizeOfStrokePoints = sizeOfStrokePoints + 1;endbreakendend% Edge pixel is part of strokeif isStroke% Calculate stoke widthstrokeWidth = sqrt((nextX - initialX)^2 + (nextY - initialY)^2);% Iterate all ray points and populate with the minimum stroke widthfor j=1:sizeOfRayswtMap(pointOfRayX(j),pointOfRayY(j)) = min(swtMap(pointOfRayX(j),pointOfRayY(j)),strokeWidth);endend
end%figure, imshow(swtMap, []), title('Stroke Width Transform: First Pass');% Iterate through all stoke points for a refinement pass.  Refer to figure
% 4b in the paper.for i=1:sizeOfStrokePointsstep = 1;initialX = strokePointsX(i);initialY = strokePointsY(i);initialTheta = theta(initialX,initialY);sizeOfRay = 0;pointOfRayX = zeros(maxStrokeWidth,1);pointOfRayY = zeros(maxStrokeWidth,1);swtValues = zeros(maxStrokeWidth,1);sizeOfSWTValues = 0;% Record first point of the raypointOfRayX(sizeOfRay+1) = initialX;pointOfRayY(sizeOfRay+1) = initialY;% Increase the size of the raysizeOfRay = sizeOfRay + 1;% Record the swt value of first stoke pointswtValues(sizeOfSWTValues+1) = swtMap(initialX,initialY);sizeOfSWTValues = sizeOfSWTValues + 1;% Follow the raywhile step < maxStrokeWidthnextX = round(initialX + cos(initialTheta) * searchDirection * step);nextY = round(initialY + sin(initialTheta) * searchDirection * step);step = step + 1;% Record next point of the raypointOfRayX(sizeOfRay+1) = nextX;pointOfRayY(sizeOfRay+1) = nextY;% Increase size of the raysizeOfRay = sizeOfRay + 1;% Record the swt value of next stoke pointswtValues(sizeOfSWTValues+1) = swtMap(nextX,nextY);sizeOfSWTValues = sizeOfSWTValues + 1;% Another edge pixel has been foundif edgeMap(nextX,nextY)breakendend% Calculate stoke width as the median value of all swtValues seen.strokeWidth = median(swtValues(1:sizeOfSWTValues));% Iterate all ray points and populate with the minimum stroke widthfor j=1:sizeOfRayswtMap(pointOfRayX(j),pointOfRayY(j)) = min(swtMap(pointOfRayX(j),pointOfRayY(j)),strokeWidth);endend%figure, imshow(swtMap, []), title('Stroke Width Transform: Second Pass');end

转载于:https://www.cnblogs.com/dawnminghuang/p/3906622.html

相关文章:

bzoj1227: [SDOI2009]虔诚的墓主人(树状数组,组合数)

传送门 首先&#xff0c;对于每一块墓地&#xff0c;如果上下左右各有$a,b,c,d$棵树&#xff0c;那么总的虔诚度就是$C_k^a*C_k^b*C_k^c*C_k^d$ 那么我们先把所有的点都给离散&#xff0c;然后按$x$为第一关键字&#xff0c;$y$为第二关键字&#xff0c;那么同一横坐标的一定在…

[导入]源代码版本控制(一)

开发过程当中源代码的版本控制一直是个大问题。项目规模小了还好办&#xff0c;人的脑子还能记过来&#xff0c;项目大了&#xff0c;可能用各式各样的表格来记录版本信息和源代码内容&#xff0c;但这个办法本身的文档组织又是个问题&#xff0c;谁来维护&#xff1f;谁来更改…

重构技巧分别能够解决哪些代码味道

1.提炼类可以解决的5种代码味道&#xff1a; 过大类 重复代码 基本类型偏执 令人迷惑的暂时值域 狎昵关系 2.将类内联化可以解决的3种代码味道 冗赘类 夸夸其谈的未来性 霰弹式修改 3.隐藏委托关系解决的2种代码味道 狎昵关系 过度耦合的消息链 4.复制被监视的数据 过大类 5.以…

python爬取电影和美食数据实战

本文使用的是requests正则来匹配网页内容&#xff0c;对于数据量较多的采用了多线程抓取的方法&#xff0c;共3个案例&#xff0c;分别是抓取猫眼电影TOP100榜单和淘票票正在热映的电影信息、以及美团的美食数据。这几个案例采用的方法大同小异。1、首先选择想要爬取的网站2、确…

Asp.Net页面执行流程分析

在我的上一篇文章中说到了HttpModule、HttpHandle的简单使用&#xff0c;我们可以利用它们在页面请求的过程中加入自己的事件处理程序。那么在一个aspx页面请求时后台到底做了什么&#xff1f;当然asp.net做了很多事情&#xff0c;过程也比较复杂&#xff0c;本文主要分析一下大…

正则验证非法字符

function regText(text){var reg /^[\s\u4e00-\u9fa5a-z0-9_-]{0,}$/;if(!reg.exec(text)){console.log("非法字符")}else{console.log("有效字符")} } regText("abc") 验证 &#xff1a;汉字、英文、数字、下划线、中划线、空格 转载于:https…

活动排序工具之双代号网络(AOA)与单代号网络(AON)[cont.]

箭线图ADM/双代号网络AOA 图示 箭线表示活动 节点表示一个活动的开始或结束 三要素&#xff1a;结点、箭线、线路 唯一使用虚活动的活动排序工具&#xff0c;虚活动用虚线箭头表示&#xff0c;没有历时&#xff0c;不需资源&#xff0c;只表达活动关系的需要 只使用一种活动之…

并发任务的可视化

一、任务要求&#xff1a;在linux系统中设计一个父进程&#xff0c;三个子进程(A,B,C)。子进程A,B同时被父进程启动来计算&#xff08;不实现具体的计算任务&#xff0c;先用CPU空跑来代替&#xff09;。进程A计算5分钟&#xff0c;而进程B计算8分钟。当进程A,B都计算完成后才能…

银监会警示担保圈贷款风险 联保贷款变异 防多米诺效应

互保联保本是解决小微企业以及农村金融贷款需求的重要创新&#xff0c;但却在部分行业、部分地区逐渐变异&#xff0c;成为引发风险事件的诱因。 据媒体报道&#xff0c;银监会近日发文要求加强企业担保圈贷款风险的防范和化解工作。银监会警示&#xff0c;担保圈企业风险较高的…

SharePoint 2007 系列(4) -Site Settings

Site administration 转载于:https://www.cnblogs.com/xuxiaoguang/archive/2008/11/05/1326913.html

软件项目管理重点总结

文章目录概论走进项目管理把控环境&#xff0c;控制过程整合项目资源控制项目范围保障项目进度驾驭项目成本保证项目质量协调项目人力资源改善项目的沟通应对项目风险关注项目的采购和外包概论 项目的定义&#xff1a;为创造一个特定的产品、服务或者成果而采取的临时性的努力…

jQuery发送含有数组参数的ajax请求以及后台Struts2的OGNL解析错误

当使用jquery1.3以上版本时&#xff0c;进行ajax参数传值时&#xff0c;会出现以下的一个错误: ognl.ExpressionSyntaxException: Malformed OGNL expression: f[] [ognl.ParseException: Encountered " "]" "] "" at line 1, column 3. 这个错…

数据绑定以及Container.DataItem绑定技巧

数据绑定以及Container.DataItem绑定技巧 灵活的运用数据绑定操作绑定到简单属性:<%#UserName%>绑定到集合:<asp:ListBox id"ListBox1" datasource<%# myArray%> runat"server">绑定到表达式:<%#(class1.property1.ToString() "…

LeetCode 76. Minimum Window Substring / 567. Permutation in String

76. Minimum Window Substring 典型Sliding Window的问题&#xff0c;维护一个区间&#xff0c;当区间满足要求则进行比较选择较小的字串&#xff0c;重新修改start位置。 思路虽然不难&#xff0c;但是如何判断当前区间是否包含所有t中的字符是一个难点&#xff08;t中字符有重…

计算机网络中的协议数据单元的控制信息主要包括哪些内容

在计算机网络的数据传输过程中会对数据进行封装&#xff0c;俗称加头(链路层还会加尾)&#xff0c;增加的控制信息主要包括以下内容&#xff1a; 地址(Address)&#xff1a;用来标识发送端或接收端差错检测编码(Error-detecting code)&#xff1a;用于差错检测或纠正协议控制(…

jQuery 超屏加载

jQuery 超屏加载&#xff0c;当文档超出屏幕的高度时&#xff0c;加载最新下个列数据 $(window).scroll(function () {var height $(document).height(); //页面的高度var keheight $(window).height(); //浏览器可视的高度var sheight $(document).scrollTop(); //滚动的高…

自己动手,打造轻量级VSCode/C#环境代替LinqPad

.Net 的项目都挺重的&#xff0c;一直想找一个轻量级的 CSharp 环境&#xff0c;能像Python那样&#xff0c;选一个文件就能跑的。之前用的是 LinqPad&#xff0c;但它的缺点也很明显&#xff1a; &#xff08;1&#xff09; 不付费&#xff0c;自动完成不能用&#xff08;…

让html:error只显示第一条错误信息

struts-config.xml 中的 <plug-in className"org.apache.struts.validator.ValidatorPlugIn"> 里面加上 <set-property property"stopOnFirstError" value"true"/> 就可以了 </plug-in> 转载于:https://www.cnblogs.com/kakak…

(C++)除基取余法:将十进制数转化为Q进制数

所谓基&#xff0c;就是指将要转换成的进制Q。 除基取余的意思就是&#xff1a;每次将待转换数除以Q&#xff0c;然后将得到的余数作为低位存储&#xff0c;而商则继续除以Q并重复上面的操作&#xff0c;直至商0时&#xff0c;将所有位从高到低输出就可以得到Q进制数。 代码实…

《C++ Primer 4th》读书笔记 第5章-表达式

原创文章&#xff0c;转载请注明出处&#xff1a; http://www.cnblogs.com/DayByDay/p/3912114.html 转载于:https://www.cnblogs.com/DayByDay/p/3912114.html

vue - check-versions.js for child_process

webpack之类的配置文件. webpack.base.conf.js

EasyPHP-2.0b1+ Mantis-1.1.0安装及技巧

转载&#xff1a; EasyPHP-2.0b1 Mantis-1.1.0安装及技巧 注&#xff1a;部分配置来源网络&#xff0c;写此文仅为以后配置提供参考 Mantis是一个轻量级的brower的bug管理系统&#xff0c;界面直观&#xff0c;简单易用&#xff0c;安装简单&#xff0c;支持多语言&#xff0c;…

PAT 显示格式错误

记录一&#xff1a; 2021/7/8 10:26 代码逻辑写错了&#xff0c;一个该没有空格的地方也加了空格

翡润年华-毛货展示003

www.520jade.com转载于:https://www.cnblogs.com/520jade/p/3912790.html

json学习之路

总感觉自己比别人慢好几排&#xff0c;不知道到底多少&#xff0c;但至少一排吧&#xff1f;&#xff1f;&#xff1f; 一直很喜欢js&#xff0c;但刚开始编程的时候一直把js停留在"有效性验证"上&#xff0c;大大浪费了js.不过当时已经知道js很强大了&#xff0c;可…

layoutSubviews 调用情况

init初始化不会触发layoutSubviews 但是是用initWithFrame 进行初始化时&#xff0c;当rect的值不为CGRectZero时,也会触发addSubview会触发layoutSubviews设置view的Frame会触发layoutSubviews&#xff0c;当然前提是frame的值设置前后发生了变化滚动一个UIScrollView会触发la…

python基本数据类型之序列类型和映射类型

序列类型&#xff1a;字符串/元组/列表 映射类型&#xff1a;字典 更正&#xff1a;&#xff1a;三引号也可以用来表示字符串&#xff0c;并且有额外用途&#xff1a;①搞定多行字符串 ②内用单引号和双引号 列表可以根据内容得到索引 有多个相同内容时根据第一个得到下标

关于EF中ApplyCurrentValues和ApplyOriginalValues区别

关于EF中ApplyCurrentValues和ApplyOriginalValues区别&#xff1a;两者都是编辑数据时使用。 // // 摘要: // 将 System.Data.Objects.ObjectStateEntry 的 System.Data.Objects.ObjectStateEntry.CurrentValues // 属性设置为与所提供对象的属性…

PHP Session中保存Object

在PHP中&#xff0c;使用Session保存Object时&#xff0c;PHP会将Object自动序列化。在读取Session变量时&#xff0c;准确地说是在session_start时&#xff0c;PHP会将Session中已序列化的Object反序列化。这时就需要Class的定义&#xff0c;Why&#xff1f;因为序列化时只是保…

kali linux网络配置

事情是这样的 今天早上想安装一个按个人信息生成密码的软件 发现无法安装 发现问题后 我首先检查了kali有没有获取到IP 然后就是没有获取IP 怎么解决问题如下&#xff1a; 原理进程&#xff1a; 1.写入dhcp服务 1.进行DNS设置 首先输入命令&#xff1a; gedit /etc/network/int…