Part11. 图像的轮廓
在该系列第三篇文章中,曾经简单地介绍过轮廓和轮廓发现。
11.1 轮廓的基本概念
图像的轮廓是指图像中具有相同颜色或灰度值的连续点的曲线。轮廓和边缘是有联系的,边缘是轮廓的基础,轮廓是边缘的连续集合。
轮廓和边缘的区别是:
轮廓是连续的,边缘可以是连续的,也可以是离散的。
轮廓是完整的,边缘可以是完整的,也可以是不完整的。
轮廓可以有各种形状,边缘通常是线性的。
21.2 轮廓发现和轮廓提取
轮廓发现是指在图像中找到所有可能的轮廓。
轮廓提取是指从图像中找到所有有效的轮廓和轮廓的具体信息。
轮廓发现是轮廓提取的前提,轮廓提取在轮廓发现的基础上进一步提取轮廓的形状和位置信息等等。
下面的代码,经过一系列操作找到二值图像的有效轮廓后,获取这些轮廓的最小外接矩形,最后用线在原图中框出这些外接矩形,从而在原图中找到比较明显的苹果。
#include <iostream>
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace std;
using namespace cv;
bool ascendSort(vector<Point> a,vector<Point> b)
{
return contourArea(a) > contourArea(b);
}
int main(int argc, char **argv) {
Mat src = imread(".../apple.jpg");
imshow("src", src);
Mat hsv,edge;
cvtColor(src, hsv, cv::COLOR_BGR2HSV); // BGR 转换到 HSV 色彩空间
imshow("hsv", hsv);
cv::Scalar lower_red(0, 43, 46);
cv::Scalar upper_red(10, 255, 255); // 定义红色的 HSV 范围
Mat mask;
inRange(hsv, lower_red, upper_red, mask); // 通过 inRange 函数实现二值化
imshow("mask", mask);
Mat kernel = getStructuringElement(MORPH_RECT, Size(15, 15));
morphologyEx(mask, mask, MORPH_CLOSE, kernel); // 形态学操作
morphologyEx(mask, mask, MORPH_OPEN, kernel); // 形态学操作
imshow("morphology", mask);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(mask, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
sort(contours.begin(), contours.end(), ascendSort);//ascending sort
for (size_t i = 0; i< contours.size(); i++) {
double area = contourArea(contours[i]);
if (area < 22000) {
continue;
}
cout << "area = " << area << endl;
RotatedRect rrt = minAreaRect(contours[i]);
Point2f pt[4];