(opencv)任意四边形网格划分

1 算法介绍

算法功能:用于对任意四边形进行网格化处理
输入:四边形的四个角点(类型为cv::Point),网格行数,网格列数
输出:网格交叉点点集或网格中心点点集(类型为std::vector< cv::Point > )

效果如下:
vector gridret=Gridding(TEST_P0,TEST_P1,TEST_P2,TEST_P3,3,5,1);
在这里插入图片描述
vector gridret=Gridding(TEST_P0,TEST_P1,TEST_P2,TEST_P3,3,5,2);
在这里插入图片描述
vector gridret=Gridding(TEST_P0,TEST_P1,TEST_P2,TEST_P3,3,5,1,1,1,1,1);
在这里插入图片描述

2 源码

2.1 命名空间声明和函数声明

// P0到P3为任意四边形角点,顺时针或逆时针排布均可 
// rows为四边形内想要计算的网格行数,cols为列数。
// mode为返回参数格式:mode=1 时函数返回网格角点,mode=2 时函数返回网格中心点
// 最后四个参数为网格向外扩展参数,缺省值全为0,表示计算的网格全部位于四边形内部
using namespace std; 
using namespace cv;
vector<Point> Gridding(Point P0,Point P1,Point P2,Point P3,\
                                int rows,int cols,int mode,\
         int upex=0,int downex=0,int leftex=0,int rightex=0);  //网格化函数

2.1 函数实现

//四边形网格化
vector<Point> Gridding(Point P0,Point P1,Point P2,Point P3,\
                       int rows,int cols,int mode,\
                       int upex,int downex,int leftex,int rightex)
{
    vector<Point> pointvector01; //在P0和P1方向上创建等距点
    vector<Point> pointvector12; //在P1和P2方向上创建等距点
    vector<Point> pointvector32; //在P3和P2方向上创建等距点
    vector<Point> pointvector03; //在P0和P3方向上创建等距点
    vector<Point> pointvector; //
    for(int j=0-leftex;j<cols+1+rightex;j++){
        Point point;
        point.x = P0.x+(P1.x-P0.x)*j/cols;
        point.y = P0.y+(P1.y-P0.y)*j/cols;
        pointvector01.push_back(point);
    }
    for(int j=0-upex;j<rows+1+downex;j++){
        Point point;
        point.x = P1.x+(P2.x-P1.x)*j/rows;
        point.y = P1.y+(P2.y-P1.y)*j/rows;
        pointvector12.push_back(point);}
    for(int j=0-leftex;j<cols+1+rightex;j++){
        Point point;
        point.x = P3.x+(P2.x-P3.x)*j/cols;
        point.y = P3.y+(P2.y-P3.y)*j/cols;
        pointvector32.push_back(point);
    }
    for(int j=0-upex;j<rows+1+downex;j++){
        Point point;
        point.x = P0.x+(P3.x-P0.x)*j/rows;
        point.y = P0.y+(P3.y-P0.y)*j/rows;
        pointvector03.push_back(point);
    }
    for(int i=0;i<rows+1+downex+upex;i++) //依次求得交叉点
        for(int j=0;j<cols+1+rightex+leftex;j++){
            Point point=CrossPoint(pointvector01.at(j),pointvector32.at(j),\
                                   pointvector03.at(i),pointvector12.at(i));
            pointvector.push_back(point);
        }
    return pointvector;
}

//计算两直线交点
Point CrossPoint(Point P1, Point P2, Point P3, Point P4)
{
    Point pt;
    double x1=P1.x,y1=P1.y;
    double x2=P2.x,y2=P2.y;
    double x3=P3.x,y3=P3.y;
    double x4=P4.x,y4=P4.y;
    double D = (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4);
    if (D == 0){
        pt.x=0;
        pt.y=0;
    }
    else{
        pt.x = ((x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4))/D;
        pt.y = ((x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4))/D;
    }
    return pt;
}
  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要拟合四边形,可以使用 OpenCV 中的函数 cv::approxPolyDP。该函数可以将给定的轮廓逼近为指定精度的多边形,因此可以用于拟合四边形。 以下是一个简单的示例代码,演示如何使用 cv::approxPolyDP 拟合四边形: ```c++ #include <opencv2/opencv.hpp> #include <iostream> int main() { cv::Mat image = cv::imread("input.jpg"); // 转换为灰度图像 cv::Mat gray; cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY); // 二值化 cv::Mat binary; cv::threshold(gray, binary, 128, 255, cv::THRESH_BINARY); // 查找轮廓 std::vector<std::vector<cv::Point>> contours; cv::findContours(binary, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); // 遍历每个轮廓 for (const auto& contour : contours) { // 拟合多边形 std::vector<cv::Point> polygon; cv::approxPolyDP(contour, polygon, 0.01 * cv::arcLength(contour, true), true); // 如果是四边形,则绘制轮廓 if (polygon.size() == 4) { cv::drawContours(image, std::vector<std::vector<cv::Point>>{polygon}, -1, cv::Scalar(0, 0, 255), 2); } } cv::imshow("output", image); cv::waitKey(0); return 0; } ``` 在上面的示例代码中,我们首先将输入图像转换为灰度图像,然后对其进行二值化。接下来,我们使用 cv::findContours 查找图像中的轮廓。对于每个轮廓,我们使用 cv::approxPolyDP 拟合多边形,并检查是否是四边形。如果是,则在原始图像上绘制轮廓。 请注意,这只是一个简单的示例代码,实际应用中可能需要进行更多的预处理和参数调整。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值