Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用opencv或python检测2条相交(交叉)曲线?_Python_Opencv - Fatal编程技术网

如何使用opencv或python检测2条相交(交叉)曲线?

如何使用opencv或python检测2条相交(交叉)曲线?,python,opencv,Python,Opencv,如下图所示,给定一个包含两条相交曲线的图像,如何使用opencv或python检测和区分这两条曲线?(所以我需要两条分开的曲线) 您可以扫描每一列,并从连接的部分识别其中的群集 伪算法: list of curves for each column if a pixel region is black, surrounded by white add it to the list of curves for which it continues the curve bes

如下图所示,给定一个包含两条相交曲线的图像,如何使用opencv或python检测和区分这两条曲线?(所以我需要两条分开的曲线)


您可以扫描每一列,并从连接的部分识别其中的群集

伪算法:

list of curves
for each column
    if a pixel region is black, surrounded by white
        add it to the list of curves for which it continues the curve best
最棘手的部分是,如何定义一条已经给定的曲线如何最好地继续。如果只选择到曲线最近点的距离,则在连接处会出现问题。 从曲线的上一点到最后一点创建一条直线到新点,并测量到曲线最后一点的距离,效果非常好。然而,由于测量的距离非常小(可能存在舍入问题等),我没有遍历所有列,而是只遍历每第五列

C++代码如下:

double distance_to_Line(cv::Point line_start, cv::Point line_end, cv::Point point)
{
    double normalLength = _hypot(line_end.x - line_start.x, line_end.y - line_start.y);
    double distance = (double)((point.x - line_start.x) * (line_end.y - line_start.y) - (point.y - line_start.y) * (line_end.x - line_start.x)) / normalLength;
    return abs(distance);
}

int main()
{
    cv::Mat in = cv::imread("C:/StackOverflow/Input/splitCurves.png", cv::IMREAD_GRAYSCALE);

    std::vector<std::vector <cv::Point2f> > clusters;
    float maxDist = 10.0f; //heuristic

    // looping like this is quite expensive, but we need to scan column-wise
    // will be cheaper to first transpose the image and then scan row-wise!!
    for (int x = 0; x < in.cols; x+=5)
    {
        bool active = false;
        cv::Point2f cCluster;
        int cClusterSupportSize = 0;
        for (int y = 0; y < in.rows; ++y)
        {
            cv::Point2f cPoint = cv::Point2f(x, y);
            bool cActive = in.at<unsigned char>(y,x) == 0; // is the pixel black?
            if (cActive)
            {
                cCluster += cPoint;
                cClusterSupportSize += 1;
                active = cActive;
            }

            if (active && !cActive)
            {
                // creating cluster:
                cv::Point2f finishedCluster = 1.0f / cClusterSupportSize * cCluster;

                cCluster = cv::Point2f();
                cClusterSupportSize = 0;
                active = false;

                // adding cluster to list
                int bestCluster = -1;
                float bestDist = FLT_MAX;
                for (int i = 0; i < clusters.size(); ++i)
                {
                    float distToClusters = FLT_MAX;

                    // compute dist from apprximating a line through the last two points of the curve
                    // special case: no 2 points yet:
                    if (clusters[i].size() == 1)
                    {
                        float cDist = cv::norm(finishedCluster - clusters[i].back());
                        if (cDist < distToClusters) distToClusters = cDist;
                    }
                    else
                    {
                        // test continuity by testing whether adding the new point would make the last point still be placed well on the curve
                        cv::Point2f lineA = clusters[i][clusters[i].size() - 1];
                        cv::Point2f lineB = clusters[i][clusters[i].size() - 2];
                        //cv::Point2f lineB = finishedCluster;
                        // get dist from the current point to that line:

                        float cDist =  distance_to_Line(lineA, lineB, finishedCluster);
                        if (cDist < distToClusters) distToClusters = cDist;
                    }



                    /*
                    for (int j = 0; j < clusters[i].size(); ++j)
                    {
                        // get dist to the curve
                        cv::Point2f lineA = 
                        //float cDist = cv::norm(finishedCluster - clusters[i][j]);
                        if (cDist < distToClusters) distToClusters = cDist;
                    }
                    */

                    if (distToClusters < maxDist)
                    {
                        if (distToClusters < bestDist)
                        {
                            bestDist = distToClusters;
                            bestCluster = i;
                        }
                    }
                }

                if (bestCluster < 0)
                {
                    std::vector<cv::Point2f> newCluster;
                    newCluster.push_back(finishedCluster);
                    clusters.push_back(newCluster);
                }
                else
                {
                    clusters[bestCluster].push_back(finishedCluster);
                }

            }

        }
    }

    cv::Mat out;
    cv::cvtColor(in, out, cv::COLOR_GRAY2BGR);
    for (int i = 0; i < clusters.size(); ++i)
    {
        cv::Scalar color = cv::Scalar(i*rand() % 255, (i+2)*rand() % 255, (i+1) * 100);
        if (i == 0) color = cv::Scalar(0, 255, 0);
        if (i == 1) color = cv::Scalar(0, 0, 255);
        for (int j = 1; j < clusters[i].size(); ++j)
        {
            cv::line(out, clusters[i][j - 1], clusters[i][j], color, 2);
        }
    }
    cv::imwrite("C:/StackOverflow/Input/splitCurves_out.png", out);
    cv::imshow("out", out);
    cv::waitKey(0);
}
到线的双距离(cv::点线\起点,cv::点线\终点,cv::点点)
{
double normalLength=\u hypot(line\u end.x-line\u start.x,line\u end.y-line\u start.y);
双倍距离=(双倍)((point.x-line\u start.x)*(line\u end.y-line\u start.y)-(point.y-line\u start.y)*(line\u end.x-line\u start.x))/normalLength;
返回abs(距离);
}
int main()
{
cv::Mat in=cv::imread(“C:/StackOverflow/Input/splitCurves.png”,cv::imread\U灰度);
std::向量簇;
float maxDist=10.0f;//启发式
//这样的循环非常昂贵,但我们需要按列扫描
//首先转置图像,然后按行扫描会更便宜!!
对于(int x=0;x
您知道将有两条曲线吗?你知道他们会是什么样的曲线吗(例如,1条椭圆和1条三阶曲线?如果是,您可以尝试一种基于RANSAC的算法,根据需要随机选取任意多个点来创建该曲线,然后检查哪些其他点支持该曲线。重复此操作,直到找到您想要的曲线,并将所有支持点分配给单个曲线。作为更一般的方法,请查看“格式塔理论”,但我不认为有这样的算法。老实说,解释一下,你的图像是两条曲线需要领域知识,以及如何分割线来获得cu