表示和描述
0. 前言
本章只学习了前三节……
VS安装Image watch插件请查看官网OpenCV: Image Watch: viewing in-memory images in the Visual Studio debugger
第三版教材中图片下载地址: book images downloads
vs2019配置opencv可以查看:VS2019 & Opencv4.5.4配置教程
前情回顾:
《数字图像处理》第三章 灰度变换和空间滤波 学习笔记附部分例子代码
《数字图像处理》第四章 频率域滤波 学习笔记附部分例子代码
数字图像处理第五章 图像复原和重建(内容较简单,就没有详细记录笔记)
《数字图像处理》第六章 彩色图像处理 学习笔记附部分例子代码
《数字图像处理》第七章 小波域多分辨率处理 学习笔记附部分例子代码
数字图像处理第八章 图像压缩 非重点
《数字图像处理》第九章 形态学图像处理 学习笔记附部分例子代码
《数字图像处理》第十章 图像分割 学习笔记附部分例子代码
1. 表示
1.1 边界追踪
处理的是二值图像,其目标和背景点分别标为1和0,Moore
边界追踪算法的步骤如下:
-
找到图像左上角为1的点b0为边界起始点。b0左边的点为c0,从c0开始按顺时针方向考察b0的8邻域,找到的第一个值1的点为b1,令扫描到b1前的点为c1。
-
赋值b=b1,c=c1。
-
从c开始顺时针方向行进,找到第一个值1的点nk,其之前的点均为背景点。
-
赋值b=nk,c=nk-1。
-
重复step3和step4,直到b=b0且下一个边界点为b1。
1.2 链码
链码用于表示由顺次连接的具有指定长度和方向的直线段组成的边界
使用了opencv的findContours()
和drawContours()
,具体形参的表示可以看补充
void ch11_test01(string path) {
Mat image = imread(path, IMREAD_GRAYSCALE);
if (image.empty()) {
cout << "Unable to load the image\n";
return;
}
// 创建一个纯黑画布
Mat black(image.size(), CV_8U, Scalar(0));
Mat filtered;
blur(image, filtered, Size(9, 9));
Mat result = Otsu(filtered);//该函数的实现请看第十章笔记的3.2节
// 寻找轮廓
vector<vector<Point>> contours;
findContours(result, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
vector<Point> contour = contours[0];
vector<int> freemaCode;
Point currentPoint = contour[0];
Point nextPoint;
for (size_t i = 1; i < contour.size(); i++) {
nextPoint = contour[i];
// 计算方向
int dx = nextPoint.x - currentPoint.x;
int dy = nextPoint.y - currentPoint.y;
// 转换为佛雷曼链码
int code = -1;
if (dx == 0 && dy == -1) code = 0;
else if (dx == 1 && dy == -1) code = 1;
else if (dx == 1 && dy == 0) code = 2;
else if (dx == 1 && dy == 1) code = 3;
else if (dx == 0 && dy == 1) code = 4;
else if (dx == -1 && dy == 1) code = 5;
else if (dx == -1 && dy == 0) code = 6;
else if (dx == -1 && dy == -1)code = 7;
// 添加到链码序列
freemaCode.push_back(code);
// 更新当前点
currentPoint = nextPoint;
}
// 输出佛雷曼链码
cout << "Freeman Chain Code: ";
for (int code : freemaCode) {
cout << code << " ";
}
cout << endl;
// 在黑布上画出轮廓
drawContours(black,