c++视觉处理-----cv::findContours函数和图像进行去噪、平滑、边缘检测和轮廓检测,动态检测图形

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);
}

在这里插入图片描述
使用python方法来实现

import cv2
import numpy as np

# 全局变量声明
g_srcImage = None
g_grayImage = None
g_nThresh = 80
g_nThresh_max = 255
g_rng = np.random.default_rng(12345)
g_cannyMat_output = None
g_vContours = None
g_vHierarchy = None

# 窗口标题定义
WINDOW_NAME1 = "原始图窗口"
WINDOW_NAME2 = "轮廓图"

# 回调函数
def on_ThreshChange(val):
    global g_nThresh
    g_nThresh = val

    # Canny边缘检测
    canny_output = cv2.Canny(g_grayImage, g_nThresh, g_nThresh * 2, 3)

    # 寻找轮廓
    contours, hierarchy = cv2.findContours(canny_output, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    color = (255, 0, 0)  # Blue
    # 绘制轮廓
    drawing = np.zeros_like(canny_output, dtype=np.uint8)
    for i, contour in enumerate(contours):
        color = (255, 0, 0)  # Blu
        cv2.drawContours(drawing, contours, i, color, 2, cv2.LINE_8, hierarchy, 0)

    # 显示效果图
    cv2.imshow(WINDOW_NAME2, drawing)

# 主函数
if __name__ == "__main__":
    # 加载源图像
    g_srcImage = cv2.imread("113.jpg")
    if g_srcImage is None:
        print("读取图片错误,请检查图片路径!")
        exit(1)

    # 转成灰度并模糊化降噪
    g_grayImage = cv2.cvtColor(g_srcImage, cv2.COLOR_BGR2GRAY)
    g_grayImage = cv2.blur(g_grayImage, (3, 3))

    # 创建窗口
    cv2.namedWindow(WINDOW_NAME1, cv2.WINDOW_AUTOSIZE)
    cv2.imshow(WINDOW_NAME1, g_srcImage)

    # 创建滚动条并初始化
    cv2.createTrackbar("canny阈值", WINDOW_NAME1, g_nThresh, g_nThresh_max, on_ThreshChange)

    # 等待用户操作
    cv2.waitKey(0)
    cv2.destroyAllWindows()
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枭玉龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值