ЗдравствуйтеПомогите нубу приобщиться к мудрости
Начал вникать в машинное зрение вообще и 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, то в результате получим примерно тоже изображение, что выше - т.е. правильно ли я понимаю, что для получения доступа к контуру отдельной фигуры потребуются дальнейшие вычисления или я опять что-то не так делаю?