Использование OpenCV для задач сегментации изображений

Исследование проблем сегментации изображений и существующих способов их решения. Выбор инструментальных средств. Информация по установке и использованию библиотеки компьютерного зрения OpenCV. Программирование алгоритмов сегментации при ее помощи.

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 07.08.2018
Размер файла 5,5 M

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

2.10 Будущее библиотеки OpenCV

Количество приложений, использующие компьютерное зрение, быстро растёт; подобного рода приложения находят своё применение для анализа изображений, видео, медицинских снимков и даже для перемещения по Марсу. Совместно с увеличением потребности в подобного рода запросах развивается и сама библиотека.

OpenCV имеет продолжительную историю поддержки от корпорации Intel и относительно недавнюю от Willow Garage, которая финансирует новые разработки в сфере робототехнике и технологический инкубатор. Willow Garage большое внимание уделяет развитию гражданской робототехнике за счёт открытой разработки и поддержки развития аппаратной и программной инфраструктуры. Благодаря этой поддержке и сохранению связей с несколькими первыми разработчиками, библиотека стала довольно таки быстро развиваться и обновляться. Так же при наличии поддержки стремительно стало развиваться OpenCV сообщество, ускорился процесс оценки и интеграции новых разработок.

Одним из ключевых новых направлений развития в OpenCV является роботизированное восприятие. Сосредоточение происходит на 3D восприятии, а также на распознавании 2D+3D объектов, комбинируя типы для улучшения особенностей, используемые при обнаружении объектов, сегментации и распознавании. Роботизированное восприятие во многом зависит от 3D сканирования, поэтому ведутся работы по улучшению процесса калибровки камеры, исправлению и сопоставлению картинки с нескольких камер и комбинированию камеры и лазера.

Наравне с 3D сканированием объектов, роботам нужно будет распознавать 3D объекты и их 3D представления. Для того, чтобы это было возможно необходимо развивать некоторые масштабируемые методы, распознающие 2D+3D объекты. Процесс создания роботов включает в себя большинство областей компьютерного зрения и искусственного интеллекта, начиная от точного 3D реконструирования слежения, идентификации человека, распознавания объекта, сшивки изображений и заканчивая обучением, контролированием, планированием и принятием решений. Любая высокоуровневая задача, такая, как планирование, во многом облегчает, ускоряет и повышает точность восприятия глубины и распознавание. Именно этим областям в дальнейшем будет уделяться повышенное внимание либо за счёт поощрения открытого сообщества, либо за счёт использования более эффективных методов решения сложных проблем восприятия реального мира, распознавания и обучения.

При этом безусловно OpenCV не перестанет развиваться в других направлениях, от индексации изображений и видео в интернете до систем безопасности и анализа медицинских данных. В целом, дальнейшее развитие OpenCV будет зависеть от потребностей общества.

3. Исследование алгоритмов сегментации в OpenCV

В этой главе описываются одни из самых популярных алгоритмом сегментации изображений, реализованные в библиотеке компьютерного зрения OpenCV с открытым исходным кодом. А именно:

· алгоритм водораздела (WaterShed);

· алгоритм сегментации GrabCut;

· алгоритм сдвига среднего (MeanShift);

3.1 Алгоритм водораздела (WaterShed)

3.1.1 Основная идея алгоритма

Одним из наиболее популярных методов сегментации изображений является метод водораздела. В геодезии водоразделом называется линия поверхности, разделяющая бассейны двух рек.

Основная идея метода водораздела состоит в представлении полутонового изображения в виде топографической карты местности. Высота точки над нулевым уровнем будет равна значению ее яркости. При заполнении данной местности водой образуются бассейны. При постепенном увеличении количества воды происходит объединение бассейнов. Для того, чтобы два бассейна не слились, между ними строится дамба. В итоге, построенные дамбы будут образовывать границы водораздела, т. е. границы объектов (см. рис 3.1).

Рис. 3.1 - Процесс заполнения водой

Следует отметить, что алгоритм считает бассейнами даже самые маленькие и незначимые объекты, например, шум или несущественные колебания яркости. Поэтому применение алгоритма в классическом виде приводит к чрезмерной сегментации. Чтобы избежать этого, как правило, используют два подхода. Первый - введение порога глубины бассейна. Если глубина бассейна в момент слияния с другим бассейном меньше заданного порога, то граница водораздела не строится и бассейны сливаются в один. Второй подход получил название метода маркерного водораздела. В этом случае маркеры задают инициирующие бассейны [6]. Пользователь сам отмечает маркером один или несколько объектов и задний фон. В процессе работы этого алгоритма не создаются новые бассейны.

