使用切线方法,对切线方向上的边缘进行强化:

参考连接:图像锐化和边缘检测

代码:

		//在种子点方向上寻找合适的梯度,用于寻找边缘
//对low_Gray, high_gray之间的点寻找边缘
void FindBestGradient(
cv::Mat &_src, cv::Mat &_dst,
cv::Point2f &seed,
float low_Gray,
float high_gray,
int aperture_size, bool oPenEnhence )
{
//角度矩阵
cv::Mat df = cv::Mat::zeros( _src.rows,_src.cols, CV_32FC1 );
//梯度矩阵
cv::Mat dg = cv::Mat::zeros( _src.rows,_src.cols, CV_32FC1 );
//原始图像
cv::Mat ds = _src.clone();
//目标图像 uchar型
cv::Mat dd = _src.clone(); //1.根据角度计算梯度//得到梯度矩阵
//使用N*1的算子
int n = aperture_size;//必须为奇数 //对每个柱进行初始化
//搜索柱:在射线方向上搜索l_Search 个像素;宽度为
int l_Search = n;
int w_Search = 1;
std::vector<std::vector<std::pair<cv::Point ,float> > > beam;
beam.resize( l_Search );
for (int i=0;i< beam.size();++i)
{
beam[i].resize(w_Search);
}//初始化柱 //设定系数//生成模板
double gap = 2.0/ (n-1);
std::vector< double > mask(l_Search);
for (int i=0;i< mask.size();++i)
{
mask[i] = -1 + i*gap ;
} //2.生成角度图像
//在射线方向上寻找//方法不是太好,但是没有寻找到简单有效的方法
for ( int y=0 ;y< ds.rows;++y )
{
float* ptr = (float*)( df.data + y * df.step);
unsigned char* pS = ( unsigned char* )( ds.data + y * ds.step);
for ( int x=0; x< ds.cols; ++x )
{
//计算角度
if ( (int)(*pS) > low_Gray && (int)(*pS) <high_gray )
{
*ptr = (float)(cvWish::cosCv(seed,cv::Point2f( x,y ) ) );
}
else
{
*ptr = 0.00000000000f;
}
++ptr;
++pS;
}
} //计算差值-导数
for (int y=0 ;y< ds.rows;++y)
{
float* pf = (float*)( df.data + y * df.step);
float* pg = (float*)( dg.data + y * dg.step);
unsigned char* pd = (unsigned char*)( dd.data + y * dd.step); for (int x=0;x< ds.cols;++x )
{
//计算角度
if ( abs((float)(*pf)) > 0.00000001 )
{
//cvWish::BeamInit(l_Search,w_Search,cv::Point2f( x,y ),df.at<float >(y,x),beam,0);//0表示从中部开始搜索
cvWish::BeamInit(l_Search,w_Search,cv::Point2f( x,y ), *pf ,beam,0);//0表示从中部开始搜索
cvWish::BeamNormal(dg.cols, dg.rows , beam); *pg = 0;
for ( int k =0; k< l_Search; ++k ){
*pg += (float)( mask[k]* ds.at<unsigned char>(beam[k][0].first.y,beam[k][0].first.x) );
}
int s = abs ( ( (int)(*pg ) )%255 ) ;
*pd = (unsigned char) (s);
}
else
{
*pd = (unsigned char) (0);
} ++pf;
++pg;
++pd;
}
} cv::Mat edgeMat = dd;
cv::Mat angleMat= df;
int maskSize = 5;
if ( oPenEnhence )
{
int num = 1;
for (int i=0;i< num;++i)
{
EnhanceEdgeByTangent( edgeMat ,angleMat, maskSize);
} }
else
{
}
_dst = edgeMat.clone();
return;
}

边缘强化函数:

//使用边缘增强--沿切线方向增强
//方向性,边缘限制
void EnhanceEdgeByTangent( cv::Mat &edgeMat ,cv::Mat &angleMat, int maskSize)
{
cv::Mat ds = edgeMat;
cv::Mat dd = edgeMat.clone(); cv::Mat df = angleMat;
cv::Mat dg = angleMat.clone();//导数图,最终转化为 灰度图 dd const int l_Search = maskSize;
const int w_Search = 1;
//初始化柱
std::vector<std::vector<std::pair<cv::Point ,float> > > beam;
beam.resize( l_Search );
for (int i=0;i< beam.size();++i)
{
beam[i].resize(w_Search);
}//初始化柱 //设定系数//生成模板
double gap = 2.0/ ( l_Search - 1);
std::vector< double > mask(l_Search);
for (int i=0;i< mask.size();++i)
{
mask[i] =abs( 1- abs( -1 + i*gap ) );
} //强化边缘
for (int y=0 ;y< ds.rows;++y)
{
float* pf = (float*)( df.data + y * df.step);
float* pg = (float*)( dg.data + y * dg.step);
unsigned char* pd = (unsigned char*)( dd.data + y * dd.step); for ( int x=0; x< ds.cols; ++x )
{
//计算角度
if ( abs((float)(*pf)) > 0.00000001 )
{
float angle = *pf + PI_1_2 ;//切线方向,加 PI_1_2
angle = angle>=PI_4_2? angle - PI_4_2:angle; cvWish::BeamInit( l_Search, w_Search, cv::Point2f( x,y ), angle , beam, 0 );
cvWish::BeamNormal(dg.cols, dg.rows , beam); *pg = 0;
const int gl= ds.at<unsigned char>(y,x) ;//当前像素值
int vvv = dd.at<unsigned char>(y,x);
for ( int k =0; k< l_Search; ++k ){
vvv += gl* mask[k];
}
if ( vvv>255 )
{
vvv=255 ;
}
dd.at<unsigned char>(y,x) = vvv; //*pd = (unsigned char) (s);
}
else
{
*pd = (unsigned char) (0);
}
++pf;
++pg;
++pd;
}
} edgeMat = dd.clone();
return ;
}

