4
votes

I have binary image of edges computed from Phase and magnitude (monogenic signal) , and I want to apply hysteresis thresholding in OpenCv. Unfortunately i couldnt use it as its implemented within Canny edge detection in opencv library. I want to know if there is workaround or simple implementation approach.

1
Why you can't use canny?Miki
I need contrast invariant methods, Gradient based edge detection like canny will not work with my images.aditya sai
which language are you using? if it is python, you may try to use scikit, which has hysteresis threshold as a functionapi55
@api55 we are developing in C++giuseppe
I guess you should look out for a research paper on this topic and try to find if someone has already implemented it, if not then try implementing it by yourself and attach the progress with the question itself.ZdaR

1 Answers

0
votes

I came up with this solution:

Mat threshUpper, threshLower;
threshold(inImage, threshUpper, inThreshold, 128, CV_THRESH_BINARY);
threshold(inImage, threshLower, inThreshold-inHysteresis, 128, CV_THRESH_BINARY);

// Find the contours to get the seed from which starting floodfill
vector<vector<Point>> contoursUpper;
cv::findContours(threshUpper, contoursUpper, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

// Makes brighter the regions that contain a seed
for(auto cnt : contoursUpper){
    cv::floodFill(threshLower, cnt[0], 255, 0, 2, 2, CV_FLOODFILL_FIXED_RANGE);
}
//Threshold the image again to make black the not filled regions
threshold(threshLower, outImg, 200, 255, CV_THRESH_BINARY);

Nevertheless, I am still trying to figure out why floodfill takes a lot of time (about 1.5sec) on some input and run smoothly on others (5 millisec)!

EDIT: If you do not care of having a binary image with the regions but you are interested in the contours property you can just have the two thresholded images and perform the following instructions. There are two solutions, one guarantee the hysteresis correctness but is O(n^2) the other approximate the region with its bounding box and run in O(n)

 vector<vector<Point>> contoursUpper, contoursLower;
 cv::findContours(threshUpper, contoursUpper, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
 cv::findContours(threshLower, contoursLower, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

 // Correct solution O(n^2)
 for(auto cntU : contoursUpper){
     for(auto cntL : contoursLower){
         if(cv::pointPolygonTest(cntL, cntU[0], false) >= 0){
             ///@todo: Do something with the cntL region (e.g. compute bounding box etc.)
             break; //Already found the connected region the others cannot be connected too
         }
     }
 }


// Approx. solution: O(n)
double minV, maxV;
for(auto cntL : largerContours){
    auto minBoundingBox = boundingRect(cntL);
    minMaxLoc(narrowThreshold(minBoundingBox), &minV, &maxV);
    if(maxV > 1){
        ///@todo: Do something with the cntL region (e.g. compute bounding box etc.)
    }
}