3.1.2 Программная реализация

Листинг 3.1

#include "stdafx.h"

#include <opencv2/core/utility.hpp>

#include "opencv2/pictureproc.hpp"

#include "opencv2/picturecodecs.hpp"

#include "opencv2/highgui.hpp"

#include <cstdio>

#include <iostream>

using namespace cv;

using namespace std;

Mat markers, picture;

Point prevPt(-1, -1);

static void onMouse(int event, int x, int y, int flags, void*)

{

if (x < 0 || x >= picture.cols || y < 0 || y >= picture.rows)

return;

if (event == EVENT_LBUTTONUP || !(flags & EVENT_FLAG_LBUTTON))

prevPt = Point(-1, -1);

else if (event == EVENT_LBUTTONDOWN)

prevPt = Point(x, y);

else if (event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON))

{

Point pt(x, y);

if (prevPt.x < 0)

prevPt = pt;

line(markers, prevPt, pt, Scalar::all(255), 5, 8, 0);

line(picture, prevPt, pt, Scalar::all(255), 5, 8, 0);

prevPt = pt;

imshow("image", picture);

}

}

int main(int argc, char** argv)

{

string filename = "C:\\Image.jpg";

Mat picture0 = imread(filename, 1), pictureGray;

if (picture0.empty())

{

cout << "Couldn'g open image " << filename;

return 0;

}

namedWindow("image", 1);

picture0.copyTo(picture);

cvtColor(picture, markers, COLOR_BGR2GRAY);

cvtColor(markers, pictureGray, COLOR_GRAY2BGR);

markers = Scalar::all(0);

imshow("image", picture);

setMouseCallback("image", onMouse, 0);

while(true)

{

int c = waitKey(0);

if ((char)c == 27)

break;

if ((char)c == 'r')

{

markers = Scalar::all(0);

picture0.copyTo(picture);

imshow("image", picture);

}

if ((char)c == 'w' || (char)c == ' ')

{

int i, j, compCount = 0;

vector<vector<Point> > contours;

vector<Vec4i> hierarchy;

findContours(markers, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);

if (contours.empty())

continue;

Mat markers(markers.size(), CV_32S);

markers = Scalar::all(0);

int idx = 0;

for (; idx >= 0; idx = hierarchy[idx][0], compCount++)

drawContours(markers, contours, idx, Scalar::all(compCount + 1), -1, 8, hierarchy, INT_MAX);

if (compCount == 0)

continue;

vector<Vec3b> colorTab;

for (i = 0; i < compCount; i++)

{

int b = theRNG().uniform(0, 255);

int g = theRNG().uniform(0, 255);

int r = theRNG().uniform(0, 255);

colorTab.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));

}

double t = (double)getTickCount();

watershed(picture0, markers);

t = (double)getTickCount() - t;

printf("execution time = %gms\n", t*1000. / getTickFrequency());

Mat watershed(markers.size(), CV_8UC3);

for (i = 0; i < markers.rows; i++)

for (j = 0; j < markers.cols; j++)

{

int index = markers.at<int>(i, j);

if (index == -1)

watershed.at<Vec3b>(i, j) = Vec3b(255, 255, 255);

else if (index <= 0 || index > compCount)

watershed.at<Vec3b>(i, j) = Vec3b(0, 0, 0);

else

watershed.at<Vec3b>(i, j) = colorTab[index - 1];

}

watershed = watershed*0.5 + pictureGray*0.5;

imshow("watershed transform", watershed);

}

}

return 0;

}

3.1.3 Результат работы алгоритма

Начнем с простых изображений с однотонным фоном и небольшим количеством объектов. На первом рисунке изображены четыре карты на темно-зеленом фоне. (см. рис. 3.2) Границы объектов вполне очевидны.

Рис. 3.2 - Оригинал изображения «Карты»

После того, как программа откроет изображение, так как мы использовали алгоритм маркерного водораздела, необходимо маркером отметить объекты и фон. (см. рис. 3.3)

Запускаем алгоритм и получаем результат метода водораздела. Алгоритм с высокой точностью определил границы объектов и фона. (см. рис. 3.4)

