cv::findContours
cv::findContours
是OpenCV中用于查找图像中对象轮廓的函数。轮廓是对象的边界,通常用于对象检测、分割和形状分析。cv::findContours
函数的基本用法如下:
cv::findContours(image, contours, hierarchy, mode, method, offset = cv::Point(0, 0));
image
: 输入的二值化图像(通常是灰度图像,经过阈值处理得到的二值图像)。contours
: 用于存储找到的轮廓的容器,通常是一个std::vector<std::vector<cv::Point>>
。hierarchy
: 可选参数,用于存储轮廓的层次结构信息。mode
: 轮廓检索模式,通常使用cv::RETR_EXTERNAL
表示只检索最外层的轮廓。method
: 轮廓近似方法,通常使用cv::CHAIN_APPROX_SIMPLE
表示只保留轮廓的端点。offset
: 可选参数,通常设置为cv::Point(0, 0)
。
cv::findContours
将在输入图像中查找轮廓,并将找到的轮廓保存在 contours
容器中。hierarchy
参数用于存储轮廓的层次结构信息,通常在分析多个轮廓之间的关系时使用。
以下是一个示例,演示如何使用 cv::findContours
函数来查找图像中的轮廓:
#include <opencv2/opencv.hpp>
int main() {
cv::Mat image = cv::imread("your_binary_image.jpg", cv::IMREAD_COLOR);
cv::Mat grayImage, binaryImage;
if (image.empty()) {
std::cerr << "无法加载图像" << std::endl;
return -1;
}
// 将图像转换为灰度图像
cv::cvtColor(image, grayImage, cv::COLOR_BGR2GRAY);
// 阈值处理,将图像转换为二值图像
cv::threshold(grayImage, binaryImage, 128, 255, cv::THRESH_BINARY);
// 查找轮廓
std::vector<std::vector<cv::Point>> contours;
cv::findContours(binaryImage, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
// 绘制轮廓
cv::Mat contourImage = cv::Mat::zeros(image.size(), CV_8UC3);
cv::drawContours(contourImage, contours, -1, cv::Scalar(0, 0, 255), 2);
cv::imshow("原始图像", image);
cv::imshow("轮廓图像", contourImage);
cv::waitKey(0);
return 0;
}
在这个示例中,我们首先将彩色图像转换为灰度图像,然后进行阈值处理得到二值图像。接下来,使用 cv::findContours
查找图像中的轮廓,并将其绘制到另一个图像上。这个示例只是演示了 cv::findContours
的基本用法,您可以根据具体的应用需要进一步处理找到的轮廓。
要对图像进行去噪、平滑、边缘检测和轮廓检测,然后允许通过滑动条调整参数以动态检测图形
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
// 回调函数,用于处理滑动条的变化
void trackbarCallback(int threshold, void* userdata) {
cv::Mat* image = static_cast<cv::Mat*>(userdata);
// 去噪处理(高斯滤波)
cv::Mat denoisedImage;
cv::GaussianBlur(*image, denoisedImage, cv::Size(5, 5), 0);
// 边缘检测(Canny)
cv::Mat edges;
cv::cvtColor(denoisedImage, edges, cv::COLOR_BGR2GRAY);
cv::Canny(edges, edges, threshold, threshold * 2);
// 查找轮廓
std::vector<std::vector<cv::Point>> contours;
cv::findContours(edges, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
// 绘制轮廓
cv::Mat contourImage = cv::Mat::zeros(image->size(), CV_8UC3);
cv::drawContours(contourImage, contours, -1, cv::Scalar(0, 0, 255), 2);
cv::imshow("动态边缘检测与轮廓", contourImage);
}
int main() {
cv::Mat image = cv::imread("111.jpg", cv::IMREAD_COLOR);
if (image.empty()) {
std::cerr << "无法加载图像" << std::endl;
return -1;
}
// 创建窗口
cv::namedWindow("动态边缘检测与轮廓", cv::WINDOW_NORMAL);
int initialThreshold = 100;
int maxThreshold = 500;
// 创建滑动条
cv::createTrackbar("阈值", "动态边缘检测与轮廓", &initialThreshold, maxThreshold, trackbarCallback, &image);
// 初始化
trackbarCallback(initialThreshold, &image);
cv::waitKey(0);
return 0;
}
方法2
#include <opencv2/opencv.hpp>
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
#include <iostream>
#include <fstream>
using namespace cv; //包含cv命名空间
#include <opencv2/core/core.hpp>
#define WINDOW_NAME1 "【原始图窗口】" //为窗口标题定义的宏
#define WINDOW_NAME2 "【轮廓图】" //为窗口标题定义的宏
//【全局变量声明部分】-------------------- -
// 描述: 全局变量的声明
//
Mat g_srcImage;
Mat g_grayImage;
int g_nThresh = 80;
int g_nThresh_max = 255;
RNG g_rng(12345);
Mat g_cannyMat_output;
vector<vector<Point>> g_vContours;
vector<Vec4i> g_vHierarchy;
//-------- -------------------【全局函数声明部分】-----------------------
// 描述:全局函数的声明
static void ShowHelpText();
void on_ThreshChange(int, void*);
// --【main()函数】---------------------------
// 描述: 控制台应用程序的入口函数, 我们的程序从这里开始执行
//- -------
int main(int argc, char** argv)
{
//【0】改变 console字体颜色
system("color 1F");
//【0】显示欢迎和帮助文字
ShowHelpText();
// 加载源图像
g_srcImage = imread("113.jpg", 1);
if (!g_srcImage.data)
{
printf("读取图片错误, 请确定目录下是否有imread函数指定的图片存在~! \n"); return false;
}
// 转成灰度并模糊化降噪
cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
blur(g_grayImage, g_grayImage, Size(3, 3));
// 创建窗口
namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE);
imshow(WINDOW_NAME1, g_srcImage);
//创建滚动条并初始化
createTrackbar("canny阈值", WINDOW_NAME1, &g_nThresh, g_nThresh_max, on_ThreshChange);
on_ThreshChange(0, 0);
waitKey(0);
return(0);
}
// -【on_ThreshChange()函数】--------------------
// 描述: 回调函数
//-
void on_ThreshChange(int, void*)
{
// 用Canny算子检测边缘
Canny(g_grayImage, g_cannyMat_output, g_nThresh, g_nThresh * 2, 3);
// 寻找轮廓
findContours(g_cannyMat_output, g_vContours, g_vHierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
// 绘出轮廓
Mat drawing = Mat::zeros(g_cannyMat_output.size(), CV_8UC3);
for (int i = 0; i < g_vContours.size(); i++)
{
Scalar color = Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255));//任意值
drawContours(drawing, g_vContours, i, color, 2, 8, g_vHierarchy, 0, Point());
}
// 显示效果图
imshow(WINDOW_NAME2, drawing);
}
//---------------------------【ShowHelpText()函数】-------------------
// 描述: 输出一些帮助信息
//-
static void ShowHelpText()
{
//输出欢迎信息和OpenCV版本
printf("\n\n\t\t\t 当前使用的OpenCV 版本为: " CV_VERSION);
}