OpenCV Canny after ConvexPoly not working

I'm working on an lane detection algorithm with opencv in c++. I did an Affine Transform to extract an triangular area to an mask.

After this step I want to perform the Canny edge detector. But it is not working. Is it due to the bit conversion? Or what is my Problem?

I outsourced the main part to the function warpTriangle. The porgram breaks in this function at the end.

Error Message:

OpenCV Error: Assertion failed ((_dst.getObj() != _src.getObj() || _src.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3))) && "Inplace parameters are not supported") in Canny, file /tmp/opencv-20180113-80339-d8g5mw/opencv-3.4.0/modules/imgproc/src/canny.cpp, line 935 libc++abi.dylib: terminating with uncaught exception of type cv::Exception: /tmp/opencv-20180113-80339-d8g5mw/opencv-3.4.0/modules/imgproc/src/canny.cpp:935: error: (-215) (_dst.getObj() != _src.getObj() || _src.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3))) && "Inplace parameters are not supported" in function Canny

Screenshot

My code:

#include <opencv2/opencv.hpp>
#include <stdlib.h>
#include <chrono>
#include <thread>

using namespace cv;
using namespace std;

// Warps and alpha blends triangular regions from img1 and img2 to img
void warpTriangle(Mat &img1, Mat &img2, vector<Point2f> tri)
{
    // Find bounding rectangle for each triangle
    Rect r1 = boundingRect(tri);
    Rect r2 = boundingRect(tri);

    // Offset points by left top corner of the respective rectangles
    vector<Point2f> tri1Cropped, tri2Cropped;
    vector<Point> tri2CroppedInt;
    for(int i = 0; i < 3; i++)
    {
        tri1Cropped.push_back( Point2f( tri[i].x - r1.x, tri[i].y -  r1.y) );
        tri2Cropped.push_back( Point2f( tri[i].x - r2.x, tri[i].y - r2.y) );

        // fillConvexPoly needs a vector of Point and not Point2f
        tri2CroppedInt.push_back( Point((int)(tri[i].x - r2.x), (int)(tri[i].y - r2.y)) );

    }

    // Apply warpImage to small rectangular patches
    Mat img1Cropped;
    img1(r1).copyTo(img1Cropped);

    // Given a pair of triangles, find the affine transform.
    Mat warpMat = getAffineTransform( tri1Cropped, tri2Cropped );

    // Apply the Affine Transform just found to the src image
    Mat img2Cropped = Mat::zeros(r2.height, r2.width, img1Cropped.type());
    warpAffine( img1Cropped, img2Cropped, warpMat, img2Cropped.size(), INTER_LINEAR, BORDER_REFLECT_101);

    // Get mask by filling triangle
    Mat mask = Mat::zeros(r2.height, r2.width, CV_32FC3);
    fillConvexPoly(mask, tri2CroppedInt, Scalar(1.0, 1.0, 1.0), 16, 0);
    imshow("mask", mask);
    // Copy triangular region of the rectangular patch to the output image

    multiply(img2Cropped,mask, img2Cropped);

    img2Cropped.convertTo(img2Cropped, CV_8U);
    imshow("img2Cropped",img2Cropped);
    Canny(img2Cropped, img2Cropped, 50, 150);   <--- Breaks here!

}

int main( int argc, char** argv)
{

  //  VideoCapture cap(0);
    // Challenge video
    VideoCapture cap("/Users/markus/Desktop/challenge.mp4");
    Mat imgIn;
    while (true)
    {
        Mat start;

        Mat frame = Mat(320,480, CV_8U, 0.0);
        cap >> start;

        resize(start, frame, frame.size());

        cout << "h: " << frame.rows << " w: " << frame.cols << endl;

        Mat imgIn = frame;

        // Read input image and convert to float
        imgIn.convertTo(imgIn, CV_32FC3, 1/255.0);

        // Output image is set to white
        Mat imgOut = Mat::ones(imgIn.size(), imgIn.type());
        imgOut = Scalar(0.0,0.0,0.0);

        int height, width;
        height = frame.rows;
        width = frame.cols;
        // Input triangle
        vector <Point2f> triIn;
        triIn.push_back(Point2f(0,height-1));
        triIn.push_back(Point2f(width-1,height-1));
        triIn.push_back(Point2f(width/2-1,height/2-1));

        // Warp all pixels inside input triangle to output triangle
         warpTriangle(imgIn, imgOut, triIn);

        // Draw triangle on the input and output image.

        // Convert back to uint because OpenCV antialiasing
        // does not work on image of type CV_32FC3

        imgIn.convertTo(imgIn, CV_8UC3, 255.0);
        imgOut.convertTo(imgOut, CV_8UC3, 255.0);

        // Draw triangle using this color
        Scalar color = Scalar(255, 150, 0);

        // cv::polylines needs vector of type Point and not Point2f
        vector <Point> triInInt, triOutInt;
        for(int i=0; i < 3; i++)
        {
            triInInt.push_back(Point(triIn[i].x,triIn[i].y));
        }

        // Draw triangles in input and output images
        polylines(imgIn, triInInt, true, color, 2, 16);
        polylines(imgOut, triOutInt, true, color, 2, 16);

        imshow("frame", imgIn);


        if (waitKey(30) >= 0) {
            break;
        }
    }
    return 0;
}

1 answer

  • answered 2018-01-17 08:18 api55

    The error tells you already what is wrong

    _dst.getObj() != _src.getObj()

    This means that the source and the destination object should not be the same...

    In your code you have:

    Canny(img2Cropped, img2Cropped, 50, 150); 
    

    As you can see, you have the same variable as source and destination (img2Cropped). To fix it change it to:

    Mat resultCanny;
    Canny(img2Cropped, resultCanny, 50, 150);