C++ 霍夫圆变换

C++ 霍夫圆变换,c++,opencv,hough-transform,C++,Opencv,Hough Transform,我正在尝试使用梯度方向实现Hough变换。我知道OpenCv中有一个实现,但我想自己做 我用Sobel得到X和Y梯度。然后,对于每个像素 magnitute-->sqrt(sobelX^2+sobelY^2) 方向-->atan2(sobelY,sobelX)*180/PI 如果震级高于220(几乎为黑色),这就是边缘。 然后将方向用于圆方程 但结果是不可接受的。有什么帮助吗 我知道有cv::polar和cv::cartToPolar,但我想优化代码,使所有方程都能动态计算,没有空循环

我正在尝试使用梯度方向实现Hough变换。我知道OpenCv中有一个实现,但我想自己做

我用Sobel得到X和Y梯度。然后,对于每个像素

  • magnitute-->
    sqrt(sobelX^2+sobelY^2)

  • 方向-->
    atan2(sobelY,sobelX)*180/PI
如果震级高于220(几乎为黑色),这就是边缘。 然后将方向用于圆方程

但结果是不可接受的。有什么帮助吗

我知道有
cv::polar
cv::cartToPolar
,但我想优化代码,使所有方程都能动态计算,没有空循环

cv::Mat sobelX,sobelY;
Sobel(mat,sobelX,CV_32F,1,0,kernelSize,1,0,CV::BORDER_REPLICATE);
Sobel(mat,sobelY,CV_32F,0,1,kernelSize,1,0,CV::BORDER_REPLICATE);
//cv::Canny(mat,mat,100200,内核大小,假);
调试::showImage(“sobelX”,sobelX);
调试::showImage(“SobelY”,SobelY);
调试::showImage(“MAT”,MAT);
cv::Mat震级图、角度图;
magnitudeMap=cv::Mat::Zero(Mat.rows、Mat.cols、Mat.type());
angleMap=cv::Mat::zero(Mat.rows、Mat.cols、Mat.type());
向量hough_空间(max);

对于(int i=0;我不想优化所有方程都将动态计算的代码,没有空循环。我不认为你会通过自己实现已经优化的函数来提高性能。是的,我知道,但我不想理解它是如何工作的,不使用所有库函数。但是当我使用cartToPolar时,没有任何变化。result仍然是不可接受的。这可能是一个愚蠢的问题,但您是否尝试过查看sobelX、sobelY和magnitude图像的输出?它是否给出了您期望的结果?
cv::Mat sobelX,sobelY;
        Sobel(mat, sobelX, CV_32F, 1, 0, kernelSize, 1, 0, cv::BORDER_REPLICATE);
        Sobel(mat, sobelY, CV_32F, 0, 1, kernelSize, 1, 0, cv::BORDER_REPLICATE);
        //cv::Canny(mat,mat,100,200,kernelSize,false);
        debug::showImage("sobelX",sobelX);
        debug::showImage("SobelY",sobelY);
        debug::showImage("MAT",mat);
        cv::Mat magnitudeMap,angleMap;
    magnitudeMap = cv::Mat::zeros(mat.rows,mat.cols,mat.type());
    angleMap = cv::Mat::zeros(mat.rows,mat.cols,mat.type());
        std::vector<cv::Mat> hough_spaces(max);
        for(int i=0; i<max; ++i)
        {
            hough_spaces[i] = cv::Mat::zeros(mat.rows,mat.cols,mat.type());
        }
        for(int x=0; x<mat.rows; ++x)
        {
            for(int y=0; y<mat.cols; ++y)
            {

                const float magnitude = sqrt(sobelX.at<uchar>(x,y)*sobelX.at<uchar>(x,y)+sobelY.at<uchar>(x,y)*sobelY.at<uchar>(x,y));
                const float theta= atan2(sobelY.at<uchar>(x,y),sobelX.at<uchar>(x,y)) * 180/CV_PI;
                magnitudeMap.at<uchar>(x,y) = magnitude;
                if(magnitude > 225)//mat.at<const uchar>(x,y) == 255)
                {
                    for(int radius=min; radius<max; ++radius)
                    {

                        const int a = x - radius * cos(theta);//lookup::cosArray[static_cast<int>(theta)];//+ 0.5f;
                        const int b = y - radius * sin(theta);//lookup::sinArray[static_cast<int>(theta)]; //+ 0.5f;
                        if(a >= 0 && a <hough_spaces[radius].rows && b >= 0 && b<hough_spaces[radius].cols)                             {
                            hough_spaces[radius].at<uchar>(a,b)+=10;
                        }


                    }
                }
            }
        }
        debug::showImage("magnitude",magnitudeMap);
        for(int radius=min; radius<max; ++radius)
        {
            double min_f,max_f;
            cv::Point min_loc,max_loc;
            cv::minMaxLoc(hough_spaces[radius],&min_f,&max_f,&min_loc,&max_loc);
            if(max_f>=treshold)
            {
                circles.emplace_back(cv::Point3f(max_loc.x,max_loc.y,radius));
                // debug::showImage(std::to_string(radius).c_str(),hough_spaces[radius]);

            }
        }
        circles.shrink_to_fit();