Однако, есть нюанс. Первая слева карта перекрывается второй, из-за этого правый верхний угол первой карты выделен так, словно он принадлежит второй карте. (см. рис. 3.5) Тот же нюанс виден и с двумя другими картами. Отсюда можно сделать вывод, что если объект на изображении перекрывается другим объектом или чем-то еще, то алгоритм WaterShed найдет границы, однако отметит как два разных объекта.

Рис. 3.3 - Маркировка объектов и фона

Рис. 3.4 - Результат сегментации №1

Возьмем изображение посложнее, с более разнообразной цветовой палитрой и произведем те же манипуляции. (см. рис. 3.6)

Несмотря на большее разнообразие цветов, в этом случае алгоритм водораздела также неплохо справился с задачей. (см. рис. 3.7) Повысить точность сегментации и избежать «потерянных перьев», как в данном случае, можно более точной маркировкой.

Рис. 3.5 - Вторая карта перекрывает первую

Рис. 3.6 - Маркировка объекта и фона

Рис. 3.7 - Результат сегментации №2

Усложним задачу еще больше и возьмем еще более пеструю картинку с бликами. (см. рис. 3.8) Повторим эксперимент.

Рис. 3.8 - Маркировка объектов

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

Рис. 3.9 - Результат сегментации №3

3.2 Алгоритм сегментации GrabCut

3.2.1 Основная идея алгоритма

Алгоритм GrabCut был разработан Владимиром Колмогоровым, Эндрю Блэйком и Карстеном Ротером. Алгоритм GrabCut - это интерактивное выделение объектов переднего плана изображения при помощи итерационного применения алгоритма разрезания графа (GraphCut). GraphCut - это алгоритм, который недавно приобрел популярность для использования в задачах сегментации в компьютерном зрении, и который де-факто стал эталонным алгоритмом интерактивной сегментации.

Алгоритм GrabCut является развитием GraphCut-а. Главной целью разработчиков алгоритма было сведение к минимуму взаимодействия алгоритма с пользователем, а именно они хотели сделать достаточным задание ограничивающего прямоугольника вокруг объекта для получения изначального приближения. Для этого они ввели итеративную схему сегментации. [7]

GrabCut - это итеративный алгоритм, который объединяет статистику и Graph Cut для выполнения детальной 2D-сегментации с очень ограниченным доступом, первоначально разработанным в Microsoft Research Cambridge.

Рабочий процесс для пользователя выглядит следующим образом: пользователь выбирает изображение, которое должно использоваться для выполнения сегментации, и рисует прямоугольник вокруг интересующего объекта, который должен быть сегментирован. Это все, что требуется алгоритмом GrabCut для выполнения сегментации. После этого пользователь может выполнить окончательное касание изображения, если это необходимо, или снова использовать изображение, выбрав новый прямоугольник.

Основные этапы алгоритма GrabCut заключаются в следующем:

1. Пользователь вводит три вещи: передний план, фон и неизвестную часть изображения, которая может быть либо передним, либо фоновым. Обычно это делается, выбирая прямоугольник вокруг интересующего объекта и отмечая область внутри этого прямоугольника как неизвестную. Пиксель за пределами этого прямоугольника будет отмечен как известный фон.

2. Компьютер создает начальную сегментацию изображения, где неизвестные пиксели помещаются в класс переднего плана, а все известные фоновые пиксели классифицируются как фон.

3. На переднем плане и в фоновом режиме моделируются модели гауссовых смесей (GMM) с использованием алгоритма кластеризации Орчард-Бумана.

4. Каждому пикселю на переднем плане назначается наиболее вероятный гауссовский компонент в GMM переднего плана. Тот же идентификатор процесса, что и пиксели в фоновом режиме, но с компонентами базовых GMM.

5. Новые GMM выбираются из наборов пикселей, которые были созданы в предыдущем шаге.

6. Создан граф, и GraphCut используется для поиска новой классификации пикселей переднего и заднего фона.

7. Повторяются пункты 4-6 до тех пор, пока классификация не сходится.

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

Рис. 3.10 - Дополнительные метки объекта

3.2.2 Программная реализация

Листинг 3.2

#include "stdafx.h"

#include <opencv2/core/utility.hpp>

#include "opencv2/imgproc.hpp"

#include "opencv2/imgcodecs.hpp"

#include "opencv2/highgui.hpp"

#include <cstdio>

