Перейти к содержимому
Compvision.ru

Smorodov

Главные администраторы
  • Количество публикаций

    3 873
  • Зарегистрирован

  • Посещение

  • Days Won

    346

Все публикации пользователя Smorodov

  1. Посмотрел видео, для снега как то стремно, поддержу что не нужно добавлять это в основную ветку, по крайней мере пока с параметрами не будет определенности.
  2. Думается это уменьшенное, но не очень сильно. Уменьшать можно до тех пор, пока все объекты которые нужно детектировать различимы. А пропускать кадры, да еще один хороший способ снизить нагрузку на железо.
  3. Возможно, для ускорения поиска, изображение нужно уменьшить раза в 4, и шаблон также, точность поиска это уменьшить не должно, а искать будет намного быстрее. Затем просто пересчитать координаты в исходный масштаб.
  4. Да, нейронка, в данном случае как из пушки по воробьям, если бы вы изначально подробно описали задачу, то можно было бы найти решение быстрее. А так да, Nuzhny прав,поиск по шаблону скорее всего будет работать здесь оптимально см. http://docs.opencv.org/2.4/doc/tutorials/imgproc/histograms/template_matching/template_matching.html Если нужно распознавать что заэлемент, а не искать место расположения элемента, тогда можно обучить маленькую трехслойную нейронку..
  5. Мне кажется это и есть трекер, На сколько я понимаю, этот GMPHD должен делать примерно то же что и фильтр Кальмана с венгерским алгоритмом.
  6. Tут похоже что то близкое: https://github.com/orobix/retina-unet если переучить.
  7. ASM/AAM в OpenCV

    В OpenCV встроенных нет, посмотрите здесь: https://github.com/TadasBaltrusaitis/OpenFace
  8. Я как то запускал исходники этого метода, на МАТЛАБ по моему, что то там далеко от реалтайма то было, насколько помню.
  9. Как сравнить качество изображений

    Ну так PSNR используют обычно: http://docs.opencv.org/2.4/doc/tutorials/gpu/gpu-basics-similarity/gpu-basics-similarity.html
  10. Похоже на это: и это, судя по картинками в конце pdf-ки это именно оно и есть. http://www.robots.ox.ac.uk/ActiveVision/Publications/benfold_reid_cvpr2011/benfold_reid_cvpr2011.html
  11. Оптический поток

    Если вы знаете где точка находилась на предыдущем кадре, знаете оптический поток для этой точки, то координаты точки на текущем кадре будут равны координатам точки на предыдущем кадре плюс оптический поток в этой точке.
  12. Оптический поток

    Матрицу err не использовал, а получаете ответ на вопрос: где будут заданные точки текущего кадра на следующем кадре? Да возьмите пример из стандартных примеров OpenCV там все понятно.
  13. Оптический поток

    Ну возьмите датасет и сравните, то что должно получиться (ground truth) с тем что у вас получается. Хотя бы здесь: http://sintel.is.tue.mpg.de/
  14. Моя лекция по Фурье и Хаару, и реализация фильтра на основе вейвлет-преобразования. Если найдете ошибки, напишите, буду благодарен. Wavelets.cpp Wavelets.pdf Результат разложения: Результат фильтрации (границы отрисованы четко,а монотонные области грубо): Еще можно посмотреть здесь: Вейвлеты в компьютерной графике Фракталы близкая тема: http://habrahabr.ru/blogs/programming/135344/ Картинки оттуда понравились: Соорудил на OpenCV: Картинка с камеры Исходник Hilbert.cpp PS: На квадратном изображении (размер задается параметром size) поместится вся кривая. Это, кстати одна цельная ломаная линия.
  15. Просто инициализация переменных, привычка.
  16. Здравствуйте, ну это вы вероятно форумом ошиблись. Это больше по теме здесь: https://ru.stackoverflow.com/ .
  17. Есть еще "MS-Celeb-1M Dataset" но не помню есть там метки обозначающие персону или нет. Вообще да, CASIA довольно грязный и неравномерный датасет, строил гистограмму получается что то похожее на экспоненту. То есть одних фоток во много раз больше чем других. UPD: глянул, вроде должны быть метки: https://msceleb.github.io/celeb1m/1m
  18. Я как-то занимался чем то подобным, из готовых БД скорее https://support.hdfgroup.org/HDF5/ подходит, а поиск соседей делать ручками. Но в конце остановился на простой загрузке векторов из файла в память, в моем случае этого вполне достаточно было, ну и поиск OpenCV-шным kNN.
  19. Да со сферой то ничего сложного, для каждого лица есть 128-мерный вектор, длина которого равна единице. Для того чтобы сравнить два вектора, можно найти угол между ними, ну или косинус угла. Так как векторы нормированные, то косинус угла будет равен скалярному произведению. Вот косинус и будет определять насколько похожи лица с точки зрения OpenFace. Естественно при добавлении новых данных качество поиска будет падать. То же верно и для человеческого восприятия, среди 10000 человек, всегда найдутся похожие, которых вам будет трудно различить, в случае нескольких человек, вы просто запоминаете отличия одного от другого, создавая более настроенную на этих людей систему признаков. В случае большого количества необходимо использовать более общие, соответственно менее точные метрики. К тому же SVM плохо доучивается, да, есть разные извращения по этому поводу, но широкого применения я почему то не вижу. То есть, добавил человека, переучивай SVM. Можно еще использовать kNN если человек при внесении в базе делает несколько фотографий, точность такой классификации должна быть повыше простого сравнения расстояний или углов с единственной фотографией в базе.
  20. Предлагаю поразмыслить на досуге над выводом русских букв и произвольных шрифтов. Привожу ниже код, использующий библиотеку freetype, но результат, надо сказать не очень радует. В первую очередь огорчает прорисовка контуров средствами opencv. Если кто решил вопрос человеческой отрисовки шрифтов, прошу поделиться опытом Вот еще полезная ссылка в тему: http://www.codeproject.com/KB/GDI/hersheyfont.aspx // OpenCVFont.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "opencv2/opencv.hpp" #include <ft2build.h> #include FT_FREETYPE_H FT_Library library; FT_Face face; /* handle to face object */ using namespace cv; // all the new API is put into "cv" namespace. Export its content using namespace std; typedef vector<Point> cont; vector<cont> contours; vector<Vec4i> hierarchy; //---------------------------------------------------------- void cubic_bezier(cont& points, const Point2f & from, const Point2f & cp1, const Point2f & cp2, const Point2f & to, int curveResolution ) { points.push_back(Point2f(from.x,from.y)); if (points.size() > 0) { float x0 = points[points.size()-1].x; float y0 = points[points.size()-1].y; float ax, bx, cx; float ay, by, cy; float t, t2, t3; float x, y; // polynomial coefficients cx = 3.0f * (cp1.x - x0); bx = 3.0f * (cp2.x - cp1.x) - cx; ax = to.x - x0 - cx - bx; cy = 3.0f * (cp1.y - y0); by = 3.0f * (cp2.y - cp1.y) - cy; ay = to.y - y0 - cy - by; for (int i = 0; i < curveResolution; i++) { t = (float)i / (float)(curveResolution-1); t2 = t * t; t3 = t2 * t; x = (ax * t3) + (bx * t2) + (cx * t) + x0; y = (ay * t3) + (by * t2) + (cy * t) + y0; points.push_back(Point(x,y)); } } } //---------------------------------------------------------- void quad_bezier(cont& points, float x1, float y1, float x2, float y2, float x3, float y3, int curveResolution) { points.push_back(Point2f(x1,y1)); for(int i=0; i <= curveResolution; i++) { double t = (double)i / (double)(curveResolution); double a = (1.0 - t)*(1.0 - t); double b = 2.0 * t * (1.0 - t); double c = t*t; double x = a * x1 + b * x2 + c * x3; double y = a * y1 + b * y2 + c * y3; points.push_back(Point(x, y)); } } //--------------------------------------------------------------------- static void makeContoursForCharacter(vector<cont> &result,FT_Face &face) { result.clear(); cont Cont; int nContours = face->glyph->outline.n_contours; int startPos = 0; char * tags = face->glyph->outline.tags; FT_Vector * vec = face->glyph->outline.points; for(int k = 0; k < nContours; k++) { Cont.clear(); if( k > 0 ) { startPos = face->glyph->outline.contours[k-1]+1; } int endPos = face->glyph->outline.contours[k]+1; Point2f lastPoint; for(int j = startPos; j < endPos; j++) { if( FT_CURVE_TAG(tags[j]) == FT_CURVE_TAG_ON ) { lastPoint.x=(float)vec[j].x; lastPoint.y=(float)-vec[j].y; Cont.push_back(Point(lastPoint.x, lastPoint.y)); } else { if( FT_CURVE_TAG(tags[j]) == FT_CURVE_TAG_CUBIC ) { int prevPoint = j-1; if( j == 0) { prevPoint = endPos-1; } int nextIndex = j+1; if( nextIndex >= endPos) { nextIndex = startPos; } Point2f nextPoint( (float)vec[nextIndex].x, -(float)vec[nextIndex].y ); //we need two control points to draw a cubic bezier bool lastPointCubic = ( FT_CURVE_TAG(tags[prevPoint]) != FT_CURVE_TAG_ON ) && ( FT_CURVE_TAG(tags[prevPoint]) == FT_CURVE_TAG_CUBIC); if( lastPointCubic ) { Point2f controlPoint1((float)vec[prevPoint].x, (float)-vec[prevPoint].y); Point2f controlPoint2((float)vec[j].x, (float)-vec[j].y); Point2f nextPoint((float) vec[nextIndex].x, -(float) vec[nextIndex].y); cubic_bezier(Cont, lastPoint, controlPoint1, controlPoint2, nextPoint, 8); } } else { Point2f conicPoint( (float)vec[j].x, -(float)vec[j].y ); //If the first point is connic and the last point is connic then we need to create a virutal point which acts as a wrap around if( j == startPos ) { bool prevIsConnic = ( FT_CURVE_TAG( tags[endPos-1] ) != FT_CURVE_TAG_ON ) && ( FT_CURVE_TAG( tags[endPos-1]) != FT_CURVE_TAG_CUBIC ); if( prevIsConnic ) { Point2f lastConnic((float)vec[endPos - 1].x, (float)-vec[endPos - 1].y); lastPoint.x = (conicPoint.x + lastConnic.y) / 2; lastPoint.y = (conicPoint.x + lastConnic.y) / 2; } } //bool doubleConic = false; int nextIndex = j+1; if( nextIndex >= endPos) { nextIndex = startPos; } Point2f nextPoint( (float)vec[nextIndex].x, -(float)vec[nextIndex].y ); bool nextIsConnic = ( FT_CURVE_TAG( tags[nextIndex] ) != FT_CURVE_TAG_ON ) && ( FT_CURVE_TAG( tags[nextIndex]) != FT_CURVE_TAG_CUBIC ); //create a 'virtual on point' if we have two connic points if( nextIsConnic ) { nextPoint.x = (conicPoint.x + nextPoint.x) / 2; nextPoint.y = (conicPoint.y + nextPoint.y) / 2; } quad_bezier(Cont, lastPoint.x, lastPoint.y, conicPoint.x, conicPoint.y, nextPoint.x, nextPoint.y, 8); if( nextIsConnic ) { lastPoint = nextPoint; } } } //end for } result.push_back(Cont); } } //----------------------------------------------------------------------- void PrintString(Mat& img,std::wstring str,int x,int y) { FT_Bool use_kerning=0; FT_UInt previous=0; use_kerning = FT_HAS_KERNING( face ); float posx=0; for(int k=0;k<str.length();k++) { int glyph_index = FT_Get_Char_Index( face, str.c_str()[k] ); FT_GlyphSlot slot = face->glyph; /* a small shortcut */ float dx=slot->advance.x/64; FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); makeContoursForCharacter(contours,face); if ( use_kerning && previous && glyph_index ) { FT_Vector delta; FT_Get_Kerning( face, previous, glyph_index, FT_KERNING_DEFAULT, &delta ); posx += (delta.x/64); } for(int i=0;i<contours.size();i++) { for(int j=0;j<contours[i].size();j++) { contours[i][j].x=(float)contours[i][j].x/64.0; contours[i][j].y=(float)contours[i][j].y/64.0; } } posx+=(dx); drawContours(img,contours,-1, Scalar(255,255,255), -1,CV_AA,noArray(),INT_MAX,cv::Point(posx+x,y)); contours.clear(); previous = glyph_index; } } //----------------------------------------------------------------------- int _tmain(int argc, _TCHAR* argv[]) { FT_Init_FreeType( &library ); FT_New_Face( library,"arial.ttf",0,&face ); FT_Set_Pixel_Sizes(face,40,0); FT_Select_Charmap(face, FT_ENCODING_UNICODE); Mat img(480,640,CV_8UC3); PrintString(img,L"Привет!",100,100); // http://freetype.org/freetype2/docs/reference/ft2-outline_processing.html#FT_Outline //printf("%d",x); cv::imshow("win",img); cv::waitKey(0); //CvPoint2D32f return 0; }
  21. К сожалению актуален.
  22. Так то так, но это если пространство правильно деформировано и имеет правильную размерность, тогда лица каждого человека будут формировать гиперсферы одинакового радиуса. Но вот это как раз и есть сферический конь в вакууме, такое редко бывает на практике. Обычно получется так что точки для одного человека ложатся в виде N-мерной гиперколбасы и гиперколбасы эти переплетены между собой узлами. Так вот, чтобы понять где чье лицо нужно создать границы (не сферические), чтобы классификатор мог отличить где кто. Вот при обучении SVM и обучается классифицировать кто какой гиперколбасе принадлежит. А вообще, насколько я помню, OpenFace выдает вектор на 128-мерной гиперсфере радиуса 1, и можно измерять углы между векторами, чтобы узнать кто на кого похож. Есть еще t-sne, которые могут выкладывать гиперпространство на плоскости или в 3-D.
  23. svm.predict возвращает int, вместо float.

    Не ну есть конечно метод, но он "через назад". Можно обучить по бинарному SVM классификатору на каждый символ. Дальше думаю понятно.
×