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

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

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

代码:

		//在种子点方向上寻找合适的梯度,用于寻找边缘
		//对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 ;
		}


图片效果:

              

posted @ 2016-06-27 18:18  wishchin  阅读(1523)  评论(0编辑  收藏  举报