#include <iostream>

using namespace cv;

using namespace std;

const Scalar RED = Scalar(0, 0, 255);

const Scalar PINK = Scalar(230, 130, 255);

const Scalar BLUE = Scalar(255, 0, 0);

const Scalar LIGHTBLUE = Scalar(255, 255, 160);

const Scalar GREEN = Scalar(0, 255, 0);

const int BGD_KEY = EVENT_FLAG_CTRLKEY;

const int FGD_KEY = EVENT_FLAG_SHIFTKEY;

static void getBinMask(const Mat& comMask, Mat& binMask)

{

if (comMask.empty() || comMask.type() != CV_8UC1)

CV_Error(Error::StsBadArg, "comMask is empty or has incorrect type (not CV_8UC1)");

if (binMask.empty() || binMask.rows != comMask.rows || binMask.cols != comMask.cols)

binMask.create(comMask.size(), CV_8UC1);

binMask = comMask & 1;

}

class GCApplication

{

public:

enum{ NOT_SET = 0, IN_PROCESS = 1, SET = 2 };

static const int radius = 2;

static const int thickness = -1;

void reset();

void setImageAndWinName(const Mat& _image, const string& _winName);

void showImage() const;

void mouseClick(int event, int x, int y, int flags, void* param);

int nextIter();

int getIterCount() const { return iterCount; }

private:

void setRectInMask();

void setLblsInMask(int flags, Point p, bool isPr);

const string* winName;

const Mat* image;

Mat mask;

Mat bgdModel, fgdModel;

uchar rectState, lblsState, prLblsState;

bool isInitialized;

Rect rect;

vector<Point> fgdPxls, bgdPxls, prFgdPxls, prBgdPxls;

int iterCount;

};

void GCApplication::reset()

{

if (!mask.empty())

mask.setTo(Scalar::all(GC_BGD));

bgdPxls.clear(); fgdPxls.clear();

prBgdPxls.clear(); prFgdPxls.clear();

isInitialized = false;

rectState = NOT_SET;

lblsState = NOT_SET;

prLblsState = NOT_SET;

iterCount = 0;

}

void GCApplication::setImageAndWinName(const Mat& _image, const string& _winName)

{

if (_image.empty() || _winName.empty())

return;

image = &_image;

winName = &_winName;

mask.create(image->size(), CV_8UC1);

reset();

}

void GCApplication::showImage() const

{

if (image->empty() || winName->empty())

return;

Mat res;

Mat binMask;

if (!isInitialized)

image->copyTo(res);

else

{

getBinMask(mask, binMask);

image->copyTo(res, binMask);

}

vector<Point>::const_iterator it;

for (it = bgdPxls.begin(); it != bgdPxls.end(); ++it)

circle(res, *it, radius, BLUE, thickness);

for (it = fgdPxls.begin(); it != fgdPxls.end(); ++it)

circle(res, *it, radius, RED, thickness);

for (it = prBgdPxls.begin(); it != prBgdPxls.end(); ++it)

circle(res, *it, radius, LIGHTBLUE, thickness);

for (it = prFgdPxls.begin(); it != prFgdPxls.end(); ++it)

circle(res, *it, radius, PINK, thickness);

if (rectState == IN_PROCESS || rectState == SET)

rectangle(res, Point(rect.x, rect.y), Point(rect.x + rect.width, rect.y + rect.height), GREEN, 2);

imshow(*winName, res);

}

void GCApplication::setRectInMask()

{

CV_Assert(!mask.empty());

mask.setTo(GC_BGD);

rect.x = max(0, rect.x);

rect.y = max(0, rect.y);

rect.width = min(rect.width, image->cols - rect.x);

rect.height = min(rect.height, image->rows - rect.y);

(mask(rect)).setTo(Scalar(GC_PR_FGD));

}

void GCApplication::setLblsInMask(int flags, Point p, bool isPr)

{

vector<Point> *bpxls, *fpxls;

uchar bvalue, fvalue;

if (!isPr)

{

bpxls = &bgdPxls;

fpxls = &fgdPxls;

bvalue = GC_BGD;

fvalue = GC_FGD;

}

else

{

bpxls = &prBgdPxls;

fpxls = &prFgdPxls;

bvalue = GC_PR_BGD;

fvalue = GC_PR_FGD;

}

if (flags & BGD_KEY)

{

bpxls->push_back(p);

circle(mask, p, radius, bvalue, thickness);

}

if (flags & FGD_KEY)

{

fpxls->push_back(p);

circle(mask, p, radius, fvalue, thickness);

}

}

