如何在C++(OpenCV)中基于给定四点绘制不规则填充区域?
实现带填充的不规则形状轮廓绘制
嘿,这个需求在OpenCV里实现起来很简单,我给你拆解成几个关键步骤,再附上完整的代码示例:
核心思路
要绘制带填充的不规则形状,我们只需要先把离散的点组织成OpenCV要求的轮廓数据结构,然后用填充函数直接在空白Mat上绘制即可——你说要忽略圆角,那完全不用额外处理,直接用原始点就行。
具体步骤
步骤1:整理轮廓点集
OpenCV的填充函数(比如fillPoly或drawContours)要求轮廓数据是vector<vector<cv::Point>>类型,也就是“多个轮廓的集合,每个轮廓由一组点组成”。我们先把你的四个点放进这个结构里:// 定义你的四个原始点 std::vector<cv::Point> contour_points = { cv::Point(3, 5), cv::Point(13, 9), cv::Point(1, 18), cv::Point(16, 22) }; // 包装成轮廓集合(这里只有一个轮廓) std::vector<std::vector<cv::Point>> contours; contours.push_back(contour_points);步骤2:创建空白画布(Mat)
你需要一个足够大的空白Mat来容纳这个形状。可以手动指定尺寸(比如比所有点的最大坐标大一点),也可以自动计算形状的边界框来确定尺寸,后者更灵活:// 自动计算轮廓的边界框,确定画布的最小尺寸 cv::Rect bounding_rect = cv::boundingRect(contour_points); // 创建带边距的空白彩色Mat,背景设为黑色(Scalar(0,0,0)) cv::Mat filled_shape = cv::Mat::zeros(bounding_rect.height + 10, bounding_rect.width + 10, CV_8UC3);步骤3:调整点坐标(可选但推荐)
因为我们是基于边界框创建的画布,原始点的坐标是相对于原图像的,所以需要把点偏移到画布的有效区域内:// 给点加上边距偏移,避免形状贴到画布边缘 for (auto& pt : contours[0]) { pt.x -= bounding_rect.x - 5; pt.y -= bounding_rect.y - 5; }步骤4:填充轮廓
这里有两种常用方法,效果完全一致,选你顺手的就行:
方法一:用fillPoly直接填充// 设置填充颜色,比如红色(OpenCV是BGR顺序,所以红色是Scalar(0,0,255)) cv::fillPoly(filled_shape, contours, cv::Scalar(0, 0, 255));方法二:用
drawContours填充(最后一个参数设为-1表示填充整个轮廓)cv::drawContours(filled_shape, contours, 0, cv::Scalar(0, 0, 255), -1);
完整可运行代码
把上面的步骤整合起来,完整代码如下:
#include <opencv2/opencv.hpp> #include <vector> int main() { // 1. 准备轮廓点 std::vector<cv::Point> contour_points = { cv::Point(3, 5), cv::Point(13, 9), cv::Point(1, 18), cv::Point(16, 22) }; std::vector<std::vector<cv::Point>> contours; contours.push_back(contour_points); // 2. 创建带边距的空白画布 cv::Rect bounding_rect = cv::boundingRect(contour_points); cv::Mat filled_shape = cv::Mat::zeros(bounding_rect.height + 10, bounding_rect.width + 10, CV_8UC3); // 3. 调整点坐标到画布范围内 for (auto& pt : contours[0]) { pt.x -= bounding_rect.x - 5; pt.y -= bounding_rect.y - 5; } // 4. 填充形状 cv::fillPoly(filled_shape, contours, cv::Scalar(0, 0, 255)); // 查看结果 cv::imshow("Filled Irregular Shape", filled_shape); cv::waitKey(0); cv::destroyAllWindows(); // 保存结果(可选) cv::imwrite("filled_shape.png", filled_shape); return 0; }
小提示
- 如果需要绘制灰度图,把Mat的类型改成
CV_8UC1,填充颜色用Scalar(255)表示白色即可。 - OpenCV会自动把轮廓的最后一个点和第一个点连接起来,你不需要手动闭合形状。
内容的提问来源于stack exchange,提问作者user9590073
相关产品推荐
相关产品推荐

