首页 > 解决方案 > 霍夫圆形变换

问题描述

我试图使用梯度方向实现霍夫变换。我知道 OpenCv 中有一个实现,但我想自己做。

我正在使用 Sobel 来获取 X 和 Y 渐变。那么对于每个像素

如果幅度高于 220(几乎是黑色),这就是边缘。然后在圆方程上使用方向。

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

我知道有cv::polarand cv::cartToPolar,但我想优化代码,以便所有方程都可以即时计算,没有空循环。

HoughTransform 的结果

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();

标签: c++opencvhough-transform

解决方案


推荐阅读