void GCApplication::mouseClick(int event, int x, int y, int flags, void*)

{

// TODO add bad args check

switch (event)

{

case EVENT_LBUTTONDOWN: // set rect or GC_BGD(GC_FGD) labels

{

bool isb = (flags & BGD_KEY) != 0,

isf = (flags & FGD_KEY) != 0;

if (rectState == NOT_SET && !isb && !isf)

{

rectState = IN_PROCESS;

rect = Rect(x, y, 1, 1);

}

if ((isb || isf) && rectState == SET)

lblsState = IN_PROCESS;

}

break;

case EVENT_RBUTTONDOWN: // set GC_PR_BGD(GC_PR_FGD) labels

{

bool isb = (flags & BGD_KEY) != 0,

isf = (flags & FGD_KEY) != 0;

if ((isb || isf) && rectState == SET)

prLblsState = IN_PROCESS;

}

break;

case EVENT_LBUTTONUP:

if (rectState == IN_PROCESS)

{

rect = Rect(Point(rect.x, rect.y), Point(x, y));

rectState = SET;

setRectInMask();

CV_Assert(bgdPxls.empty() && fgdPxls.empty() && prBgdPxls.empty() && prFgdPxls.empty());

showImage();

}

if (lblsState == IN_PROCESS)

{

setLblsInMask(flags, Point(x, y), false);

lblsState = SET;

showImage();

}

break;

case EVENT_RBUTTONUP:

if (prLblsState == IN_PROCESS)

{

setLblsInMask(flags, Point(x, y), true);

prLblsState = SET;

showImage();

}

break;

case EVENT_MOUSEMOVE:

if (rectState == IN_PROCESS)

{

rect = Rect(Point(rect.x, rect.y), Point(x, y));

CV_Assert(bgdPxls.empty() && fgdPxls.empty() && prBgdPxls.empty() && prFgdPxls.empty());

showImage();

}

else if (lblsState == IN_PROCESS)

{

setLblsInMask(flags, Point(x, y), false);

showImage();

}

else if (prLblsState == IN_PROCESS)

{

setLblsInMask(flags, Point(x, y), true);

showImage();

}

break;

}

}

int GCApplication::nextIter()

{

if (isInitialized)

grabCut(*image, mask, rect, bgdModel, fgdModel, 1);

else

{

if (rectState != SET)

return iterCount;

if (lblsState == SET || prLblsState == SET)

grabCut(*image, mask, rect, bgdModel, fgdModel, 1, GC_INIT_WITH_MASK);

else

grabCut(*image, mask, rect, bgdModel, fgdModel, 1, GC_INIT_WITH_RECT);

isInitialized = true;

}

iterCount++;

bgdPxls.clear(); fgdPxls.clear();

prBgdPxls.clear(); prFgdPxls.clear();

return iterCount;

}

GCApplication gcapp;

static void on_mouse(int event, int x, int y, int flags, void* param)

{

gcapp.mouseClick(event, x, y, flags, param);

}

int main(int argc, char** argv)

{

string filename = "C:\\Image.jpg";

if (filename.empty())

{

cout << "\nDurn, empty filename" << endl;

return 1;

}

Mat image = imread(filename, 1);

if (image.empty())

{

cout << "\n Durn, couldn't read image filename " << filename << endl;

return 1;

}

const string winName = "GrabCut segmentation";

namedWindow(winName, WINDOW_AUTOSIZE);

setMouseCallback(winName, on_mouse, 0);

gcapp.setImageAndWinName(image, winName);

gcapp.showImage();

for (;;)

{

int c = waitKey(0);

switch ((char)c)

{

case '\x1b':

cout << "Exiting ..." << endl;

goto exit_main;

case 'r':

cout << endl;

gcapp.reset();

gcapp.showImage();

break;

case 'n':

int iterCount = gcapp.getIterCount();

cout << "<" << iterCount << "... ";

int newIterCount = gcapp.nextIter();

if (newIterCount > iterCount)

{

gcapp.showImage();

cout << iterCount << ">" << endl;

}

else

cout << "rect must be determined>" << endl;

break;

}

}

exit_main:

destroyWindow(winName);

return 0;

}

