使用切线方法,对切线方向上的边缘进行强化:
参考连接:图像锐化和边缘检测
代码:
//在种子点方向上寻找合适的梯度,用于寻找边缘
//对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 ;
}图片效果: