参考http://blog.csdn.net/hyymeishi/article/details/46409735
在得到图斑的边界像素点集合(存在容器中)后,需对边界建立栅格缓冲区。具体代码如下:
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
int Height;
int Width;
cv::Mat contourBuffer;
void findBoundary(cv::Mat &mask,std::vector<cv::Point> &boundary)
{
int height=mask.rows;
int width=mask.cols;
for ( int x=0;x<width;x++ )
{
for ( int y=0;y<height;y++ )
{
int curvalue=mask.at<uchar>(y,x);
if ( curvalue!=0 )
{
if ( x==0 || x==width-1 || y==0 || y==height-1 )
{
boundary.push_back(cv::Point(x,y));
}
else
{
//4邻域,若图斑邻接表改为8邻域,则这里也需要改
if ( mask.at<uchar>(y,x-1)==0 || mask.at<uchar>(y,x+1)==0 ||
mask.at<uchar>(y-1,x)==0 || mask.at<uchar>(y+1,x)==0)
{ boundary.push_back(cv::Point(x,y)); }
}
}
}
}
}
void contourFill8(int x,int y,int d,int oldvalue,int newvalue)
{
if ( x>=0 && x<Width && y>=0 && y<Height )
{
if ( d==0 ) { return; }
else { d--; }
int currentvalue;
currentvalue = contourBuffer.at<uchar>(y,x);
if ( currentvalue == oldvalue )
{ contourBuffer.at<uchar>(y,x)=newvalue;}
//8邻域
for (int i=-1;i<=1;i++)
{
for (int j=-1;j<=1;j++)
{
if ( i!=0 || j!=0 )
{ contourFill8( x+i, y+j, d, oldvalue, newvalue); }
}
}
}
else { return; }
}
int main()
{
cv::Mat mask;//create buffer along the contour
mask=cv::imread("test.png");
cvtColor(mask,mask,CV_BGR2GRAY);
Height=mask.rows;
Width=mask.cols;
std::vector<cv::Point> boundary;
// accept only char type matrices
CV_Assert( mask.depth() == CV_8U );
// accept only gray scale matrices
CV_Assert( mask.channels() == 1 );
findBoundary(mask,boundary);
int dist=3;
int oldvalue=0;
int newvalue=255;
contourBuffer=cv::Mat::zeros(Height,Width,CV_8UC1);
for (std::vector< cv::Point >::const_iterator it=boundary.begin();
it!=boundary.end();it++)
{ contourFill8(it->x,it->y,dist,oldvalue,newvalue); }
imwrite("end.jpg",contourBuffer);
return 0;
}
测试图像:
轮廓边界:
测试结果: