1 轮廓检测
图像目标中的形状检测是图像识别的重要的技术之一,对物体进行检测并提取,首先要做的就是提取物体的轮廓信息,然后在通过点集特征选择相应的算法进行处理,最后得到物体的形状信息。轮廓形状是我们看到物体最开始的印象,轮廓提取的原理是通过对图像进行二值化,利用边缘点连接的层次差别,提取位于数结构特征高的区域点集构成的集合,这部分最可能是物体的轮廓。
主要用到的函数findContours()对物体轮廓进行检测。
void findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset=Point())
Contour retrieval mode.
Contour approximation method.
#include
#include
#include
#include
#include
using namespace cv;
using namespace std;
Mat srcImagel;
Mat srcGray;
int max_thresh = 255;
int thresh = 100;
RNG rng(12345);
//鼠标回调事件
void thresh_callback(int, void*)
{
Mat canny_output;
vector> contours;
vector hierarchy;
//用canny算子检测边缘
Canny(srcGray, canny_output, thresh, thresh * 2, 3);
//寻找轮廓
findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
//绘出轮廓
Mat drawing = Mat::zeros(canny_output.size(), CV_8UC3);
for (int i = 0; i < contours.size(); i++)
{
Scalar color = Scalar(rng.uniform(0, 255),rng.uniform(0,255),rng.uniform(0,255));
//随机颜色绘制轮廓
drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point());
}
//显示轮廓结果
namedWindow("Contours", CV_WINDOW_AUTOSIZE);
imshow("Contours", drawing);
}
int main()
{
Mat srcImage = imread("D:\\6.jpg");
if (!srcImage.data)
return -1;
cvtColor(srcImage, srcGray, COLOR_BGR2GRAY);
blur(srcGray, srcGray, Size(3, 3));
//创建窗体
char* source_window = "srcImage";
namedWindow(source_window, CV_WINDOW_AUTOSIZE);
imshow(source_window, srcImage);
//滑动条控制Canny阈值
createTrackbar(" thresh:", "srcImage", &thresh, max_thresh, thresh_callback);
thresh_callback(0, 0);
waitKey(0);
return 0;
}
#include
#include
#include
#include
#include
using namespace cv;
using namespace std;
//设置全局参数
Mat srcImage, srcGray;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);
void thresh_callback(int, void*)
{
Mat srcTemp = srcImage.clone();
Mat threMat;
//轮廓检测参数
vector > contours;
vector hierarchy;
//阈值化操作
threshold(srcGray, threMat, thresh, 255, THRESH_BINARY);
//轮廓检测
findContours(threMat, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
//凸包及缺陷检测参数
vector > pointHull(contours.size());
vector > intHull(contours.size());
vector > hullDefect(contours.size());
for (size_t i = 0; i < contours.size(); i++)
{
//Point类型凸包检测
convexHull(Mat(contours[i]), pointHull[i], false);
//int 类型凸包检测
convexHull(Mat(contours[i]), intHull[i], false);
//凸包缺陷检测
convexityDefects(Mat(contours[i]), intHull[i], hullDefect[i]);
}
//绘制凸包及缺陷检测
Mat drawing = Mat::zeros(threMat.size(), CV_8UC1);
for (size_t i = 0; i < contours.size(); i++)
{
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(drawing, contours, i, color, 1, 8, vector(), 0, Point());
drawContours(drawing, pointHull, i, color, 1, 8, vector(), 0, Point());
//绘制缺陷
size_t count = contours[i].size();
if (count < 300)
continue;
//设置凸包缺陷迭代器
vector::iterator iterDefects = hullDefect[i].begin();
//遍历得到4个特征量
while (iterDefects != hullDefect[i].end())
{
Vec4i& v = (*iterDefects);
//起始位置
int startidx = v[0];
Point ptStart(contours[i][startidx]);
//终止位置
int endidx = v[1];
Point ptEnd(contours[i][endidx]);
//内凸壳最远的点缺陷
int faridx = v[2];
Point ptFar(contours[i][faridx]);
//凸点之间的最远点
int depth = v[3] / 256;
//绘制相应的线与圆检测结果
if (depth > 20 && depth < 80)
{
line(drawing, ptStart, ptFar, CV_RGB(0, 255, 0), 2);
line(drawing, ptEnd, ptFar, CV_RGB(0, 255, 0), 2);
circle(drawing, ptStart, 4, Scalar(255, 0, 100), 2);
circle(drawing, ptEnd, 4, Scalar(255, 0, 100), 2);
circle(drawing, ptFar, 4, Scalar(100, 0, 255), 2);
}
iterDefects++;
}
}
imshow("result", drawing);
}
int main()
{
Mat srcImage = imread("D:\\3.jpg");
if (!srcImage.data)
return -1;
cvtColor(srcImage, srcGray, CV_BGR2GRAY);
blur(srcGray, srcGray, Size(3, 3));
char* source_window = "Source";
namedWindow(source_window, CV_WINDOW_AUTOSIZE);
imshow(source_window, srcImage);
createTrackbar("Thewshold:", "Source", &thresh, max_thresh, thresh_callback);
thresh_callback(0, 0);
waitKey(0);
return 0;
}