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

Nuzhny

Пользователи
  • Количество публикаций

    1 427
  • Зарегистрирован

  • Посещение

  • Days Won

    176

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

  1. Отвечу на последний вопрос темы - над первым надо ещё подумать. Быстрее так: void barrel_pincusion_dist(IplImage* img, double kx, double ky) { IplImage* mapx = cvCreateImage( cvGetSize(img), IPL_DEPTH_32F, 1 ); IplImage* mapy = cvCreateImage( cvGetSize(img), IPL_DEPTH_32F, 1 ); int w= img->width; int h= img->height; int Cx= w/2; int Cy= h/2; float* pbuf = (float*)mapx->imageData; for (int y = 0; y < h; y++) { int ty= y-Cy; for (int x = 0; x < w; x++) { int tx= x-Cx; int rt= tx*tx+ty*ty; *pbuf = (float)(tx*(1+kx*rt)+Cx); ++pbuf; } } pbuf = (float*)mapx->imageData; for (int y = 0;y < h; y++) { int ty= y-Cy; for (int x = 0; x < w; x++) { int tx= x-Cx; int rt= tx*tx+ty*ty; *pbuf = (float)(ty*(1+ky*rt)+Cy); ++pbuf; } } IplImage* temp = cvCloneImage(img); cvRemap( temp, img, mapx, mapy ); cvReleaseImage(&temp); cvReleaseImage(&mapx); cvReleaseImage(&mapy); }
  2. 1. Я в цикле прохожу по "сырым" данным изображения/матрицы. Или ищу в справке необходимые мне функции - очень часто всё уже реализовано. Какие производные тебе нужны? 2. Да, со скалярами через val работаю. А что не устраивает?
  3. Посмотри довольно тупую мою реализацию для твоего изображения: #include <list> #include <limits> #include <highgui.h> #include <cv.h> //////////////////////////////////////////////////////////////////////////// int main() { IplImage* img = cvLoadImage("f:\\test.bmp", 0); IplImage* img2 = cvCloneImage(img); cvShowImage("original", img2); // Немного доработаем исходное изображение для удобного писка контуров cvSubRS(img, cvScalar(255), img); cvDilate(img, img, 0, 1); cvErode(img, img, 0, 1); cvShowImage("img", img); // Ищем контуры CvMemStorage *storage = cvCreateMemStorage(0); CvContourScanner traverse = cvStartFindContours(img, storage, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE); // Контейнер для концевых точек std::list<CvPoint> points; size_t ccounter = 0; for (CvSeq* contour = cvFindNextContour(traverse); contour; contour = cvFindNextContour(traverse)) { // Совершено тупой и нерациональный поиск концевых точек size_t min1 = std::numeric_limits<size_t>::max(); size_t min2 = std::numeric_limits<size_t>::max(); CvPoint min_p1 = cvPoint(0, 0); CvPoint min_p2 = cvPoint(500, 500); for (int i = 0; i < contour->total; ++i) { CvPoint p1 = *(CvPoint*)cvGetSeqElem(contour, i); size_t near_count = 0; for (int j = 0; j < contour->total; ++j) { if (i != j) { CvPoint p2 = *(CvPoint*)cvGetSeqElem(contour, j); if (abs(p1.x - p2.x) < 5 && abs(p1.y - p2.y) < 5) ++near_count; } } if ((near_count < min1) && (abs(p1.x - min_p2.x) > 10 || abs(p1.y - min_p2.y) > 10)) { min1 = near_count; min_p1 = p1; } else if ((near_count < min2) && (abs(min_p1.x - p1.x) > 10 || abs(min_p1.y - p1.y) > 10)) { min2 = near_count; min_p2 = p1; } } points.push_back(min_p1); points.push_back(min_p2); printf("%u\n", ++ccounter); } cvEndFindContours(&traverse); cvReleaseMemStorage(&storage); // Соединяем ближайшие концевые точки прямыми for (std::list<CvPoint>::iterator it1 = points.begin(); it1 != points.end(); it1 = points.erase(it1)) { double min_dist = std::numeric_limits<double>::max(); std::list<CvPoint>::iterator it2 = it1; std::list<CvPoint>::iterator best_it = it1; ++best_it; for (++it2; it2 != points.end(); ++it2) { double dist = sqrt((double)((it1->x - it2->x) * (it1->x - it2->x) + (it1->y - it2->y) * (it1->y - it2->y))); if (dist < min_dist) { min_dist = dist; best_it = it2; } } cvLine(img2, *it1, *best_it, cvScalar(0)); points.erase(best_it); } cvShowImage("result", img2); cvWaitKey(); cvReleaseImage(&img2); cvReleaseImage(&img); cvDestroyAllWindows(); return 0; } //////////////////////////////////////////////////////////////////////////// Сравни картинки original и result. Это то, что тебе надо?
  4. Вроде как в последней OpenCV есть HOG как раз для детекции людей. Посмотри. С автонаведением камеры отдельный разовор, сильно зависит от выбраного тобой способа их поиска, скорости и качества поворотной камеры. Поэкспериментируй.
  5. GDAL + OpenCV

    Блин, я уже удалил проект, неохода заново пенастраивать пути и переименовывать либы. Я просто сделал так, как считал правильным - оно само и заработало.
  6. GDAL + OpenCV

    Чуть внимательней надо с памятью работать: int _tmain(int argc, _TCHAR* argv[]) { GDALAllRegister(); // загрузка GDAL //GDALDataset* r_image = (GDALDataset *)GDALOpen("gia_gr.jpg", GA_ReadOnly); // открытие изображения GRAYSCALE (1канал/8бит) GDALDataset* r_image = (GDALDataset *)GDALOpen("gia.jpg", GA_ReadOnly); // открытие изображения COLOR (3канала/8бит) <--- а вот с этим уже проблемы int channelsCount = r_image->GetRasterCount(); // количество каналов изображения int width = r_image->GetRasterXSize(); // ширина int height = r_image->GetRasterYSize(); // высота IplImage* result = cvCreateImage(cvSize(width, height), 8, channelsCount); byte *currentBuffer = (byte *)malloc(width * height * sizeof(byte)); // выделяем буфер для текущего канала for (int chan = 1; chan <= channelsCount; ++chan) // в GDAL каналы считаются с 1 !!! { GDALRasterBand *currentChannel = r_image->GetRasterBand(chan); // получаем канал // чтение данных канала в буфер currentBuffer auto err = currentChannel->RasterIO( GF_Read, // метод доступа к данным 0, // nXOff - смещение 0, // nYOff - смещение width, // nXSize height, // nYSize currentBuffer, // буфер width, // nBufXSize height, // nBufYSize GDT_Byte, // тип данных 0, // nPixelSpace 0 // nLineSpace ); // Запись данных канала в буфер byte* dest_buf = (byte*)result->imageData; byte* src_buf = currentBuffer; for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { // Последовательность каналов в GDAL R,G,B // поэтому приходится инвертировать в B,G,R int channelIndex = channelsCount - chan - 1; dest_buf[channelsCount * x + channelIndex] = *src_buf; ++src_buf; } dest_buf += result->widthStep; } } free(currentBuffer); cvShowImage("RESULT", result); cvWaitKey(); cvReleaseImage(&result); cvDestroyAllWindows(); return 0; } P.S. Я рефлекторно поубирал лишние выделения памяти, добавил освобождение. Глаза режет.
  7. Производительность OpenCV

    Для решения твоей задачи необходим профайлер. Попробуй, например, VTune. Им можно бесплатно и официально пользоваться месяц. Иначе все твои замеры страдают неточностью. В частности, QueryPerformanceCounter на многоядерной системе может выдавать "левые" результаты - это происходит при преключении рабочего потока по ядрам. Диспетчер задач тоже не показатель - особенно при работе с функцией Sleep.
  8. Смещение на -20 будет только лишь у левой верхней точки изображения. Само оно деформируется при этом, а нужен полноценный параллельный перенос. Об этом и пишется в начальном сообщении. Надо.
  9. У тебя это работает только потому, что изображение не повёрнуто - соответствующие элементы матрицы гомографии равны нулю. Запусти оригинальный пример и сразу увидишь разницу.
  10. Поразмышлял немного... Смещение надо производить немного по-другому: CvPoint2D64f dst_corners[4]; // Изменил тип точек ... dst_corners[i] = cvPoint2D64f(X, Y); // Изменил немного GetCorners ... // Ну и сам сдвиг усложнился cvmSet(homo, 0, 2, cvmGet(homo, 2, 2) * (dst_corners[0].x - 20)); cvmSet(homo, 0, 0, ((cvmGet(homo, 2, 0) * (double)loaded->width + cvmGet(homo, 2, 2)) * (dst_corners[1].x - 20) - cvmGet(homo, 0, 2)) / (double)loaded->width); cvmSet(homo, 0, 1, ((cvmGet(homo, 2, 1) * (double)loaded->height + cvmGet(homo, 2, 2)) * (dst_corners[3].x - 20) - cvmGet(homo, 0, 2)) / (double)loaded->height); Теперь мои мысли: 1. раз преобразование координаты X углов изображения зависит от трёх параметров матрицы гомографии (double X = (h[0] * x + h[1] * y + h[2]) * Z;), то и при сдвиге должны изменяться все три параметра. 2. Для трёх параметров нужна система из трёх уравнений. - В выражение из пункта 1 подставляем точку с координатами (0; 0), которая соответствует dst_corners[0] и вместо X подставляем X - 20 - находим h[2] - В выражение из пункта 1 подставляем точку с координатами (width; 0), которая соответствует dst_corners[1] и вместо X подставляем X - 20 - находим h[0] - В выражение из пункта 1 подставляем точку с координатами (0; height), которая соответствует dst_corners[3] и вместо X подставляем X - 20 - находим h[1] Вот и всё.
  11. Многопоточность и OpenCV

    1. Лучше выложить код, чтобы не гадать. 2. Как передаёшь изображения из потока захвата в поток отрисовки?
  12. Поиск картины на фотографии

    Посмотри на ASIFT, его исходники доступны. Пример его работы можно посмотреть здесь или здесь
  13. Многопоточность и OpenCV

    Это другой аспект многопоточности - здесь говорилось о потокобезопасности. 1. OpenMP, вроде, подключить можно. Во всяком случае в коде OpenCV есть максросы _OPENMP и USE_OPENMP. Надо их включить и перекомпилировать OpenCV. Попробуешь? 2. Судя по параметрам CMake, OpenCV может использовать Intel Threading Building Blocks - более удобный аналог OpenMP. Надо их поставить, переконфигурировать с помощью CMake OpenCV и перекомпилировать. 3. Можно самому использовать потоки (например из boost'а).
  14. Одноцветных - cvFloodFill. После делаешь изображение-маску и работаешь. Очень многие функции OpenCV принимают маску своим параметром.
  15. Эквализация гистограммы - это хорошо, но не всегда. Если изображение пожато, то в результате могут явно проявиться артефакты сжатия. Особенно это заметно на потоковых кодеках. В этом случае надо предварительно избавляться от артефактов и лишь после улучшать контрастность. Кроме контрастности, можно ещё улучшить резкость: найти лапласиан от яркости и сложить с исходным изображением.
  16. Попробуй просто вычесть из одного изображения другое и посмотреть результат.
  17. Я бы на твоём месте не заморачивался с GDI. OpenGL или DirectX по степени сложности освоения находятся на схожем уровне, но предоставляют в разы больше возможностей. Проверено не только моим опытом.
  18. Это же GDI+ Тормознутый и неприжившийся. Именно эту возможность можно использовать только из C#
  19. Как прикрутить OpenCV к билдеру?

    Я думаю, что твои линии надо как-нибудь сделать тонкими, а после уже заниматься их соединением. Можно придумать какую-нибудь хитрую мат. морфологию.
  20. На полках книжных магазинов не видел. Я сам заказывал напрямую у издательства с доставкой по почте.
  21. ConvexityDefects в C++ версии OpenCV

    В версии 2.1 нет.
  22. Дисторсии(подушка,бочка)

    cvInitUndistortMap + cvRemap
  23. В детали не вдавался, но cvMatchTemplate внутри себя вызывает функцию icvCrossCorr, которая использует cvDFT.
  24. Как прикрутить OpenCV к билдеру?

    Евклидово расстояние проще не вычислишь. А данные сохраняй так, как тебе удобней с ними будет после работать. Можешь вообще в вектора или матрицы перегнать. Я бы так и сделал.
×