opencv 线段相关的函数

在opencv求得直线段的时候,我们总想给线段长短排序,判断线段之间的夹角,求两直线的交点,求两直线的距离,求点线距离,求垂线,求平行线。
下面粘贴出我用的直线相关的函数。
一般情况下,x1,y1,x2,y2表示线段1,x3,y3,x4,y4表示线段2
Vec4f 类型的 line1也可以表示一个线段,其中line1[0],line1[1]表示一个线段断点的x,y
line1[2],line1[3]表示另一个端点。
LineFunction.h文件

#include <opencv2/opencv.hpp>

#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include "opencv2/core/core.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <time.h>
#include<algorithm>
using namespace cv;
using namespace cv::ml;
using namespace std;
extern  double Pointdistance(double  x1, double y1, double x2, double y2);
extern double lineslope(Vec4f line); 
extern double lineslope(double x1, double y1, double x2, double y2); 
extern double linelen(Vec4f line);
extern  double PointToSegDist(double x, double y, double x1, double y1, double x2, double y2);
extern  double PointToSegDist(double x, double y, Vec4f line);

extern  Point2f lineIntersection(Vec4f  line1, Vec4f line2, int& result);
extern Point2f lineVertical(Vec4f  line, Point2f p);
extern Point2f linePara(Vec4f  line, Point2f p);
extern double lineAngle(Vec4f line1, Vec4f line2);
extern double lineDist(Vec4f line1, Vec4f line2);
struct LenOrder
{
    int order;
    double len;
};
extern void lineSort(vector<Vec4f> line, vector<LenOrder>&order);

extern void ContoursLine(vector<Vec4f>& lineall, vector<Point> contours, double  distepsilon = 20);
extern void lineMerge(vector<Vec4f>&  lineall, double alfa = 8, double cita = 20);
extern bool ContoursRect(vector<Vec4f>&  lineall, vector<Point> contours, vector<Vec4f>&  lineRect, double LineDistTh = 500, double LineLenTh = 400, double LineAngleTh = 8);

cpp文件

#include   "LineFunction.h"

#include <opencv2/opencv.hpp>
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include "opencv2/core/core.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <time.h>
#include<algorithm>
using namespace cv;
using namespace cv::ml;
using namespace std;


