OpenCV Android Създайте ново изображение, като използвате ръбовете на най-големия контур

Мога да открия най-големия квадрат/правоъгълник (в зелено) в изображение. Искам обаче да преобразувам най-големия квадрат/правоъгълник, открит в изображението, в ново изображение (което да се съхранява в нова подложка).

Ето обратното изображение на тази функция, което има най-големия правоъгълник/квадрат: http://img153.imageshack.us/img153/9308/nn4w.png

Ето моят код досега:

private Mat findLargestRectangle(Mat original_image) {
    Mat imgSource = original_image;

    //convert the image to black and white
    Imgproc.cvtColor(imgSource, imgSource, Imgproc.COLOR_BGR2GRAY);

    //convert the image to black and white does (8 bit)
    Imgproc.Canny(imgSource, imgSource, 50, 50);

    //apply gaussian blur to smoothen lines of dots
    Imgproc.GaussianBlur(imgSource, imgSource, new Size(5, 5), 5);

    //find the contours
    List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
    Imgproc.findContours(imgSource, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);

    double maxArea = -1;
    int maxAreaIdx = -1;
    MatOfPoint temp_contour = contours.get(0); //the largest is at the index 0 for starting point
    MatOfPoint2f approxCurve = new MatOfPoint2f();
    Mat largest_contour = contours.get(0);
    List<MatOfPoint> largest_contours = new ArrayList<MatOfPoint>();
    for (int idx = 0; idx < contours.size(); idx++) {
        temp_contour = contours.get(idx);
        double contourarea = Imgproc.contourArea(temp_contour);
        //compare this contour to the previous largest contour found
        if (contourarea > maxArea) {
            //check if this contour is a square
            MatOfPoint2f new_mat = new MatOfPoint2f( temp_contour.toArray() );
            int contourSize = (int)temp_contour.total();
            Imgproc.approxPolyDP(new_mat, approxCurve, contourSize*0.05, true);
            if (approxCurve.total() == 4) {
                maxArea = contourarea;
                maxAreaIdx = idx;
                largest_contours.add(temp_contour);
                largest_contour = temp_contour;
            }
        }
    }
    MatOfPoint temp_largest = largest_contours.get(largest_contours.size()-1);
    largest_contours = new ArrayList<MatOfPoint>();
    largest_contours.add(temp_largest);

    Imgproc.cvtColor(imgSource, imgSource, Imgproc.COLOR_BayerBG2RGB);
    Imgproc.drawContours(imgSource, largest_contours, -1, new Scalar(0, 255, 0), 1);

    //create the new image here using the largest detected square

    Toast.makeText(getApplicationContext(), "Largest Contour: ", Toast.LENGTH_LONG).show();

    return imgSource;
}

Променливата largest_contours е списък на MatOfPoint, но съдържа само най-големия контур, също съхранен в променливата largest_contour. Как мога да направя ново изображение от най-големия контур?

Използвам OpenCV в Android и има малко уроци за откриване на изображения, но не точно как да използвам Imgproc.warpPerspective()

Благодаря!


person James Arnold    schedule 12.07.2013    source източник
comment
Какво имате предвид, когато казвате да създадете нов имидж? Какво съдържа това ново изображение?   -  person Aurelius    schedule 12.07.2013
comment
Здравей @Aurelius, това се опитвах да постигна stackoverflow.com/questions/17512234/. Публикувах това преди няколко седмици и сега, когато мога да открия най-големия квадратен контур в изображението, искам да изрежа това изображение и да създам ново.   -  person James Arnold    schedule 13.07.2013
comment
Използвах този код успешно, за да намеря най-големия правоъгълник. Също така открих начин да запазя полученото изображение. Полученото изображение е черно-бяло. Как мога да предотвратя това? Искам да е цветно.   -  person TharakaNirmana    schedule 31.08.2013


Отговори (2)


Всичко, от което се нуждаете, е да намерите ъглите на този контур. Можете да използвате подхода на екстремни точки.

Трябва просто да откриете точката с минимум x и минимум y (това е вашето горе вляво), минимум x максимум y (това е вашето долно ляво) и т.н.

В C++ има библиотека с име algoritm, която има методи min/max. Например min_element ще ви помогне да намерите точката с минимум x или y. Не забравяйте да включите заглавка.

След като имате вашите 4 точки, можете да използвате трансформация на перспектива.

Първо въведете вашите точки за този метод. Дестинацията трябва да бъде

Point2f dest[4] = {(0,0),(image.width,0),(0,image.height),(image.height,image.width)}

за твоя случай. Матрицата (M), която получавате от този метод, ще трансформира точките ви до местоназначението с помощта на друг метод.

Късмет.

Редактиране: На втората мисъл; тъй като вашият контур не е успоредник, имате своите крайни точки като min x = долу вляво, min y = горе вляво и т.н. Тогава е по-лесно да се намери минималният елемент.

person baci    schedule 13.07.2013
comment
Здравейте Bacci, благодаря за отговора. Благодаря за алгоритъма за определяне на екстремните точки. Четириъгълникът може да бъде успоредник, тъй като изображението идва от мобилна камера. Благодаря отново! - person James Arnold; 14.07.2013
comment
Здравей Canberk Baci, ето моят напредък досега: stackoverflow.com /questions/17637730/ Вие сте голяма помощ в този проект. Благодаря! - person James Arnold; 14.07.2013
comment
Не мисля, че екстремният подход ще работи за правоъгълника, завъртян под ъгъл (страните на който не са успоредни на координатната ос). - person Ankur Gautam; 13.01.2014

Това не е начинът да използвате drawContour на нов мат. Този документ ще ви помогне.

Правилният начин би бил

    Imgproc.findContours(imgSource, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);

    ...

    Imgproc.cvtColor(imgSource, imgSource, Imgproc.COLOR_BayerBG2RGB);
    Imgproc.drawContours(imgSource, contours, maxAreaIdx, new Scalar(0, 255, 0), 1);
person Tae-Sung Shin    schedule 12.07.2013
comment
Благодаря @Thomas, това помогна много за обработката, тъй като не се нуждая от списъка с масиви на large_contour. Но все още имам голяма нужда да изрежа най-големия контур и да създам ново изображение от него. Благодаря отново! - person James Arnold; 13.07.2013