估计图像线渐变(不是像素渐变)

时间:2015-01-23 07:19:02

标签: image matlab opencv image-processing gradient

我有一个问题,我想估计轮廓线的渐变。请注意,我不需要像素梯度,但线路的变化率。

如果看到附加的图像,您将看到带有绿色轮廓的二进制图像。我想根据轮廓上像素的渐变标记每个像素。

为什么我需要渐变是因为我想计算渐变方向从+到 - 或从 - 到+变化的点。

我想不出一个好的方法,估计图像上的这一点。有人可以帮我提出如何估算这一点的建议。

enter image description here

1 个答案:

答案 0 :(得分:2)

这是一个小程序,以非常简单的方式计算每个轮廓像素位置的切线(还有其他可能更好的方法!简单的方法是:http://en.wikipedia.org/wiki/Finite_difference#Forward.2C_backward.2C_and_central_differences):

  1. 获取轮廓像素c_ {i}获取邻居c_ {i-1}和c_ {i + 1}
  2. c_i处的切线方向为(c_ {i-1} - c_ {i + 1}
  3. 所以这一切都在CONTOUR PIXELS上,但如果计算与完整图像像素渐变的正交,也许你可以这么类似......不确定;)

    这里是代码:

    int main()
    {
        cv::Mat input = cv::imread("../inputData/ContourTangentBin.png");
    
        cv::Mat gray;
        cv::cvtColor(input,gray,CV_BGR2GRAY);
    
        // binarize
        cv::Mat binary = gray > 100;
    
        // find contours
        std::vector<std::vector<cv::Point> > contours;
        std::vector<cv::Vec4i> hierarchy;
        findContours( binary.clone(), contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE );    // CV_CHAIN_APPROX_NONE to get each single pixel of the contour!!
    
    
        for( int i = 0; i< contours.size(); i++ )
        {
            std::vector<cv::Point> & cCont = contours[i];
            std::vector<cv::Point2f> tangents;
    
            if(cCont.size() < 3) continue;
    
            // 1. compute tangent for first point
            cv::Point2f cPoint = cCont.front();
            cv::Point2f tangent = cCont.back() - cCont.at(1);   // central tangent => you could use another method if you like to
            tangents.push_back(tangent);
    
            // display first tangent
            cv::Mat tmpOut = input.clone();
            cv::line(tmpOut, cPoint + 10*tangent, cPoint-10*tangent, cv::Scalar(0,0,255),1);
            cv::imshow("tangent",tmpOut);
            cv::waitKey(0);
    
            for(unsigned int j=1; j<cCont.size(); ++j)
            {
                cPoint = cCont[j];
                tangent = cCont[j-1] - cCont[(j+1)%cCont.size()];   // central tangent => you could use another method if you like to
                tangents.push_back(tangent);
    
                //display current tangent:
                tmpOut = input.clone();
                cv::line(tmpOut, cPoint + 10*tangent, cPoint-10*tangent, cv::Scalar(0,0,255),1);
                cv::imshow("tangent",tmpOut);
                cv::waitKey(0);
                //if(cv::waitKey(0) == 's') cv::imwrite("../outputData/ContourTangentTangent.png", tmpOut);
            }
    
            // now there are all the tangent directions in "tangents", do whatever you like with them
        }
    
        for( int i = 0; i< contours.size(); i++ )
        {
            drawContours( input, contours, i, cv::Scalar(0,255,0), 1, 8, hierarchy, 0 );
        }
    
        cv::imshow("input", input);
        cv::imshow("binary", binary);
        cv::waitKey(0);
        return 0;
    }
    

    我用过这张图片:

    enter image description here

    并得到如下输出:

    enter image description here

    enter image description here

    enter image description here

    在结果中,您将获得具有该轮廓的每个像素的2D切线信息(线方向)的矢量。