3.2.3 Результат работы алгоритма

Алгоритм GrabCut с высокой точностью отделил объект от фона. (см. рис. 3.11 и 3.12)

Рис. 3.11 - Оригинальное изображение

Рис. 3.12 - Результат сегментации алгоритма GrabCut

В алгоритме GrabCut взаимодействие с пользователем сведено к минимуму. Пользователю необходимо лишь выделить объект в прямоугольник. Однако, если объект совпадает по цвету с фоном или имеет расплывчатые границы, то алгоритму трудно определить границу объекта. Также следует отметить, что алгоритм предполагает, что прямоугольником выделяется лишь один объект. Поэтому, если попробовать выделить несколько объектов, то алгоритм не отделит часть фона между объектами. (см. рис. 3.13 и 3.14)

Рис. 3.13 - Оригинальное изображение

Рис. 3.14 - Результат сегментации

Поэтому алгоритм предусматривает возможность дополнительной маркировки переднего и заднего плана. (см. рис 3.15 и 3.16)

Рис. 3.15 - Маркировка переднего и заднего плана

Рис. 3.16 - Сегментация нескольких объектов

3.3 Алгоритм среднего сдвига (MeanShift)

3.3.1 Основная идея алгоритма

Наиболее универсальными являются алгоритмы сегментации, разбивающие изображение на однородные области, поскольку они не ориентированы на конкретную предметную область и находят широкое применение в компьютерном зрении при распознавании изображений. Одним из таких автоматических алгоритмов сегментации изображений является алгоритм MeanShift.

Метод среднего сдвига (MeanShift) первоначально был представлен в 1975 году Фукунагой и Хостетлером.

Алгоритм MeanShift относится к классу алгоритмов кластеризации, однако, в отличие от других алгоритмов кластеризации (k-means и др.), метод сдвига среднего не требует задания количества кластеров. MeanShift не является эвристическим алгоритмом и имеет математическое обоснование.

На вход подается изображение, представляющее из себя множество точек в двумерном пространстве. Предположим, что круговое окно сосредоточено на C и имеет радиус r в качестве ядра. Сдвиг среднего - это алгоритм восхождения к вершине, который включает итеративное перемещение этого ядра в область с более высокой плотностью до сходимости. Каждый сдвиг определяется средним вектором сдвига. Средний вектор сдвига всегда указывает на направление максимального увеличения плотности. На каждой итерации ядро смещается в центр. Метод вычисления этого среднего зависит от выбора ядра. В этом случае, если вместо плоского ядра выбирается гауссовское ядро, каждой точке сначала присваивается вес, который будет экспоненциально убывать по мере увеличения расстояния от центра ядра.

В OpenCV функция cvPyrMeanShiftFiltering реализует алгоритм, основанный на среднем сдвиге скопления цветов. Сегментация методом среднего сдвига находит пики распределения цвета в пространстве. Общим у алгоритмов сегментации и слежения является то, что они оба полагаются на способность среднего сдвига находить режимы (пики) распределения. Для множества многомерных точек (x, y, синий, зеленый, красный) алгоритм среднего сдвига может найти самую высокую плотность "сгустка" данных в данном пространстве при оконном сканировании над ним. Однако стоит обратить внимание на то, что пространственные переменные (x, y) могут сильно различаться в зависимости от величины цветового диапазона (синий, зеленый, красный). В данном случае необходимо иметь один радиус для пространственных переменных (spatialRadius) и ещё один для величины цвета (colorRadius). Средний сдвиг движущегося окна, все те точки которого сходятся в пике данных, становятся связанными или "принадлежащими" этому пику. Эта принадлежность, исходящая из самых плотных пиков, формирует сегментацию изображения. Сегментация на самом деле это градация пирамид (cvPyrUp(), cvPyrDown()), поэтому цветовое скопление на верхних уровнях пирамид (съежившиеся изображения) имеют границы, уточненные пирамидами нижнего уровня.

У cvPyrMeanShiftFiltering() имеется исходное src и конечное dst изображения. Оба изображения должны быть 8-битными, трехканальными цветными изображениями одинакового размера. spatialRadius и colorRadius определяют, как алгоритм среднего сдвига оперирует средними цвета и пространства для формирования сегментации. Для 640x480 изображения, алгоритм показывает хорошие результаты для значений spatialRadius = 2 и colorRadius = 40. Аргумент max_level определяет количество уровней пирамид, которые будут использованы для сегментации. Для 640x480 изображения max_level равен 2 или 3.

