OpenCV坐标计算辅助

OpenCV坐标计算辅助,其它情况可修改数点(cv::Point)数据类型以适用。
用于一些坐标计算的辅助类,算法来源于初高中数学老师和互联网,后期整理出处。

头信息

#include 
#include 
namespace CVG  {
...
}

角度(三点两线段角度计算)

/**
 角度

 @param pt1 端点
 @param pt2 端点
 @param pt0 交点
 @return 角度
 */
double CVG::angle(cv::Point pt1, cv::Point pt2, cv::Point pt0) {
    double dx1 = pt1.x - pt0.x;
    double dy1 = pt1.y - pt0.y;
    double dx2 = pt2.x - pt0.x;
    double dy2 = pt2.y - pt0.y;
    return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}

中心点(线段中心点)

/**
 中心点

 @param pt0 端点
 @param pt1 端点
 @return 端点
 */
cv::Point CVG::center(cv::Point pt0, cv::Point pt1) {
    cv::Point pt;
    pt.x = (pt0.x+pt1.x)/2 + 0.5;
    pt.y = (pt0.y+pt1.y)/2 + 0.5;
    return pt;
}

距离(线段长度)

/**
 距离长度

 @param pt0 端点
 @param pt1 端点
 @return 距离长度
 */
double CVG::length( cv::Point pt0, cv::Point pt1) {
    double dist_x = pt0.x - pt1.x;
    double dist_y = pt0.y - pt1.y;
    return sqrt(pow(dist_x, 2)+pow(dist_y, 2));
}

多边形中心点(重心)

/**
 多边形中心点

 @param pts 多边形坐标,环形分布
 @return 中心点
 */
cv::Point CVG::center(std::vector &pts) {
    long n = pts.size();
    cv::Point pt_c;
    if (n==0) {
        return pt_c;
    }
    long sum_x = 0, sum_y = 0;
    for (int i = 0; i < n; i ++) {
        cv::Point pt = pts[i];
        sum_x += pt.x;
        sum_y += pt.y;
    }
    pt_c.x = (int)(sum_x / n + 0.5);
    pt_c.y = (int)(sum_y / n + 0.5);
    return pt_c;
}

两线段交点(不存在返回极大值点)

/**
 两线段交点
 
 @param l0p0 线段0端点
 @param l0p1 线段0端点
 @param l1p0 线段1端点
 @param l1p1 线段1端点
 @return 交点
 */
cv::Point CVG::intersects(cv::Point l0p0, cv::Point l0p1, cv::Point l1p0, cv::Point l1p1) {
    int delta, r, u;
    cv::Point p;//交点
    delta = (l0p1.x - l0p0.x) * (l1p0.y - l1p1.y) - (l1p0.x - l1p1.x) * (l0p1.y - l0p0.y);
    if(delta == 0)  {
        p.x = INT_MAX;
        p.y = INT_MAX;
    }  else {
        r = ((l1p0.x - l0p0.x) * (l1p0.y - l1p1.y) - (l1p0.x - l1p1.x) * (l1p0.y - l0p0.y)) / delta;
        u = ((l0p1.x - l0p0.x) * (l1p0.y - l0p0.y) - (l1p0.x - l0p0.x) * (l0p1.y - l0p0.y)) / delta;
        if((r >= 0 && r <= 1) && (u >= 0 && u <= 1))   {
            p.x = l0p0.x + r*(l0p1.x - l0p0.x);
            p.y = l0p0.y + r*(l0p1.y - l0p0.y);
        } else {
            p.x = INT_MAX;
            p.y = INT_MAX;
        }
    }
    return p;
}

线段延长点(from 到 to方向上扩张dist距离,返回新的to坐标)

/**
 线段延长点
 
 @param from 线段开始
 @param to 线段结束
 @param dist 延长距离
 @return 新的结束点
 */
cv::Point CVG::lineExp(cv::Point from, cv::Point to, double dist) {
    double dist_x = to.x - from.x;
    double dist_y = to.y - from.y;
    double s = dist/sqrt(pow(dist_x, 2)+pow(dist_y, 2))+1;
    cv::Point p;
    p.x = s*(dist_x)+from.x;
    p.y = s*(dist_y)+from.y;
    return p;
}

多边形扩张(凹边形未验证)以重心为原点向各个顶点方向进行扩张

/**
 多边形扩张

 @param pts 多边形坐标,环形分布
 @param dist 扩张距离(中心点方向)
 @return 新坐标
 */