double Pointdistance(double  x1, double y1, double x2, double y2)
{//返回点点距离
    return         sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2));
}
double lineslope(Vec4f line)
{//斜率 返回弧度  
    double dsx = line[0] - line[2];
    double dsy = line[1] - line[3] + DBL_MIN;
    //cout << "dsx" << dsx << "dsy" << dsy << "atan2" << atan2(dsx, dsy) << endl;
    return atan(dsy / dsx); //注意,antan2函数会返回带象限的方向
}
double lineslope(double x1, double y1, double x2, double y2)
{//斜率 返回弧度  
    double dsx = x1 - x2;
    double dsy = y1 - y2 + DBL_MIN;
    return atan(dsy / dsx); //注意,antan2函数会返回带象限的方向
}
double linelen(Vec4f line)
{  //线段长度
    double  x1 = line[0];
    double y1 = line[1];
    double x2 = line[2];
    double y2 = line[3];
    return         sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2));
}
int MyInterSec(double X1, double Y1, double X2, double Y2, double X3, double Y3, double X4, double Y4, double &x, double &y)
{//相交在前线上return 1,后线return 2,交于外面return 3,不相交return 0 
    //这部分不单独使用,一般用后面的函数 lineIntersection(Vec4f  line1, Vec4f line2, int& result)
    double k1, k2;
    if ((X1 == X2) && (Y1 == Y2) && (Y3 == Y4) && (X3 == X4))
    {
        return 0;
    }
    if ((X1 == X2) && (Y1 == Y2))
    {
        if ((X3 == X4) && (X1 == X3))
        {
            x = X1;
            y = Y1;
            return 1;
        }
        else if (Y2 == ((X2 - X3)*(Y4 - Y3) / (X4 - X3) + Y3))
        {
            x = X1;
            y = Y1;
            return 1;
        }
    }
    if ((Y3 == Y4) && (X3 == X4))
    {
        if ((X2 == X1) && (X1 == X3))
        {
            x = X3;
            y = Y3;
            return 2;
        }
        else if (Y3 == ((X3 - X1)*(Y2 - Y1) / (X2 - X1) + Y1))
        {
            x = X3;
            y = Y3;
            return 2;
        }
    }
    if (X1 != X2)
    {
        k1 = (Y2 - Y1) / (X2 - X1);
        if (X3 != X4)
        {
            k2 = (Y4 - Y3) / (X4 - X3);
            if (k1 == k2)
            {
                return 0;
            }
            x = (Y3 - Y1 - k2*X3 + X1*k1) / (k1 - k2);
            y = k1*(x - X1) + Y1;
            if (((X1 - x)*(X2 - x)<0 || (X1 - x)*(X2 - x) == 0) && ((Y1 - y)*(Y2 - y)<0 || (Y1 - y)*(Y2 - y) == 0))
                return 1;
            if (((X3 - x)*(X4 - x)<0 || (X3 - x)*(X4 - x) == 0) && ((Y3 - y)*(Y4 - y)<0 || (Y3 - y)*(Y4 - y) == 0))
                return 2;
            if ((X3 - x)*(X4 - x)>0 && (Y3 - y)*(Y4 - y)>0 && (X1 - x)*(X2 - x)>0 && (Y1 - y)*(Y2 - y)>0)
                return 3;
        }
        if (X3 == X4)
        {
            x = X3;
            y = k1*(X3 - X1) + Y1;
            return 1;
        }
    }
    else
    {
        if (X3 != X4)
        {
            k2 = (Y4 - Y3) / (X4 - X3);
            x = double(X1);
            y = k2*(X1 - X3) + Y3;
            return 2;
        }
        if (X3 == X4)
        {
            return 0;
        }
    }
    return 0;
}
Point2f lineIntersection(Vec4f  line1, Vec4f line2, int& result)
{   //求垂点
    double x, y;
    //cout << line1[0] << "," << line1[1] << "," << line1[2] << "," << line1[3] << endl;
    //cout << line2[0] << "," << line2[1] << "," << line2[2] << "," << line2[3] << endl;
    result = MyInterSec(line1[0], line1[1], line1[2], line1[3], line2[0], line2[1], line2[2], line2[3], x, y);
    if (result)
        return Point2f(x, y);
    return Point2f(-1, -1);

}
Point2f lineVertical(Vec4f  line, Point2f p)
{   //求过直线外一点的垂点
    Point2f result;
    float A, B, C;
    A = (line[3] - line[1]) / (line[2] - line[0] + DBL_MIN);
    B = -1;
    C = -A*line[0] + line[1];
    //double tmp = A *  A + B *  B;
    //result.x = (B *  B * p.x - A *  B * p.y - A *  C) / tmp;
    //result.y = (A *  A * p.y - A *  B * p.x - B *  C) / tmp;
    result.x = (A* p.y - A*C + p.x)/(A*A+1);
    result.y = result.x *A + C; 
    return result;
}
Point2f linePara(Vec4f  line, Point2f p)
{   //求过点p平行线 ()
    Point2f result;
    float k;
    k = (line[3] - line[1]) / (line[2] - line[0] + DBL_MIN);
    result.x = 100.1;
    result.y = k*(100 - p.x) + p.y;
    if (fabs(k) < 0.01)
        result.y = p.y + 100;//竖线
    return result;
}
double PointToSegDist(double x, double y, double x1, double y1, double x2, double y2)
{   //返回点线距离 其中x1y1,x2y2是线段
    double k = (y2 - y1) / (x2 - x1 + 0.0000000000001);
    double  b = y1 - k*x1;
    return  abs(k*x - y + b) / sqrt(1 + k*k);


}
double PointToSegDist(double x, double y, Vec4f line)
{   //返回点线距离  
    double  x1 = line[0];
    double y1 = line[1];
    double x2 = line[2];
    double y2 = line[3];
    double k = (y2 - y1) / (x2 - x1 + 0.0000000000001);
    double  b = y1 - k*x1;
    return  abs(k*x - y + b) / sqrt(1 + k*k);

}
double lineAngle(Vec4f line1, Vec4f line2)
{   //返回线段夹角
    //余弦定理 //这个angle给的是最小的夹角,如果要0-180的夹角请修改返回值得方法
    double cosfi = 0, fi = 0, norm = 0;
    double dsx = line1[0] - line1[2];
    double dsy = line1[1] - line1[3];
    double dex = line2[0] - line2[2];
    double dey = line2[1] - line2[3];
    cosfi = dsx * dex + dsy * dey;
    norm = (dsx * dsx + dsy * dsy) * (dex * dex + dey * dey);
    cosfi /= sqrt(norm);

    if (cosfi >= 1.0) return 0;
    if (cosfi <= -1.0) return 0;
    fi = acos(cosfi);

    if (180 * fi / CV_PI <90)
    {
        return 180 * fi / CV_PI;
    }
    else
    {
        return 180 - 180 * fi / CV_PI;
    }


}
double lineDist(Vec4f line1, Vec4f line2)
{//返回短线中点到长线中点的距离//由于有sort函数长直线放在第一个参数
    double   x1, x2, x, y1, y2, y;
    x1 = line1[0]; y1 = line1[1];
    x2 = line1[2]; y2 = line1[3];
    x = (line2[0] + line2[2]) / 2;
    y = (line2[1] + line2[3]) / 2;
    double k = (y2 - y1) / (x2 - x1 + 0.0000000000001);
    double  b = y1 - k*x1;
    return  abs(k*x - y + b) / sqrt(1 + k*k);

}
/线长排序//

