Adjusting the threshold in Canny edge algorithm

11,238

Canny edge detector is a multi-step detector using hysteresis thresholding (it uses two threshold instead of one), and edge tracking (your last snippet is the part of this step). I suggest reading the wikipedia entry first. One possible solution could be to choose the high threshold, so e.g. 70% of the image pixels would be classified as edge (initially - you could do this quickly using histograms), than choose the low threshold as e.g. 40% of the high threshold. It might be a good idea to try to perform edge detection on image block rather than the whole image, so your algorithm could calculate different thresholds for different areas.

Note that CAPTCHA-s are designed to be hard to segment, and adding noise that broke edge detection is one technique to achive this (you might need to smooth the image first).

Share:
11,238
Gambit King
Author by

Gambit King

Updated on June 27, 2022

Comments

  • Gambit King
    Gambit King almost 2 years

    I wanted to try my hand at text recognition, so i've used opencv to trace out the edges and c++ to find slopes, curves etc, the edge algorithm works well on big and uncluttered sets of characters but when it comes against small printed text or text with a lot of background noise like embedded in captcha it struggles and looks incomplete, my guess was i hadn't set the threshold values correctly and tried different values with no success.

    enter image description here

    enter image description here

    Here is my code :

    #include "cv.h"
    #include "highgui.h"
    using namespace cv;
    const int low_threshold  = 50;
    const int high_threshold = 150;
    
    
    int main()
    {
    
        IplImage* newImg; 
        IplImage* grayImg; 
        IplImage* cannyImg; 
    
        newImg = cvLoadImage("ocv.bmp",1);
    
        grayImg = cvCreateImage( cvSize(newImg->width, newImg->height), IPL_DEPTH_8U, 1 );
    
        cvCvtColor( newImg, grayImg, CV_BGR2GRAY );
        cannyImg = cvCreateImage(cvGetSize(newImg), IPL_DEPTH_8U, 1);
    
        cvCanny(grayImg, cannyImg, low_threshold, high_threshold, 3);
        cvNamedWindow   ("Source", 1);
        cvNamedWindow   ("Destination",1);
        cvShowImage     ("Source", newImg );
        cvShowImage     ("Destination", cannyImg );
        cvWaitKey(0);
        cvDestroyWindow ("Source" );
        cvDestroyWindow ("Destination" );
        cvReleaseImage  (&newImg );
        cvReleaseImage  (&grayImg );
        cvReleaseImage  (&cannyImg );
    
    return 0;
    
    }
    

    I've looked across the net and have seen some complicated thresholding conditions like in this code from this site :

    % Set direction to either 0, 45, -45 or 90 depending on angle.
    [x,y]=size(f1);
    for i=1:x-1,
        for j=1:y-1,
            if ((gradAngle(i,j)>67.5 && gradAngle(i,j)<=90) || (gradAngle(i,j)>=-90 && gradAngle(i,j)<=-67.5)) 
                gradDirection(i,j)=0;
            elseif ((gradAngle(i,j)>22.5 && gradAngle(i,j)<=67.5))
                gradDirection(i,j)=45;
            elseif ((gradAngle(i,j)>-22.5 && gradAngle(i,j)<=22.5))
                gradDirection(i,j)=90;
            elseif ((gradAngle(i,j)>-67.5 && gradAngle(i,j)<=-22.5))
                gradDirection(i,j)=-45;
            end
        end
    end
    

    If this is the solution can somebody provide me the c++ equivalent of this algorithm, if it's not what else can i do ?