边缘区域的定义:图像上的一个区域位于边缘。如下图所示:
标号1 为一个边缘区域
现在希望可以将图像中的边缘区域去除。一个简单的思路如下:
遍历图像上下左右四条边界上的像素。设置一个计数器和一个最小边界阈值。当边界满足要求的像素个数大于阈值,就作为一个待处理区域。并选取其中一个坐标点作为种子点进行满水填充为0。
代码如下:
// 边缘区域去除1.cpp : 定义控制台应用程序的入口点。
// VS2010 opencv2.4.9
#include "stdafx.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
Mat src=imread("1.jpg",1);;
imshow("src",src);
//灰度化
Mat grayImage;
cvtColor(src,grayImage,CV_BGR2GRAY);
//二值化原图像
Mat thresImage=Mat::zeros(grayImage.rows,grayImage.cols,CV_8UC1);
threshold(grayImage,thresImage,250,255,THRESH_BINARY);
//imshow("thresImage",thresImage);
////方法1:轮廓提取与阈值填充
//vector<vector<Point>> contours;
//vector<Point>contours_sum;
//// find
//findContours(thresImage,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);
//for(int n =0; n<contours.size();++n)
//{
// cout<<contours[n].size()<<endl;
// for (int i=0;i<contours[n].size();++i)
// {
// contours_sum.push_back(contours[n][i]);
// }
//}
////cout<<contours_sum.size()<<endl;
//for (int i=0;i<contours_sum.size();++i)
//{
// //cout<<contours_sum[i]<<endl;
// floodFill(thresImage,contours_sum[i],0);//漫水填充法
//}
//imshow("floodFill",thresImage);
const int nr=thresImage.rows;
const int nc=thresImage.cols;
Mat edge[4];
edge[0] = thresImage.row(0); //up
edge[1] = thresImage.row(nr-1); //bottom
edge[2] = thresImage.col(0); //left
edge[3] = thresImage.col(nc-1); //right
std::vector<Point> edgePts;
const int minLength=std::min(nr,nc)/4;
for(int i=0;i<4;++i)
{
std::vector<Point> line;
Mat_<uchar>::const_iterator iter = edge[i].begin<uchar>(); //当前像素
Mat_<uchar>::const_iterator nextIter = edge[i].begin<uchar>()+1; //下一个像素
while(nextIter!=edge[i].end<uchar>())
{
if(*iter==255)
{
if(*nextIter==255)
{
Point pt = iter.pos();
if(i==1)
pt.y = nr-1;
if(i==3)
pt.x = nc-1;
//line.push_back(pt);
edgePts.push_back(pt);
}
//if(*nextIter!=255)
//{
// if(line.size()>minLength)
// edgePts.push_back(line.at(line.size()/2));
// line.clear();
//}
}
++iter;
++nextIter;
}
}
for(int n =0; n<edgePts.size();++n)
//cout<<edgePts[n];
floodFill(thresImage,edgePts[n],0);//漫水填充法
imshow("floodFill",thresImage);
waitKey( 0 );
}
copyMakeBorder可以处理多通道也可以处理单通道
如何使用OpenCV函数 copyMakeBorder 设置边界(添加额外的边界)。
假设src为以下矩阵
我们首先只在一个方向上,讨论,例如 top方向:
top =5 或者 10, bottom =0,left 0,right =0;注意我们这里故意让top的值,大于 src的rows,即行数。查看结果
borderType = BORDER_REFLECT:反射

解释:当按BORDER_REFLECT,向上给src加边界时,是按照src的反射机制来加的。
borderType = BORDER_REPLICATE:复制

解释:当BORDER_REPLICATE时,代表只复制边界。
当left=5,bottom =5时,

BORDER_TYPE = BORDER_REFLECT_101:

解释:101,已经表明 0不参加反射机制。也即是以第一行为镜面,做反射