OpenCV : 基于切线方向的边缘增强算法

来源:互联网 发布:淘宝怎么进淘宝客 编辑:程序博客网 时间:2024/05/20 01:34

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

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

代码:

//在种子点方向上寻找合适的梯度,用于寻找边缘//对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();//导数图,最终转化为 灰度图 ddconst 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_2angle = 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 ;}


图片效果:

              

0 0
原创粉丝点击