图像轮廓概念
- 图像轮廓就是图像边界,主要针对二值图像,轮廓就是一系列点的集合
图像轮廓发现算法
- 我们怎么来描述轮廓呢?
- 那么我们是如何发现轮廓呢?按照怎样的方法来确定所有的轮廓?寻找的过程是怎样的?基于联通组件,反应图像拓扑结构
算法思想: 论文:Topological structural analysis of digitized binary images by border following ,中主要介绍了两种算法,用来对数字二值图像进行拓扑分析。第一种算法是在确定二值图像边界的围绕关系,即确定外边界、孔边界以及他们的层次关系,由于这些边界和原图的区域具有一一对应关系(外边界对应像素值为1的连通区域,孔边界对应像素值为0的区域),因此我们就可以用边界来表示原图。第二种算法,是第一种算法的修改版本,本质一样,但是它只找最外面的边界。也许你会问,这个算法怎么来确定外边界,孔边界以及他们的层级关系?他采用编码的思想,给不同的边界赋予不同的整数值,从而我们就可以确定它是什么边界以及层次关系。输入的二值图像即为0和1的图像,用f(i,j)表示图像的像素值。每次行扫描,遇到以下两种情况终止:
然后从起始点开始,标记边界上的像素。在这里分配一个唯一的标示符给新发现的边界,叫做NBD。初始时NBD=1,每次发现一个新边界加1。在这个过程中,遇到f(p,q)=1,f(p,q+1)=0时,将f(p,q)置为-NBD。什么意思呢?就是右边边界的终止点。假如一个外边界里有孔边界时怎么推导呢?限于篇幅,你可以看论文的附录1。
- C++ API :
findContours
和drawContours
CV_EXPORTS_W void findContours( InputArray image, OutputArrayOfArrays contours,
OutputArray hierarchy, int mode,
int method, Point offset = Point());
CV_EXPORTS_W void drawContours( InputOutputArray image, InputArrayOfArrays contours,
int contourIdx, const Scalar& color,
int thickness = 1, int lineType = LINE_8,
InputArray hierarchy = noArray(),
int maxLevel = INT_MAX, Point offset = Point() );
参数说明:详细解释
//图像轮廓发现
int main(int argc, char** argv) {
Mat src = imread("F:/code/images/rice.png");
CV_Assert(!src.empty());
namedWindow("input", WINDOW_AUTOSIZE);
imshow("input", src);
//高斯滤波
GaussianBlur(src, src, Size(3, 3), 0);
//得到灰度图
Mat gray, binary;
cvtColor(src, gray, COLOR_RGB2GRAY);
imshow("gray", gray);
//得到二值图
threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
imshow("binary", binary);
//发现轮廓
vector<vector<Point>> contours;//因为每个contour都是一系列点的集合
vector<Vec4i> hierarchy;//层次信息
findContours(binary, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());
for (size_t t = 0; t < contours.size(); t++) {
drawContours(src, contours, -1, Scalar(0, 0, 255), 1, 8);
}
imshow("find contours demo", src);
waitKey(0);
destroyAllWindows();
return 0;
}
- python API
轮廓发现:
cv2.findContours(image, mode, method[, contours[, hierarchy[, offset]]])
参数说明:
输出为: 修改后的图像,轮廓,层次结构
轮廓 是所有轮廓的列表.每个单独的轮廓是对象边界点的坐标
关于 hierarchy:详细解释
绘制轮廓:
cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]])
import cv2
img = cv2.imread('.\\images\\dial_mask_binary.jpg')
cv2.imshow('img', img)
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 127, 255, 0)
#发现轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
#绘制轮廓
cv2.drawContours(img, contours, -1, (100,255,100), 2)
cv2.imshow('img_contours', img)
cv2.waitKey(0)
cv2.destroyAllWindows()