图片效果:

OpenCV : 基于切线方向的边缘增强算法的更多相关文章

  1. opencv基于PCA降维算法的人脸识别

    opencv基于PCA降维算法的人脸识别(att_faces) 一.数据提取与处理 # 导入所需模块 import matplotlib.pyplot as plt import numpy as n ...

  2. JavaScript基于时间的动画算法

    转自:https://segmentfault.com/a/1190000002416071 前言 前段时间无聊或有聊地做了几个移动端的HTML5游戏.放在不同的移动端平台上进行测试后有了诡异的发现, ...

  3. 最小生成树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind

    最小支撑树树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind 最小支撑树树 前几节中介绍的算法都是针对无权图的,本节将介绍带权图的最小 ...

  4. mahout入门指南之基于mahout的itembased算法

    基于mahout的itembased算法 事实上mahout分布式上仅仅是实现了部分算法.比方推荐算法中Item-based和slopone都有hadoop实现和单机版实现,User-based没有分 ...

  5. 基于ReliefF和K-means算法的医学应用实例

    基于ReliefF和K-means算法的医学应用实例 数据挖掘方法的提出,让人们有能力最终认识数据的真正价值,即蕴藏在数据中的信息和知识.数据挖掘 (DataMiriing),指的是从大型数据库或数据 ...

  6. OpenCV学习(20) grabcut分割算法

    http://www.cnblogs.com/mikewolf2002/p/3330390.html OpenCV学习(20) grabcut分割算法 在OpenCV中,实现了grabcut分割算法, ...

  7. 大数据算法->推荐系统常用算法之基于内容的推荐系统算法

    港真,自己一直非常希望做算法工程师,所以自己现在开始对现在常用的大数据算法进行不断地学习,今天了解到的算法,就是我们生活中无处不在的推荐系统算法. 其实,向别人推荐商品是一个很常见的现象,比如我用了一 ...

  8. 基于FPGA的Cordic算法实现

    CORDIC(Coordinate Rotation Digital Computer)算法即坐标旋转数字计算方法,是J.D.Volder1于1959年首次提出,主要用于三角函数.双曲线.指数.对数的 ...

  9. 基于Twitter的Snowflake算法实现分布式高效有序ID生产黑科技(无懈可击)

    参考美团文档:https://tech.meituan.com/2017/04/21/mt-leaf.html Twitter-Snowflake算法产生的背景相当简单,为了满足Twitter每秒上万 ...

随机推荐

  1. BZOJ 1051 HAOI 2006 受欢迎的牛

    [题解] 先用tarjan缩点,然后如果某个强联通分量的出度为0,则该强联通分量内的点数为答案,否则无解.因为若其他所有的强联通分量都有边连向Ai,则Ai必定没有出边,否则Ai连向的点所属的强联通分量 ...

  2. 关于wordclou的一些简单操作

    详细讲解一下怎么用python的三方库wordcloud制作一个关于歌曲<Vincent>的歌词,有特别背景的云词效果,如图所示: 首先的先准备好一张背景图,为了云词效果,可以实现修改一下 ...

  3. hdu_1013_Digital Roots_201310121652

    Digital Roots Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tot ...

  4. WEB安全:SQL注入

    SQL注入是站点和web应用程序中最常见的安全漏洞. 这样的恶意技术有非常多应用场景, 但(SQL注入)一般是指在数据输入的地方注入代码以利用数据库应用程序中的安全漏洞. SQL注入在接收用户输入的接 ...

  5. 使用Linq 查询数据 构建对象 select new{}

    linq 查询数据 /// <summary> /// 汽车品牌及车型 /// </summary> /// <returns></returns> p ...

  6. JAVA正則表達式小总结

    近期项目中正在做后台校验,而后台校验也基本都是使用正則表達式校验.本文做一些粗略的总结. 1.字符串长度:.{1,10},注意有一个点在{}前,表示匹配全部.'{}'之前一定是一个捕获组,因此假设有其 ...

  7. Exchange 2013 的会议室邮箱用户一直无法正常登陆。

    某客户使用了Exchange 2013 server作为邮件承载server.详细版本号为Exchange 2013 SP1. 如今客户有个需求,希望他们的邮箱作为会议室邮箱创建,并且必须有普通邮箱全 ...

  8. Linux线程池在server上简单应用

    一.问题描写叙述 如今以C/S架构为例.client向server端发送要查找的数字,server端启动线程中的线程进行对应的查询.将查询结果显示出来. 二.实现方案 1. 整个project以cli ...

  9. C++智能指针--auto_ptr指针

    auto_ptr是C++标准库提供的类模板,头文件<memory>,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一块内存不能同一时候被分给两个拥有者.当 ...

  10. ListView无障碍识别整个listView,不识别item,设置了setContentDescription也没实用

    点击ListView的时候.无障碍识别到的是整个listView,不会读点击的那个item. 解决的方法是在getView里手动设置: <span style="font-size:1 ...