OpenCV C ++ / Obj-C: правильное обнаружение объектов - PullRequest
12 голосов
/ 21 декабря 2011

Как какой-то "праздничный проект", я играю с OpenCV и хочу обнаружить и измерить материал.

Текущий рабочий процесс (ранняя стадия - обнаружение):

  1. Преобразовать в оттенки серого (cv :: cvtColor)
  2. Применить адаптивный порог (cv :: adaptiveThreshold)
  3. Применить обнаружение канни-края (cv :: Canny)
  4. Поиск контуров (cv :: findContours)

Мой результат довольно дурацкий, и я не уверен, чтоправильное направление, чтобы идти.Я уже получил cvBlob, работающий под моей текущей установкой (OSX 10.7.2, Xcode 4.2.1), это лучший способ?Если так, как я могу реализовать это правильно?

Или мне сначала нужно вычитание фона?Я попробовал это, но потом не смог найти контуры

Вот мое изображение: image to measure

И это мой вывод, когда я рисую свои контуры обратно на первое изображение: output

ОБНОВЛЕНИЕ

Я получил это работает в моей программе, и мой вывод выглядит немного по-другому ...

- (IBAction)processImage:(id)sender
{
    cv::Mat forground = [[_inputView image] CVMat];
    cv::Mat result = [self isolateBackground:forground];
    [_outputView setImage:[NSImage imageWithCVMat:result]];
}

- (cv::Mat)isolateBackground:(cv::Mat &)_image
{
    int rh = 255, rl = 100, gh = 255, gl = 0, bh = 70, bl = 0;
    cv::cvtColor(_image, _image, CV_RGB2HSV_FULL);
    cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));
    cv::Mat bgIsolation;
    cv::inRange(_image, cv::Scalar(bl, gl, rl), cv::Scalar(bh, gh, rh), bgIsolation);
    bitwise_not(bgIsolation, bgIsolation);
    erode(bgIsolation, bgIsolation, cv::Mat());
    dilate(bgIsolation, bgIsolation, element);
    return bgIsolation;
}

1 Ответ

10 голосов
/ 22 декабря 2011

Это может быть своего рода хаком, но так как это "праздничный проект", я все равно опубликую его:)

Вы пытались изолировать фон, а затем инвертировать маску (это предполагает, что все, что не является фоном, является объектом, но может работать для того, что вы хотите).

Ниже приведен результат, полученный с помощью функции OpenCV inRange : enter image description here

Возможно, вы захотите сгладить изображение (предварительную обработку) с помощью GuassianBlur , чтобы избавиться от некоторых неровностей. Я использовал ядро ​​расширения большего размера, чем ядро ​​эрозии (5x5 против 3x3), чтобы избавиться от некоторых шумных пикселей. Сглаживание может помочь в этом, также настройка порогов может сделать ненужной эрозию. Но это должно начать вас.

Наконец, вот мой небольшой фрагмент кода, который я использовал, чтобы найти этот диапазон:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <vector>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
    Mat src = imread("test.jpg");


    int rh = 255, rl = 100, gh = 255, gl = 0, bh = 70, bl = 0;

    string windowName = "background";
    namedWindow(windowName);

    createTrackbar("rh", windowName, &rh, 255);
    createTrackbar("rl", windowName, &rl, 255);
    createTrackbar("gh", windowName, &gh, 255);
    createTrackbar("gl", windowName, &gl, 255);
    createTrackbar("bh", windowName, &bh, 255);
    createTrackbar("bl", windowName, &bl, 255);

    // for dilation
    Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));

    Mat bgIsolation;
    int key = 0;
    do
    {
        inRange(src, Scalar(bl, gl, rl), Scalar(bh, gh, rh), bgIsolation);

        bitwise_not(bgIsolation, bgIsolation);

        erode(bgIsolation, bgIsolation, Mat());
        dilate(bgIsolation, bgIsolation, element);

        imshow(windowName, bgIsolation);
        key = waitKey(33);
    } while((char)key != 27);

    waitKey();

    return 0;
}

Наслаждайтесь праздничным проектом! Выглядит весело:)

...