C++ OpenCV实现轮廓查找:详解及底层代码实现 (非findContours)
C++ OpenCV实现轮廓查找:详解及底层代码实现 (非findContours)
本文将介绍如何使用C++和OpenCV实现轮廓查找算法,无需依赖OpenCV自带的findContours函数。文章将深入探讨算法原理、实现步骤以及相关公式,并提供完整的代码示例。
1. 算法原理
本文实现的轮廓查找算法基于连通性原理。其核心思想是从二值化图像中识别所有连通区域,并将每个连通区域转换为轮廓。
2. 算法步骤
- 图像灰度化: 将输入的彩色图像转换为灰度图像。
- 图像二值化: 对灰度图像进行二值化处理,将图像转换为黑白两种像素值。
- 查找连通区域: 遍历二值化图像,找到所有连通区域。对于每个连通区域,将其所有像素点连接起来,形成轮廓。
- 绘制轮廓: 将找到的轮廓绘制到图像上。
3. 算法公式
- 灰度化:
gray = 0.299R + 0.587G + 0.114B - 二值化:
binary(x, y) = (gray(x, y) > threshold) ? 255 : 0
4. 代码实现
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main() {
Mat img = imread('image.jpg');
// 图像灰度化
Mat gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
// 图像二值化
Mat binary;
threshold(gray, binary, 100, 255, THRESH_BINARY);
// 查找轮廓
vector<vector<Point>> contours;
for (int y = 0; y < binary.rows; y++) {
for (int x = 0; x < binary.cols; x++) {
if (binary.at<uchar>(y, x) == 255) {
vector<Point> contour;
contour.push_back(Point(x, y));
int i = 0;
while (i < contour.size()) {
Point p = contour[i];
if (p.x > 0 && binary.at<uchar>(p.y, p.x - 1) == 255) {
contour.push_back(Point(p.x - 1, p.y));
binary.at<uchar>(p.y, p.x - 1) = 0;
}
if (p.x < binary.cols - 1 && binary.at<uchar>(p.y, p.x + 1) == 255) {
contour.push_back(Point(p.x + 1, p.y));
binary.at<uchar>(p.y, p.x + 1) = 0;
}
if (p.y > 0 && binary.at<uchar>(p.y - 1, p.x) == 255) {
contour.push_back(Point(p.x, p.y - 1));
binary.at<uchar>(p.y - 1, p.x) = 0;
}
if (p.y < binary.rows - 1 && binary.at<uchar>(p.y + 1, p.x) == 255) {
contour.push_back(Point(p.x, p.y + 1));
binary.at<uchar>(p.y + 1, p.x) = 0;
}
i++;
}
contours.push_back(contour);
}
}
}
// 绘制轮廓
Mat drawing = Mat::zeros(binary.size(), CV_8UC3);
for (int i = 0; i < contours.size(); i++) {
drawContours(drawing, contours, i, Scalar(0, 0, 255), 2, LINE_8);
}
// 显示结果
imshow('Contours', drawing);
waitKey(0);
return 0;
}
5. 总结
本文介绍了如何使用C++和OpenCV实现不依赖findContours函数的轮廓查找算法。通过理解算法原理和实现步骤,我们可以更加灵活地处理图像,并根据实际需求进行算法优化。
原文地址: https://www.cveoy.top/t/topic/jSdW 著作权归作者所有。请勿转载和采集!