3.3.2 Программная реализация

Листинг 3.3

#include "stdafx.h"

#include <opencv2/core/utility.hpp>

#include "opencv2/imgproc.hpp"

#include "opencv2/imgcodecs.hpp"

#include "opencv2/highgui.hpp"

#include <cstdio>

#include <iostream>

using namespace cv;

using namespace std;

int main()

{

Mat picture = imread("C:\\Image.jpg", CV_LOAD_IMAGE_COLOR);

imshow("Original Image", picture);

Mat result;

int spatialRadius = 30;

int colorRadius = 50;

int pyramidLevels = 3;

pyrMeanShiftFiltering(picture, result, spatialRadius, colorRadius, pyramidLevels);

imshow("MeanShift", result);

waitKey(0);

}

3.3.3 Результат работы алгоритма

Алгоритм MeanShift полностью справляется со своей задачей - сегментацией изображения на области точек, близких по цвету. (см. рис. 3.17 - 3.20) В зависимости от выбранных параметров, результат сегментации одного и того же изображения может быть разным.

Рис. 3.17 - Оригинальное изображение

Рис. 3.18 - Результат сегментации MeanShift

Рис. 3.19 - Оригинальное изображение

Рис. 3.20 - Результат сегментации MeanShift

Заключение

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

В общем случае сегментацией изображения называют разбиение изображения на группы точек, обладающих общими признаками. Такими признаками могут быть цвет, яркость, текстура и т. д. На сегодняшний день уже существует множество алгоритмов сегментации. Каждый алгоритм основан на определенной математической модели. Но, до сих пор, ни один алгоритм не достиг требуемой точности результатов своей работы. Поэтому в настоящее время не снижается потребность в развитии и совершенствовании алгоритмов сегментации, их реализации в различных библиотеках, в частности, в OpenCV, одной из самых обширных библиотек компьютерного зрения, которую я использовал в своей работе.

В своем исследовании я рассмотрел лишь небольшую часть существующих алгоритмов. Использование разных алгоритмов дает разные результаты сегментации. Это происходит от того, что сегментация зависит от большого количества различных факторов, и ни один из алгоритмов не дает достаточно точной информации о границах и областях. Следовательно, алгоритм сегментации следует выбирать, исходя из конкретной задачи.

Если говорить о рассмотренных алгоритмах, то метод водораздела подойдет для изображений с простой текстурой, GrabCut хорошо справится с задачей отделения конкретного объекта от фона, а при использовании алгоритма MeanShift будут кластеризованы пиксели, близкие по цвету и координатам.

Размещено на Allbest.ru

...

