compblinder 0 Жалоба Опубликовано December 27, 2012 ЗдравствуйтеПомогите нубу приобщиться к мудрости Начал вникать в машинное зрение вообще и OpenCV в частности с этого понельника, поэтому заранее извиняюсь за кривую терминологию и т.д. и т.п. Пишу программу под Андроид на Jawa, одной из функций приложения будет сравнение формы некоего объекта на получаемом изображении (с камеры, СД-карты не важно) с контурами в эталонной БД и определения 3-х наиболее сходных. Пока задание в процессе проработки, но скорее всего варианта будет два - на анализируемом фото пользователь пальцем или стилом сам обводит силуэт нужного объекта, используя определенный цвет пера - тут с точки зрения OpenCV все проще, поскольку сразу будет получать голый силуэт на чистом фоне (как я предполагаю на данный момент) для дальнейшей обработки. Второй вариант (наверное придется использовать для сложных форм и точного сравнения) - пользователь будет выделять объект в графическом редакторе все тем же определенным цветом, сохранять изображение и уже в таком виде передавать приложению. В этом случае я для надежности решил действовать тупо в лоб - брать изображение, очищать все пиксели имеющии отличный от заданного цвет и уже полученный голый силуэт переводить в серый, инвертировать и применять findContour(). И вот уже второй день головой в монитор бьюсь с этой фильтрацией по цвету. Вот мой код: public void GetContour(Bitmap bt) { Mat matproc = new Mat(); Mat matproc1 = new Mat(); //bt = bt.copy(Bitmap.Config.ARGB_8888, true); Utils.bitmapToMat(bt,matproc); Utils.bitmapToMat(bt,matproc1); Log.e(TAG, "0"); /*for(int i=0;i<matproc.height();i++){ for(int j=0;j<matproc.width();j++){ if (!(matproc.get(i, j)[0] == 0)&&(matproc.get(i, j)[1] == 0)&&(matproc.get(i, j)[2] > 192))//double y = 0.3 * matproc.get(i, j)[0] + 0.59 * matproc.get(i, j)[1] + 0.11 * matproc.get(i, j)[2]; matproc.put(i, j, new double[]{0, 0, 0}); }*/ Imgproc.cvtColor(matproc1, matproc, Imgproc.COLOR_BGR2HSV,0); Core.inRange(matproc, new Scalar(0, 0, 255), new Scalar(5, 5, 255), matproc1); //Imgproc.cvtColor(matproc1, matproc, Imgproc.COLOR_GRAY2BGR, 0); //Imgproc.cvtColor(matproc, matproc1, Imgproc.COLOR_BGR2RGBA, 0); //Bitmap bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888); currentImage1 = Bitmap.createBitmap(matproc1.cols(), matproc1.rows(), Bitmap.Config.ARGB_8888); Utils.matToBitmap(matproc1,currentImage1); im1.setImageBitmap(currentImage1); } а вот что приходит приложению и что получается на выходе: (не разобрался я с хостингом, если кому интересно картинка в файле прикреплена) справа изображение на экране исходного файла - файл я создал в Paint, несколько фигур нарисовал пером красного цвета (в Paint обозначалось как 255,0,0) и две фигуры для теста нарисовал зеленым и синим пером, после чего сохранил его в формате JPG. Андроид файл открывает стандартными средствами - через битовый поток считывает его в bitmap. Этот самый битмап соотвественно передается в функцию GetContour, которая его преобразует в матрицу, пропускает через inRange и выводит на левый контрол. Я наверное не понимаю чего-то очень очевидного, но почему любые комбинации цветов в inRange в результате дают либо объекты всех цветов либо черный фон и никогда не выводят исключительно красные фигуры? Второй вопрос в догонку: если закрыть глаза на неработающую фильтрацию и пропустить матрицу дальше, через стандартные сглаживания, инверсии, пороговое преобразование, cvCanny и наконец findContour, а потом вывести контур с наименьшей площадью через drawContour, то в результате получим примерно тоже изображение, что выше - т.е. правильно ли я понимаю, что для получения доступа к контуру отдельной фигуры потребуются дальнейшие вычисления или я опять что-то не так делаю? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано December 27, 2012 Так у Вас же в HSV все перед фильтрацией переводится. А фильтровать Вы вроде как собирались по R,G,B компонентам. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
compblinder 0 Жалоба Опубликовано December 28, 2012 Так у Вас же в HSV все перед фильтрацией переводится. А фильтровать Вы вроде как собирались по R,G,B компонентам. спасибо за внимание дело в том, чтог если в HSV не перводить вообще постоянно черный фон inRange по умолчанию работает только с HSV? Раз уж до меня гуру снизошел, то хотел бы уточнить по вопросу с контурами - если мы на вход функции findContours подаем матрицу некоего изображения на котором имеется набот идеальных фигур (круг, квадрат, прямоугольник) - у всех толщина линий 1 пиксель, никто ни с кем не пересекается, все находятся на нектором расстоянии друг от друга. Что будет представлять из себя контур номер Х полученный из этой функции? Отдельно взятую фигуру или это может быть скажем круг и ближайшая к нему сторона квадрата слева/треугольника справа? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано December 28, 2012 По поводу InRange. Проведите эксперимент возьмите маленькое изображение, скажем 8 на 8 точек, выведите его в консоль при помощи cout << Img. Посмотрите чему равны значения в матрице. InRange работает с матрицами и ничего не знает об их формате, следовательно что то у Вас со значениями элементов не то. Проблемы с тонкими контурами могут возникать при сжатии изображений методами сжатия с потерями, например JPG (они размываются или просто исчезают). Сохраните картинку из paint в png, tiff или bmp формате. Что касается контуров, то для того случая который Вы описали получите набор отдельных контуров для каждой фигуры (по одному (внешний) или по два (внутренний и внешний), в зависимости от установленных ключей). Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах