OpenCV Line Detection

Я пытаюсь найти края центрированного прямоугольника на этом изображении:

Я пытался использовать HoughLines, используя dRho = img_width / 1000, dTheta = pi / 180 и threshold = 250. Это прекрасно работает на этом изображении, масштабируется до 1/3 от размера, но на полноразмерном изображении он просто получает линии везде во всех направлениях ...

Что я могу сделать, чтобы настроить это, чтобы быть более точным?

Ответы на вопрос(3)

ом, например. Гауссовский, чтобы избавиться от высоких частот. Тот факт, что измененный размер работает лучше, вероятно, потому что ваше оригинальное изображение как-то шумно.

Сначала попробуйте размыть изображение, например. сcv::GaussianBlur(src, target, Size(0,0), 1.5), то это должно быть эквивалентно изменению размера. (Он забыл теорию, если она не работает, попробуйте также 3 и 6)

о фильтра. Это даст вам тот же эффект, что и уменьшение масштаба - линии станут более тонкими и не исчезнут одновременно.

Фильтр «Blur» - хорошая идея, как говорит Ча

Таким образом (с размытием) это станет чем-то вродеhttp: //www.ic.uff.br/~laffernandes/projects/kht/index.htm (Основанное на ядре преобразование Хафа)

Решение Вопроса

представленного в этом ответе: как обнаружить квадрат:

Оригинальную программу можно найти внутри OpenCV, она называется Squares.cpp. Приведенный ниже код был изменен для поиска квадратов только в первой цветовой плоскости, но, поскольку он все еще обнаруживает много квадратов, в конце программы я отбрасываю все из них, кроме первого, и затем вызываюdraw_squares() чтобы показать, что было обнаружено. Вы можете изменить это easilly, чтобы нарисовать их все и увидеть все, что было обнаружено.

Теперь вы можете делать все что угодно, в том числе устанавливать интересующую область (ROI) для извлечения области, находящейся внутри квадрата (игнорируйте все остальное вокруг него).

Вы можете видеть, что обнаруженный прямоугольник не совсем выровнен по линиям на изображении. Вы должны выполнить некоторые операции предварительной обработки (размыть?) Изображения, чтобы уменьшить толщину линий и улучшить обнаружение. Но с этого момента это все на вас:

#include <cv.h>
#include <highgui.h>

using namespace cv;

double angle( cv::Point pt1, cv::Point pt2, cv::Point pt0 ) {
    double dx1 = pt1.x - pt0.x;
    double dy1 = pt1.y - pt0.y;
    double dx2 = pt2.x - pt0.x;
    double dy2 = pt2.y - pt0.y;
    return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}

void find_squares(Mat& image, vector<vector<Point> >& squares)
{
    // TODO: pre-processing

    // blur will enhance edge detection
    Mat blurred(image);
    medianBlur(image, blurred, 9);

    Mat gray0(blurred.size(), CV_8U), gray;
    vector<vector<Point> > contours;

    // find squares in the first color plane.
    for (int c = 0; c < 1; c++)
    {
        int ch[] = {c, 0};
        mixChannels(&blurred, 1, &gray0, 1, ch, 1);

        // try several threshold levels
        const int threshold_level = 2;
        for (int l = 0; l < threshold_level; l++)
        {
            // Use Canny instead of zero threshold level!
            // Canny helps to catch squares with gradient shading
            if (l == 0)
            {
                Canny(gray0, gray, 10, 20, 3); // 

                // Dilate helps to remove potential holes between edge segments
                dilate(gray, gray, Mat(), Point(-1,-1));
            }
            else
            {
                    gray = gray0 >= (l+1) * 255 / threshold_level;
            }

            // Find contours and store them in a list
            findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

            // Test contours
            vector<Point> approx;
            for (size_t i = 0; i < contours.size(); i++)
            {
                    // approximate contour with accuracy proportional
                    // to the contour perimeter
                    approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);

                    // Note: absolute value of an area is used because
                    // area may be positive or negative - in accordance with the
                    // contour orientation
                    if (approx.size() == 4 &&
                            fabs(contourArea(Mat(approx))) > 1000 &&
                            isContourConvex(Mat(approx)))
                    {
                            double maxCosine = 0;

                            for (int j = 2; j < 5; j++)
                            {
                                    double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
                                    maxCosine = MAX(maxCosine, cosine);
                            }

                            if (maxCosine < 0.3)
                                    squares.push_back(approx);
                    }
            }
        }
    }
}

void draw_squares(Mat& img, vector<vector<Point> > squares)
{
    for (int i = 0; i < squares.size(); i++)
    {
        for (int j = 0; j < squares[i].size(); j++)
        {
            cv::line(img, squares[i][j], squares[i][(j+1) % 4], cv::Scalar(0, 255, 0), 1, CV_AA);
        }
    }
}


int main(int argc, char* argv[])
{
    Mat img = imread(argv[1]);

    vector<vector<Point> > squares;
    find_squares(img, squares);

    std::cout << "* " << squares.size() << " squares were found." << std::endl;

    // Ignore all the detected squares and draw just the first found
    vector<vector<Point> > tmp;
    if (squares.size() > 0)
    {
        tmp.push_back(squares[0]);
        draw_squares(img, tmp);
    }
    //imshow("squares", img);
    //cvWaitKey(0);

    imwrite("out.png", img);

    return 0;
}
 SL_User26 июн. 2012 г., 10:41
Можете ли вы сказать мне, как получить доступ к длинам квадратов, которые мы определили?
 karlphillip27 июн. 2012 г., 15:05
Спросите себя, какова длина квадрата, а затем обратите внимание, что квадрат определяется как набор из 4 точек (координат). Приведенный выше код дает вам очки, но вычисление, чтобы определить его длину, зависит от ва

Ваш ответ на вопрос