Подобные документы

  • OpenCV – библиотека компьютерного зрения с открытым исходным кодом, предоставляющая набор типов данных, функций и численных алгоритмов для обработки изображений. Ее реализация на C/C++. Цели использования технологии. Основные модули библиотек 1-3.

    презентация [121,8 K], добавлен 14.12.2013

  • Метод главных компонент. Процесс распознавания. Ковариационная матрица, диагональная матрица собственных чисел. Использовании метрики Махаланобиса и Гауссовского распределения для оценки близости изображений. Входные вектора. Библиотека OpenCV.

    статья [22,1 K], добавлен 29.09.2008

  • Анализ основных аспектов технологии компьютерного зрения, необходимых для выполнения работы. Изучение характеристик библиотеки OpenCV, оценка актуальности работы по распознаванию жестов рук. Поэтапный отчет о работе над программным обеспечением.

    курсовая работа [669,9 K], добавлен 20.05.2017

  • Компьютерная графика и обработка изображений электронно-вычислительными машинами являются наиболее важным аспектом использования ЭВМ во всех сферах человеческой деятельности. Разработка "подсистемы линейной сегментации", описание алгоритма и логики.

    дипломная работа [1,1 M], добавлен 23.06.2008

  • Выбор методов обработки и сегментации изображений. Математические основы примененных фильтров. Гистограмма яркости изображения. Программная реализация комплексного метода обработки изображений. Тестирование разработанного программного обеспечения.

    курсовая работа [1,3 M], добавлен 18.01.2017

  • Анализ существующих проблем и обзор библиотеки обработки изображений и алгоритмов общего назначения OpenCV. Особенности разработки и детальный анализ требований к программе. Основная логика ее работы и реализация. Трекинг лица и объекта по цвету.

    дипломная работа [1,3 M], добавлен 26.06.2017

  • Современные системы текстурного анализа изображений. Примеры текстурной сегментации одноканальных изображений. Использование признаков, полученных на основе гистограммы яркостей второго порядка, для классификации спектрозональных аэрофотоснимков.

    реферат [573,5 K], добавлен 15.01.2017

  • Изучение и программная реализация в среде Matlab методов обработки, анализа, фильтрации, сегментации и улучшения качества рентгеновских медицинских изображений. Цифровые рентгенографические системы. Разработка статически обоснованных алгоритмов.

    курсовая работа [4,7 M], добавлен 20.01.2016

  • Анализ существующих алгоритмов фильтрации и сегментации изображений. Разработка алгоритмов обработки видеопотока на основе выделенных быстрых методов. Реализация принимающей части цепочки сервер-клиент, получающую видеопоток с мобильного устройства.

    дипломная работа [337,5 K], добавлен 24.01.2016

  • Обработка изображений на современных вычислительных устройствах. Устройство и представление различных форматов изображений. Исследование алгоритмов обработки изображений на базе различных архитектур. Сжатие изображений на основе сверточных нейросетей.

    дипломная работа [6,1 M], добавлен 03.06.2022

  • Сравнительная оценка существующих программ, повышающих разрешение изображений на языке Borland Delphi. Выбор оптимального инструментария для разработки логической схемы. Форма поиска файлов, преобразования изображений и реализации алгоритмов интерполяции.

    дипломная работа [3,0 M], добавлен 29.11.2011

  • Исследование вертикальных проекций яркости и размаха яркости. Программная реализация алгоритма автоматического анализа цифровых изображений номерных знаков с целью сегментации цифробуквенных символов. Разработка графического пользовательского интерфейса.

    дипломная работа [1,5 M], добавлен 12.04.2013

  • Применение различных методов компрессии изображений и анимации. Определение наиболее подходящего формата сжатия. Выбор кодеков при помощи программы RIOT. Применение дополнительных способов оптимизации с использование программ OptiPNG, PNGOUT и TweakPNG.

    лабораторная работа [1,5 M], добавлен 31.05.2013

  • Положения алгоритмов сжатия изображений. Классы приложений и изображений, критерии сравнения алгоритмов. Проблемы алгоритмов архивации с потерями. Конвейер операций, используемый в алгоритме JPEG. Характеристика фрактального и рекурсивного алгоритмов.

    реферат [242,9 K], добавлен 24.04.2015

  • Обнаружение деталей и их границ изображения. Применение ранговых алгоритмов. Использование алгоритмов адаптивного квантования мод в режиме пофрагментной обработки. Обобщенная линейная фильтрация изображений. Восстановление отсутствующих участков.

    курсовая работа [1,8 M], добавлен 17.06.2013

  • Основные понятия о представлении изображения. Определение величины порога с помощью гистограммы яркостей. Глобальная, локальная, адаптивная пороговая обработка. Метод дискриминантного критерия. Исследования на искусственных и предметных изображениях.

    дипломная работа [5,1 M], добавлен 23.12.2012

  • Анализ проблем, возникающих при совмещении изображений в корреляционно-экстремальных навигационных системах. Использование двумерного дискретного преобразования Фурье. Нахождение корреляционной функции радиолокационного и моделируемого изображений.

    дипломная работа [3,6 M], добавлен 07.07.2012

  • Основы программирования на языке VB.NET. Область применения трехмерных изображений. Форматы хранения пакетов инженерной графики. Преимущества трехмерного моделирования. Разработка программы по вращению трехмерных изображений на языках VB.NET и VRML.

    курсовая работа [195,1 K], добавлен 11.03.2013

  • Необходимость применения систем электронного документооборота. Выводы по ценам, функциональным возможностям, сегментации рынка. Схема обработки информации автоматизированной системой. Нормативно-справочная информация для системы, структура алгоритмов.

    дипломная работа [2,9 M], добавлен 24.06.2009

  • Задачи цифровой обработки изображений. Методы пороговой сегментации. Создание программы представления рисунка в виде матрицы и применения к нему пороговой обработки. Разработка интерфейса программы загрузки и фильтрации изображения с выбранным порогом.

    курсовая работа [2,0 M], добавлен 12.11.2012

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.