Search code examples
algorithmmatlabopencvimage-processingedge-detection

Supposed easy edge detection in MATLAB


I have the following image: and I'd like to detect a contour of the note which is intuitionally seen easy, but when I try to do it, it actually isn't that easy.

For quick prototyping I started using MATLAB first (but later I want to do it in Java thus I'd like to not use too many special algorithms in MATLAB but rather try to use basic image proessing algorithms (prewitt / sobel / canny / adaptive thresholds / hough trafo) which are easily available in another language as well (e.g. opencv etc)..

The most easy code to start with was (but I thought this should already be quite good as the outside-edge looks to strong compared to the inside ones):

I = double(rgb2gray(imread('img.jpg')));
bw = edge(I, 'canny');
imshow(bw)

I thought matlab would be doing the choice of the threshold in the canny filter very well when using the automatical-mode. But it actually doesn't: https://i.sstatic.net/wrry6.png

When setting the threshold as a scalar manually (to .4 e.g.) I still get way too many gradients for the text inside and the outside borders are already way too incomplete/patchy: https://i.sstatic.net/kiY5F.png

I tried it using a prewitt filter (in x and y direction):

I = double(rgb2gray(imread('img.jpg')));
f1 = double(fspecial('prewitt'));
x = conv2(I, f);
y = conv2(I, f');
bw = (x.^2+y.^2).^0.5;
colormap(gray(256))
imagesc(bw);

resulting in: https://i.sstatic.net/FyUCS.png so also not very well... it looks better but still the outside is very patchy :(

Any ideas how to improve it very much? Further I'd like to unwarp the image later on to a rectangular shape. Any ideas on how to do it? Hough transform wouldn't work on a non-straight contour like the image above as it yields straight lines as a result...

Thanks very much!

Edit: Okay I found out the patchy-look comes from MATLAB... when zooming in, it is much much better and less patchy, see: https://i.sstatic.net/JfewK.jpg And I could imagine to find the contour by shrinking the outer contour because it is all black in this case (some sort of boundary box). But I don't want to assume that as the pictures are not always taken with flashlight on, e.g.: https://i.sstatic.net/Gqhyy.jpg So then there will be some noise in the outer areas...

Edit2: Just found Algorithm to detect corners of paper sheet in photo doesn't look too easy obviously. :) Maybe you've got some new ideas to start with.


Solution

  • Here is prototype in C++:

    #include <iostream>
    #include <vector>
    #include <stdio.h>
    #include <stdarg.h>
    #include "opencv2/opencv.hpp"
    #include "fstream"
    #include "iostream"
    using namespace std;
    using namespace cv;
    //-----------------------------------------------------------------------------------------------------
    // 
    //-----------------------------------------------------------------------------------------------------
    int main( int argc, char** argv )
    {
        namedWindow("Img");
        Mat Img=imread("Test2.JPG",0);
        cv::resize(Img,Img,Size(Img.cols/8,Img.rows/8));
        cv::threshold(Img,Img,100,255,cv::THRESH_OTSU);
        cv::dilate(Img,Img,cv::Mat::ones(3,3,CV_8UC1));
        cv::erode(Img,Img,cv::Mat::ones(23,23,CV_8UC1));
        cv::resize(Img,Img,Size(Img.cols*8,Img.rows*8));
        imshow("Img",Img);
        waitKey(0);
        return 0;
    }
    

    It gives the output image (after that just find contours).

    enter image description here