bool sortMethod(const LenOrder &v1, const LenOrder &v2)
{
    return v1.len >v2.len;
}
void lineSort(vector<Vec4f> line, vector<LenOrder>&order)
{  
    //线长排序,输入line是一组直线段,输出的vector<LenOrder>&order是一组以直线长度从长到短排序的序列。
    //其中LenOrder结构的.order 是直线段在原来直线组里的下标,.len是该直线段的长度//
    //用法实例     假如有一组直线段 Stdlineall  类型(vector<Vec4f>) 
    //vector<LenOrder>Stdorder;   //1   
    //lineSort(Stdlineall, Stdorder);   //2
    //Stdlineall.at(Stdorder.at(0).order)  //最长的直线
    // Stdorder.at(0).order //最长的直线的长度
    order.clear();
    for (int i = 0; i < line.size(); i++)
    {
        LenOrder lo;
        lo.len = Pointdistance(line.at(i)[0], line.at(i)[1], line.at(i)[2], line.at(i)[3]);
        lo.order = i;
        order.push_back(lo);
    }
    sort(order.begin(), order.end(), sortMethod);
}
线段长排序

///后两个函数是Contours转化为线段的函数,可以直接不理会


void ContoursLine(vector<Vec4f>& lineall, vector<Point> contours, double  distepsilon)
{   //轮廓点拟合成线段组  第一个参数是输出的直线,第二个参数是输入的轮廓点集,第三个参数是线段合并的距离临界,一般取5-20
    vector<double> xcur, ycur;
    Vec4f linecur;

    int flag;
    int num = contours.size();
    for (int k = 0; k < num; k++)
    {
        for (; k < num&&xcur.size() < 5; k++)
        {
            xcur.push_back(contours.at(k).x);
            ycur.push_back(contours.at(k).y);
        }//不足五个点,补齐
        linecur[0] = xcur.at(0);
        linecur[1] = ycur.at(0);
        linecur[2] = xcur.at(xcur.size() - 1);
        linecur[3] = ycur.at(xcur.size() - 1);//首尾作为一条直线
        if (xcur.size() > 2)
        {
            for (int L = 1; L < xcur.size() - 1; L++)
            {
                if (PointToSegDist(xcur.at(L), ycur.at(L), linecur) > distepsilon)
                {
                    xcur.erase(xcur.begin());
                    ycur.erase(ycur.begin());
                    linecur[0] = xcur.at(0);
                    linecur[1] = ycur.at(0);
                    L = 1;
                }
            }//前五个点中寻找非共线点s
            if (xcur.size() > 2)
            {
                // 确定有三点或者以上的点共线后//
                flag = 1;
                for (k = k + 1; k < num&&flag; k++)  //往后寻找新点
                {
                    if (PointToSegDist(contours.at(k).x, contours.at(k).y, linecur) <= distepsilon)
                    {
                        xcur.push_back(contours.at(k).x);
                        ycur.push_back(contours.at(k).y);
                    }
                    else
                    {
                        linecur[2] = contours.at(k).x;
                        linecur[3] = contours.at(k).y;
                        for (int L = 1; L < xcur.size(); L++)
                        {
                            if (PointToSegDist(xcur.at(L), ycur.at(L), linecur) > distepsilon)
                            {
                                flag = 0;  //找到终点,停止外层循环
                                break;
                            }
                        }
                    }
                }//到这一步找完终点
                if (xcur.size() > 5)
                {
                    double A, B;
                    std::vector<Point> points;
                    for (int i = 0; i < xcur.size() - 1; i++)
                    {
                        points.push_back(Point(xcur.at(i), ycur.at(i)));
                    }
                    Vec4f linex;
                    fitLine(Mat(points), linex, CV_DIST_L2, 0, 0.01, 0.01);

                    A = linex[1] / linex[0];
                    B = linex[3] - A*linex[2];
                    if (fabs(A) <1)
                    {
                        linecur[0] = xcur.at(0);
                        linecur[1] = xcur.at(0)*A + B;
                        linecur[2] = xcur.at(xcur.size() - 1);
                        linecur[3] = xcur.at(xcur.size() - 1)*A + B;
                    }
                    else
                    {
                        linecur[0] = (ycur.at(0) - B) / A;
                        linecur[1] = ycur.at(0);
                        linecur[2] = (ycur.at(xcur.size() - 1) - B) / A;
                        linecur[3] = ycur.at(xcur.size() - 1);
                    }
                    lineall.push_back(linecur);
                    //找到终点,保存直线
                }
                xcur.clear();
                ycur.clear();
                //确定有三点或者以上的点共线后//
            }
        }// if size>2,确保线段长度足够
    }//外循环,线段提取

    //找出所有直线/   
}
void lineMerge(vector<Vec4f>&  lineall, double alfa,double cita)
{   //轮廓上的直线合并 (首尾相连的直线段s) //第一个参数是输入也是输出,第二个是角度范围,如可容忍直线的夹角为0-8度填写8 第三个是距离范围,是一条线段中点到另一条直线的距离,
    for (int L = 0; L < lineall.size() - 2; ++L)
    {

        Vec4f line1 = lineall.at(L);
        Vec4f line2 = lineall.at(L + 1);
        Vec4f linem;
        if (lineAngle(line1, line2) < alfa && lineDist(line1, line2) < cita)
        {
            double d13 = Pointdistance(line1[0], line1[1], line2[0], line2[1]);
            double d23 = Pointdistance(line1[2], line1[3], line2[0], line2[1]);
            double d24 = Pointdistance(line1[2], line1[3], line2[2], line2[3]);
            double d14 = Pointdistance(line1[0], line1[1], line2[2], line2[3]);
            double d12 = linelen(line1);
            double d34 = linelen(line2);
            if (d14 >= d13 && d14 >= d23 && d14 >= d24  &&   d14 >= d12&&d14 >= d34)
            {
                linem[0] = line1[0];  //14最长
                linem[1] = line1[1];
                linem[2] = line2[2];
                linem[3] = line2[3];

            }
            else if (d13 >= d23&&d13 >= d24&&d13 >= d14&&d13 >= d12&&d13 >= d34)
            {
                linem[0] = line1[0];  //13最长
                linem[1] = line1[1];
                linem[2] = line2[0];
                linem[3] = line2[1];
            }
            else if (d23 >= d13&&d23 >= d24&&d23 >= d14&&d23 >= d12&&d23 >= d34)
            {
                linem[0] = line1[2];  //23最长
                linem[1] = line1[3];
                linem[2] = line2[0];
                linem[3] = line2[1];
            }
            else if (d24 >= d13&&d24 >= d23&&d24 >= d14&&d24 >= d12&&d24 >= d34)
            {
                linem[0] = line1[2];  //24最长
                linem[1] = line1[3];
                linem[2] = line2[2];
                linem[3] = line2[3];
            }
            else if (d12 >= d13&&d12 >= d23&&d12 >= d24&&d12 >= d14&&d12 >= d34)
            {
                linem = line1;
            }
            else
                linem = line2;

            lineall[L] = linem;
            lineall.erase(lineall.begin() + L + 1);
        }
        else
        {
            line2 = lineall.at(L + 2);
            if (lineAngle(line1, line2) < alfa && lineDist(line1, line2) < cita)
            {
                double d13 = Pointdistance(line1[0], line1[1], line2[0], line2[1]);
                double d23 = Pointdistance(line1[2], line1[3], line2[0], line2[1]);
                double d24 = Pointdistance(line1[2], line1[3], line2[2], line2[3]);
                double d14 = Pointdistance(line1[0], line1[1], line2[2], line2[3]);
                double d12 = linelen(line1);
                double d34 = linelen(line2);
                if (d14 >= d13 && d14 >= d23 && d14 >= d24  &&   d14 >= d12&&d14 >= d34)
                {
                    linem[0] = line1[0];  //14最长
                    linem[1] = line1[1];
                    linem[2] = line2[2];
                    linem[3] = line2[3];

                }
                else if (d13 >= d23&&d13 >= d24&&d13 >= d14&&d13 >= d12&&d13 >= d34)
                {
                    linem[0] = line1[0];  //13最长
                    linem[1] = line1[1];
                    linem[2] = line2[0];
                    linem[3] = line2[1];
                }
                else if (d23 >= d13&&d23 >= d24&&d23 >= d14&&d23 >= d12&&d23 >= d34)
                {
                    linem[0] = line1[2];  //23最长
                    linem[1] = line1[3];
                    linem[2] = line2[0];
                    linem[3] = line2[1];
                }
                else if (d24 >= d13&&d24 >= d23&&d24 >= d14&&d24 >= d12&&d24 >= d34)
                {
                    linem[0] = line1[2];  //24最长
                    linem[1] = line1[3];
                    linem[2] = line2[2];
                    linem[3] = line2[3];
                }
                else if (d12 >= d13&&d12 >= d23&&d12 >= d24&&d12 >= d14&&d12 >= d34)
                {
                    linem = line1;
                }
                else
                    linem = line2;

                lineall[L] = linem;
                lineall.erase(lineall.begin() + L + 2);

            }
        }//else

    }//for

    /后两根直线的处理
    if (lineall.size()>1)
    {
        int L = lineall.size() - 2;
        Vec4f line1 = lineall.at(L);
        Vec4f line2 = lineall.at(L + 1);
        Vec4f linem;
        if (lineAngle(line1, line2) < alfa && lineDist(line1, line2) < cita)
        {
            double d13 = Pointdistance(line1[0], line1[1], line2[0], line2[1]);
            double d23 = Pointdistance(line1[2], line1[3], line2[0], line2[1]);
            double d24 = Pointdistance(line1[2], line1[3], line2[2], line2[3]);
            double d14 = Pointdistance(line1[0], line1[1], line2[2], line2[3]);
            double d12 = linelen(line1);
            double d34 = linelen(line2);
            if (d14 >= d13 && d14 >= d23 && d14 >= d24  &&   d14 >= d12&&d14 >= d34)
            {
                linem[0] = line1[0];  //14最长
                linem[1] = line1[1];
                linem[2] = line2[2];
                linem[3] = line2[3];

            }
            else if (d13 >= d23&&d13 >= d24&&d13 >= d14&&d13 >= d12&&d13 >= d34)
            {
                linem[0] = line1[0];  //13最长
                linem[1] = line1[1];
                linem[2] = line2[0];
                linem[3] = line2[1];
            }
            else if (d23 >= d13&&d23 >= d24&&d23 >= d14&&d23 >= d12&&d23 >= d34)
            {
                linem[0] = line1[2];  //23最长
                linem[1] = line1[3];
                linem[2] = line2[0];
                linem[3] = line2[1];
            }
            else if (d24 >= d13&&d24 >= d23&&d24 >= d14&&d24 >= d12&&d24 >= d34)
            {
                linem[0] = line1[2];  //24最长
                linem[1] = line1[3];
                linem[2] = line2[2];
                linem[3] = line2[3];
            }
            else if (d12 >= d13&&d12 >= d23&&d12 >= d24&&d12 >= d14&&d12 >= d34)
            {
                linem = line1;
            }
            else
                linem = line2;
            lineall[L] = linem;
            lineall.erase(lineall.begin() + L + 1);
        }
    }
    //最后一根和第一根
    if (lineall.size()>1)
    {
        int L = lineall.size() - 2;
        Vec4f line1 = lineall.at(L+1);
        Vec4f line2 = lineall.at(0);
        Vec4f linem;
        if (lineAngle(line1, line2) < alfa && lineDist(line1, line2) < cita)
        {
            double d13 = Pointdistance(line1[0], line1[1], line2[0], line2[1]);
            double d23 = Pointdistance(line1[2], line1[3], line2[0], line2[1]);
            double d24 = Pointdistance(line1[2], line1[3], line2[2], line2[3]);
            double d14 = Pointdistance(line1[0], line1[1], line2[2], line2[3]);
            double d12 = linelen(line1);
            double d34 = linelen(line2);
            if (d14 >= d13 && d14 >= d23 && d14 >= d24  &&   d14 >= d12&&d14 >= d34)
            {
                linem[0] = line1[0];  //14最长
                linem[1] = line1[1];
                linem[2] = line2[2];
                linem[3] = line2[3];

            }
            else if (d13 >= d23&&d13 >= d24&&d13 >= d14&&d13 >= d12&&d13 >= d34)
            {
                linem[0] = line1[0];  //13最长
                linem[1] = line1[1];
                linem[2] = line2[0];
                linem[3] = line2[1];
            }
            else if (d23 >= d13&&d23 >= d24&&d23 >= d14&&d23 >= d12&&d23 >= d34)
            {
                linem[0] = line1[2];  //23最长
                linem[1] = line1[3];
                linem[2] = line2[0];
                linem[3] = line2[1];
            }
            else if (d24 >= d13&&d24 >= d23&&d24 >= d14&&d24 >= d12&&d24 >= d34)
            {
                linem[0] = line1[2];  //24最长
                linem[1] = line1[3];
                linem[2] = line2[2];
                linem[3] = line2[3];
            }
            else if (d12 >= d13&&d12 >= d23&&d12 >= d24&&d12 >= d14&&d12 >= d34)
            {
                linem = line1;
            }
            else
                linem = line2;
            lineall[L] = linem;
            lineall.erase(lineall.begin() );
        }
    }

}
bool ContoursRect(vector<Vec4f>&  lineall, vector<Point> contours, vector<Vec4f>&  lineRect, double LineDistTh, double LineLenTh, double LineAngleTh)
{   //优点:能减少部分外点
    lineRect.clear();
    vector<LenOrder> order;
    vector<Vec4f> lineTem;
    lineSort(lineall, order);
    int found = 0;
    Vec4f  line1, line2;
    for (int L = 0; L < order.size(); L++)
    {
        line1 = lineall.at(order.at(L).order);
        for (int K = L + 1; K < order.size(); K++)
        {
            line2 = lineall.at(order.at(K).order);
            if (lineAngle(line1, line2) < LineAngleTh&&lineDist(line1, line2) > LineDistTh&& order.at(L).len > LineLenTh)
            {

                found = 1;
                break;
            }
        }
        if (found)
            break;

    }
    if (found)
    {
        //cout << "line1[0]" << line1[0] << " line1[1]" << line1[1] << "line1[2]" << line1[2] << " line1[3] " << line1[3] << endl;
        //cout << "line2[0]" << line2[0] << " line2[1]" << line2[1] << "line2[2]" << line2[2] <<" line2[3] "<< line2[3] << endl;
        Point2f Pt1 = Point2f(line2[0] / 2 + line2[2] / 2, line2[1] / 2 + line2[3] / 2);
        Point2f Pt2 = lineVertical(line1, Pt1);
        Vec4f lineMed;
        lineMed[0] = Pt1.x;
        lineMed[1] = Pt1.y;
        lineMed[2] = Pt2.x;
        lineMed[3] = Pt2.y;
        double Maxdist = 0;
        Point2f Pt3;
        for (int i = 0; i < contours.size(); i++)
        {
            if (PointToSegDist(contours.at(i).x, contours.at(i).y, lineMed) > Maxdist)
            {
                Maxdist = PointToSegDist(contours.at(i).x, contours.at(i).y, lineMed);
                Pt3 = contours.at(i);
            }
        }
        Point2f Pt4 = lineVertical(line1, Pt3);
        Point2f Pt5 = lineVertical(line2, Pt3);
        Vec4f line3;
        line3[0] = Pt4.x;
        line3[1] = Pt4.y;
        line3[2] = Pt5.x;
        line3[3] = Pt5.y;
        Maxdist = 0;
        Point2f Pt6;
        for (int i = 0; i < contours.size(); i++)
        {
            if (PointToSegDist(contours.at(i).x, contours.at(i).y, line3) > Maxdist)
            {
                Maxdist = PointToSegDist(contours.at(i).x, contours.at(i).y, line3);
                Pt6 = contours.at(i);
            }
        }
        Point2f Pt7 = lineVertical(line1, Pt6);
        Point2f Pt8 = lineVertical(line2, Pt6);
        line1[0] = Pt4.x;
        line1[1] = Pt4.y;
        line1[2] = Pt7.x;
        line1[3] = Pt7.y;
        lineTem.push_back(line1);
        line1[0] = Pt5.x;
        line1[1] = Pt5.y;
        line1[2] = Pt8.x;
        line1[3] = Pt8.y;
        lineTem.push_back(line1);
        lineTem.push_back(line3);
        line1[0] = Pt7.x;
        line1[1] = Pt7.y;
        line1[2] = Pt8.x;
        line1[3] = Pt8.y;
        lineTem.push_back(line1);
        if (linelen(lineTem[0]) > linelen(lineTem[2]))
        {
            lineRect = lineTem;
        }
        else
        {
            lineRect.push_back(lineTem[2]);
            lineRect.push_back(lineTem[3]);
            lineRect.push_back(lineTem[0]);
            lineRect.push_back(lineTem[1]);
        }

        return 1;
    }
    else
        return 0;

}
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
摘要: 本文旨在帮助读者快速入门OpenCV,而无需阅读冗长的参考手册。掌握了OpenCV的以下基础知识后,有需要的话再查阅相关的参考手册。 目录  [隐藏] 1 一、简介 1.1 1、OpenCV的特点 1.1.1 (1) 总体描述 1.1.2 (2) 功能 1.1.3 (3) OpenCV模块 1.2 2、有用的学习资源 1.2.1 (1) 参考手册: 1.2.2 (2) 网络资源: 1.2.3 (3) 书籍: 1.2.4 (4) 视频处理例程(在 /samples/c/): 1.2.5 (5) 图像处理例程 (在 /samples/c/): 1.3 3、OpenCV 命名规则 1.3.1 (1) 函数名: 1.3.2 (2) 矩阵数据类型: 1.3.3 (3) 图像数据类型: 1.3.4 (4) 头文件: 1.4 4、编译建议 1.4.1 (1) Linux: 1.4.2 (2) Windows: 1.5 5、C例程 2 二、GUI 指令 2.1 1、窗口管理 2.1.1 (1) 创建和定位一个新窗口: 2.1.2 (2) 载入图像: 2.1.3 (3) 显示图像: 2.1.4 (4) 关闭窗口: 2.1.5 (5) 改变窗口大小: 2.2 2、输入处理 2.2.1 (1) 处理鼠标事件: 2.2.2 (2) 处理键盘事件: 2.2.3 (3) 处理滑动条事件: 3 三、OpenCV的基本数据结构 3.1 1、图像数据结构 3.1.1 (1) IPL 图像: 3.2 2、矩阵与向量 3.2.1 (1) 矩阵: 3.2.2 (2) 一般矩阵: 3.2.3 (3) 标量: 3.3 3、其它结构类型 3.3.1 (1) 点: 3.3.2 (2) 矩形框大小(以像素为精度): 3.3.3 (3) 矩形框的偏置和大小: 4 四、图像处理 4.1 1、图像的内存分配与释放 4.1.1 (1) 分配内存给一幅新图像: 4.1.2 (2) 释放图像: 4.1.3 (3) 复制图像: 4.1.4 (4) 设置/获取感兴趣区域ROI: 4.1.5 (5) 设置/获取感兴趣通道COI: 4.2 2、图像读写 4.2.1 (1) 从文件中读入图像: 4.2.2 (2) 保存图像: 4.3 3、访问图像像素 4.3.1 (1) 假设你要访问第k通道、第i行、第j列的像素。 4.3.2 (2) 间接访问: (通用,但效率低,可访问任意格式的图像) 4.3.3 (3) 直接访问: (效率高,但容易出错) 4.3.4 (4) 基于指针的直接访问: (简单高效) 4.3.5 (5) 基于 c++ wrapper 的直接访问: (更简单高效) 4.4 4、图像转换 4.4.1 (1) 字节型图像的灰度-彩色转换: 4.4.2 (2) 彩色图像->灰度图像: 4.4.3 (3) 不同彩色空间之间的转换: 4.5 5、绘图指令 4.5.1 (1) 绘制矩形: 4.5.2 (2) 绘制圆形: 4.5.3 (3) 绘制线段: 4.5.4 (4) 绘制一组线段: 4.5.5 (5) 绘制一组填充颜色的多边形: 4.5.6 (6) 文本标注: 5 五、矩阵处理 5.1 1、矩阵的内存分配与释放 5.1.1 (1) 总体上: 5.1.2 (2) 为新矩阵分配内存: 5.1.3 (3) 释放矩阵内存: 5.1.4 (4) 复制矩阵: 5.1.5 (5) 初始化矩阵: 5.1.6 (6) 初始化矩阵为单位矩阵: 5.2 2、访问矩阵元素 5.2.1 (1) 假设需要访问一个2D浮点型矩阵的第(i, j)个单元. 5.2.2 (2) 间接访问: 5.2.3 (3) 直接访问(假设矩阵数据按4字节行对齐): 5.2.4 (4) 直接访问(当数据的行对齐可能存在间隙时 possible alignment gaps): 5.2.5 (5) 对于初始化后的矩阵进行直接访问: 5.3 3、矩阵/向量运算 5.3.1 (1) 矩阵之间的运算: 5.3.2 (2) 矩阵之间的元素级运算: 5.3.3 (3) 向量乘积: 5.3.4 (4) 单一矩阵的运算: 5.3.5 (5) 非齐次线性方程求解: 5.3.6 (6) 特征值与特征向量 (矩阵为方阵): 6 六、视频处理 6.1 1、从视频流中捕捉一帧画面 6.1.1 (1) OpenCV 支持从摄像头或视频文件(AVI格式)中捕捉帧画面. 6.1.2 (2) 初始化一个摄像头捕捉器: 6.1.3 (3) 初始化一个视频文件捕捉器: 6.1.4 (4) 捕捉一帧画面: 6.1.5 (5) 释放视频流捕捉器: 6.2 2、获取/设置视频流信息 6.2.1 (1) 获取视频流设备信息:
OpenCV中的HoughLines和HoughLinesP函数都是用于检测图像中的直线函数,其中HoughLinesP函数比HoughLines函数更加灵活,可以检测任意角度的直线,而HoughLines函数只能检测水平和垂直方向的直线。两个函数的参数含义如下: HoughLinesP函数: - image:输入的二值化图像。 - lines:输出的直线向量。 - rho:距离精度,以像素为单位。 - theta:角度精度,以弧度为单位。 - threshold:阈值参数,只有累加器中的值大于等于该值时,才认为是一条直线。 - minLineLength:线的最小长度,小于此长度的线将被忽略。 - maxLineGap:两条线段之间的最大间隔,小于此间隔的线段将被连接成一条直线。 HoughLines函数: - image:输入的二值化图像。 - lines:输出的直线向量。 - rho:距离精度,以像素为单位。 - theta:角度精度,以弧度为单位。 - threshold:阈值参数,只有累加器中的值大于等于该值时,才认为是一条直线。 - srn:默认值为0,表示没有任何缩放。如果不为0,则表示使用多尺度Hough变换,其中srn表示距离分辨率的缩放比例。 - stn:默认值为0,表示没有任何缩放。如果不为0,则表示使用多尺度Hough变换,其中stn表示角度分辨率的缩放比例。 - min_theta:表示检测到的直线的最小角度。 - max_theta:表示检测到的直线的最大角度。 下面是一个使用HoughLinesP函数检测图像中直线的例子: ```python import cv2 import numpy as np # 读取图像 img = cv2.imread('test.jpg') # 转换为灰度图像 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 边缘检测 edges = cv2.Canny(gray, 50, 150, apertureSize=3) # 检测直线 lines = cv2.HoughLinesP(edges, rho=1, theta=np.pi/180, threshold=100, minLineLength=100, maxLineGap=10) # 绘制直线 for line in lines: x1, y1, x2, y2 = line[0] cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2) # 显示结果 cv2.imshow('result', img) cv2.waitKey(0) cv2.destroyAllWindows() ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值