std::vector CVG::shapeExp(std::vector &pts, double dist) {
    cv::Point pt_c = CVG::center(pts);
    std::vector pts_n;
    for (int i = 0; i < pts.size(); i ++) {
        cv::Point pt = cv::Point(pts[i].x, pts[i].y);
        double dist_x = pt.x - pt_c.x;
        double dist_y = pt.y - pt_c.y;
        double ratio = dist/sqrt(pow(dist_x, 2)+pow(dist_y, 2))+1;
        pt.x = ratio * (dist_x)+0.5 + pt_c.x;
        pt.y = ratio * (dist_y)+0.5 + pt_c.y;
        pts_n.push_back(pt);
    }
    return pts_n;
}

多边形平移(对于矫正前的平移处理可能需要进行多次)

/**
 多边形平移
 
 @param pts 多边形坐标,环形分布
 @param offset 偏移量
 @return 新坐标
 */
std::vector CVG::shapeMove(std::vector &pts, cv::Point offset) {
    std::vector pts_n;
    for (int i = 0; i

多边形旋转(以重心为原点对各个顶点坐标进行旋转,旋转角度:a/180.0*M_PI )

/**
 多边形旋转
 
 @param pts 多边形坐标,环形分布
 @param angle 旋转角度(正逆时针,负顺时针)
 @return 新坐标
 
 点(x,y)绕(x0,y0)逆时针旋转a角后变成(x',y'),则
 x'-x0=(x-x0)cosa-(y-y0)sina
 y'-y0=(x-x0)sina+(y-y0)cosa
 */
std::vector CVG::shapeRotate(std::vector &pts, double angle) {
    cv::Point pt_c = CVG::center(pts);
    std::vector pts_n;

    double sa = sin(angle);
    double ca = cos(angle);
    for (int i = 0; i

多边形凹凸性检查

/**
 多边形凹凸性检查

 @param pts 多边形坐标,环形分布
 @return -1 凸集, 1凹集, 0 不合法
 */
int CVG::shapeConvex(std::vector &pts) {
    long i,j,k;
    int flag = 0;
    int z;
    long n = pts.size();
    if (n < 3)
        return 0;
    for (i=0;i 0)
            flag |= 2;
        if (flag==3)
            return -1;//凸集
    }
    if (flag != 0) //凹集
        return 1;
    else
        return 0; //不合法
}

点与多边形关系,采用铅垂线法

/**
 点与多边形关系
 
 @param pts 多边形坐标,环形分布
 @param pt 点
 @return true多边形上, fale多边形外
 */
bool CVG::inside(std::vector &pts, cv::Point pt) {
    int n = 0;
    int min_y = INT_MAX;
    for (int i = 0; i=pt0.x && pt.x<=pt1.x) || (pt.x>=pt1.x && pt.x<=pt0.x)) {
            cv::Point pi = CVG::intersects(pt, pt_min, pt0, pt1);
            if (pi.x != INT_MAX && pi.y != INT_MAX) {
                n++;
            }
        }
    }
    return n%2 != 0;
}

来一个今天新写的函数(有bug请留言)
统计多边形凹点坐标

/**
 多边形凹点下标
 
 @param pts 多边形坐标,环形分布
 @return 凹点下标
 */
std::vector CVG::pits(std::vector &pts) {
    int min_y = INT_MAX;
    for (int i = 0; i ipts;
    long ct = pts.size();
    for (long i = 0; i < ct; i++) {
        long i_2 = i+2;
        if (i_2 >= ct) {
            i_2 -= ct;
        }
        cv::Point pt = CVG::center(pts[i], pts[i_2]);
        CVG::inside(pts, pt);
        
        cv::Point pt_min = cv::Point(pt.x, min_y);
        int ipt_ct = 0;
        for (int i = 0; i=pt0.x && pt.x<=pt1.x) || (pt.x>=pt1.x && pt.x<=pt0.x)) {
                cv::Point pi = CVG::intersects(pt, pt_min, pt0, pt1);
                if (pi.x != INT_MAX && pi.y != INT_MAX) {
                    ipt_ct++;
                }
            }
        }
        if (ipt_ct%2 == 0) {
            long ipt_idx = i+1;
            if (ipt_idx >= ct) {
                ipt_idx -= ct;
            }
            ipts.push_back(ipt_idx);
        }
    }
    return ipts;
}

其它常用计算发掘中,欢迎各位提供其它计算方式,一起整合资源。
函数计算有误或精度误差的还请留言提醒,不胜感激!

你可能感兴趣的:(OpenCV坐标计算辅助)