Search code examples
c++opencvimage-processingfilteringsobel

opencv: how to draw arrows on orientation image


I'm trying to perform orientation estimation on an input image in OpenCV. I used sobel function to get gradients of the image, and used another function called calculateOrientations, which I found on the internet, to calculate orientations.

The code is as follows:

void computeGradient(cv::Mat inputImg)
{
    // Gradient X
    cv::Sobel(inputImg, grad_x, CV_16S, 1, 0, 5, 1, 0, cv::BORDER_DEFAULT);
    cv::convertScaleAbs(grad_x, abs_grad_x);

    // Gradient Y
    cv::Sobel(inputImg, grad_y, CV_16S, 0, 1, 5, 1, 0, cv::BORDER_DEFAULT);
    cv::convertScaleAbs(grad_y, abs_grad_y);

    // convert from CV_8U to CV_32F
    abs_grad_x.convertTo(abs_grad_x2, CV_32F, 1. / 255);
    abs_grad_y.convertTo(abs_grad_y2, CV_32F, 1. / 255);

    // calculate orientations
    calculateOrientations(abs_grad_x2, abs_grad_y2);    
} 

void calculateOrientations(cv::Mat gradientX, cv::Mat gradientY)
{
    // Create container element
    orientation = cv::Mat(gradientX.rows, gradientX.cols, CV_32F);

    // Calculate orientations of gradients --> in degrees
    // Loop over all matrix values and calculate the accompagnied orientation
    for (int i = 0; i < gradientX.rows; i++){
        for (int j = 0; j < gradientX.cols; j++){
            // Retrieve a single value
            float valueX = gradientX.at<float>(i, j);
            float valueY = gradientY.at<float>(i, j);
            // Calculate the corresponding single direction, done by applying the arctangens function
            float result = cv::fastAtan2(valueX, valueY);
            // Store in orientation matrix element
            orientation.at<float>(i, j) = result;
        }
    }
}

Now, I need to make sure whether the obtained orientation is correct or not. For that I want to draw arrows for each block of size 5x5 on the orientation matrix. Could someone advice me on how to draw arrows on this? Thank you.


Solution

  • The simplest way for OpenCV to distinguish direction is to draw little circle or square at a start or end point of line. There are no function for arrows afaik. If you need arrow you have to write this (it is simple but takes time too). Once I did it this way (not openCV, but I hope you convert it):

      double arrow_pos = 0.5; // 0.5 = at the center of line
      double len = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
      double co = (x2-x1)/len, si = (y2-y1)/len; // line coordinates are (x1,y1)-(x2,y2)
      double const l = 15, sz = linewidth*2; // l - arrow length 
      double x0 = x2 - len*arrow_pos*co;
      double y0 = y2 - len*arrow_pos*si;
      double x = x2 - (l+len*arrow_pos)*co;
      double y = y2 - (l+len*arrow_pos)*si;
      TPoint tp[4] = {TPoint(x+sz*si, y-sz*co), TPoint(x0, y0), TPoint(x-sz*si, y+sz*co), TPoint(x+l*0.3*co, y+0.3*l*si)};
      Polygon(tp, 3);
      Canvas->Polyline(tp, 2);
    

    UPDATE: arrowedLine(...) function added since OpenCV 2.4.10 and 3.0